diff options
author | Christian Heimes <christian@cheimes.de> | 2007-11-27 10:40:20 (GMT) |
---|---|---|
committer | Christian Heimes <christian@cheimes.de> | 2007-11-27 10:40:20 (GMT) |
commit | ff737954f3ee3005236133fc51b55a508b11aa06 (patch) | |
tree | b65ae9e39e774bd73674b5088e549d09a7bfd7d6 /Objects/classobject.c | |
parent | 0d3fb8a944a810f421377d5823cbc006700b3c1d (diff) | |
download | cpython-ff737954f3ee3005236133fc51b55a508b11aa06.zip cpython-ff737954f3ee3005236133fc51b55a508b11aa06.tar.gz cpython-ff737954f3ee3005236133fc51b55a508b11aa06.tar.bz2 |
Removed the API to create unbound methods and simplified the API for bound methods. The signature is PyMethod_New(func, instance).
Also removed im_class and renamed im_self to __self__ and im_func to __func__. im_class can be substituted with method.__self__.__class__.
I've also updated some parts of the documenation.
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r-- | Objects/classobject.c | 171 |
1 files changed, 36 insertions, 135 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c index 2db898a..5362fbc 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -26,33 +26,25 @@ PyMethod_Self(PyObject *im) return ((PyMethodObject *)im)->im_self; } -PyObject * -PyMethod_Class(PyObject *im) -{ - if (!PyMethod_Check(im)) { - PyErr_BadInternalCall(); - return NULL; - } - return ((PyMethodObject *)im)->im_class; -} - - -/* Method objects are used for two purposes: - (a) as bound instance methods (returned by instancename.methodname) - (b) as unbound methods (returned by ClassName.methodname) - In case (b), im_self is NULL +/* Method objects are used for bound instance methods returned by + instancename.methodname. ClassName.methodname returns an ordinary + function. */ static PyMethodObject *free_list; PyObject * -PyMethod_New(PyObject *func, PyObject *self, PyObject *klass) +PyMethod_New(PyObject *func, PyObject *self) { register PyMethodObject *im; if (!PyCallable_Check(func)) { PyErr_BadInternalCall(); return NULL; } + if (self == NULL) { + PyErr_BadInternalCall(); + return NULL; + } im = free_list; if (im != NULL) { free_list = (PyMethodObject *)(im->im_self); @@ -68,25 +60,21 @@ PyMethod_New(PyObject *func, PyObject *self, PyObject *klass) im->im_func = func; Py_XINCREF(self); im->im_self = self; - Py_XINCREF(klass); - im->im_class = klass; _PyObject_GC_TRACK(im); return (PyObject *)im; } /* Descriptors for PyMethod attributes */ -/* im_class, im_func and im_self are stored in the PyMethod object */ +/* im_func and im_self are stored in the PyMethod object */ #define OFF(x) offsetof(PyMethodObject, x) static PyMemberDef method_memberlist[] = { - {"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED, - "the class associated with a method"}, - {"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED, + {"__func__", T_OBJECT, OFF(im_func), READONLY|RESTRICTED, "the function (or other callable) implementing a method"}, - {"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED, - "the instance to which a method is bound; None for unbound methods"}, + {"__self__", T_OBJECT, OFF(im_self), READONLY|RESTRICTED, + "the instance to which a method is bound"}, {NULL} /* Sentinel */ }; @@ -141,7 +129,7 @@ method_getattro(PyObject *obj, PyObject *name) } PyDoc_STRVAR(method_doc, -"method(function, instance, class)\n\ +"method(function, instance)\n\ \n\ Create an instance method object."); @@ -150,27 +138,24 @@ method_new(PyTypeObject* type, PyObject* args, PyObject *kw) { PyObject *func; PyObject *self; - PyObject *classObj = NULL; if (!_PyArg_NoKeywords("instancemethod", kw)) return NULL; if (!PyArg_UnpackTuple(args, "method", 2, 3, - &func, &self, &classObj)) + &func, &self)) return NULL; if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "first argument must be callable"); return NULL; } - if (self == Py_None) - self = NULL; - if (self == NULL && classObj == NULL) { + if (self == NULL || self == Py_None) { PyErr_SetString(PyExc_TypeError, - "unbound methods must have non-NULL im_class"); + "self must not be None"); return NULL; } - return PyMethod_New(func, self, classObj); + return PyMethod_New(func, self); } static void @@ -181,7 +166,6 @@ method_dealloc(register PyMethodObject *im) PyObject_ClearWeakRefs((PyObject *)im); Py_DECREF(im->im_func); Py_XDECREF(im->im_self); - Py_XDECREF(im->im_class); im->im_self = (PyObject *)free_list; free_list = im; } @@ -225,10 +209,15 @@ method_repr(PyMethodObject *a) { PyObject *self = a->im_self; PyObject *func = a->im_func; - PyObject *klass = a->im_class; - PyObject *funcname = NULL, *klassname = NULL, *result = NULL; + PyObject *klass = (PyObject*)Py_Type(self); + PyObject *funcname = NULL ,*klassname = NULL, *result = NULL; char *defname = "?"; + if (self == NULL) { + PyErr_BadInternalCall(); + return NULL; + } + funcname = PyObject_GetAttrString(func, "__name__"); if (funcname == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) @@ -239,6 +228,7 @@ method_repr(PyMethodObject *a) Py_DECREF(funcname); funcname = NULL; } + if (klass == NULL) klassname = NULL; else { @@ -253,16 +243,12 @@ method_repr(PyMethodObject *a) klassname = NULL; } } - if (self == NULL) - result = PyUnicode_FromFormat("<unbound method %V.%V>", - klassname, defname, - funcname, defname); - else { - /* XXX Shouldn't use repr()/%R here! */ - result = PyUnicode_FromFormat("<bound method %V.%V of %R>", - klassname, defname, - funcname, defname, self); - } + + /* XXX Shouldn't use repr()/%R here! */ + result = PyUnicode_FromFormat("<bound method %V.%V of %R>", + klassname, defname, + funcname, defname, self); + Py_XDECREF(funcname); Py_XDECREF(klassname); return result; @@ -292,92 +278,19 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg) { Py_VISIT(im->im_func); Py_VISIT(im->im_self); - Py_VISIT(im->im_class); return 0; } -static void -getclassname(PyObject *klass, char *buf, int bufsize) -{ - PyObject *name; - - assert(bufsize > 1); - strcpy(buf, "?"); /* Default outcome */ - if (klass == NULL) - return; - name = PyObject_GetAttrString(klass, "__name__"); - if (name == NULL) { - /* This function cannot return an exception */ - PyErr_Clear(); - return; - } - if (PyUnicode_Check(name)) { - strncpy(buf, PyUnicode_AsString(name), bufsize); - buf[bufsize-1] = '\0'; - } - Py_DECREF(name); -} - -static void -getinstclassname(PyObject *inst, char *buf, int bufsize) -{ - PyObject *klass; - - if (inst == NULL) { - assert(bufsize > 0 && (size_t)bufsize > strlen("nothing")); - strcpy(buf, "nothing"); - return; - } - - klass = PyObject_GetAttrString(inst, "__class__"); - if (klass == NULL) { - /* This function cannot return an exception */ - PyErr_Clear(); - klass = (PyObject *)(inst->ob_type); - Py_INCREF(klass); - } - getclassname(klass, buf, bufsize); - Py_XDECREF(klass); -} - static PyObject * method_call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *self = PyMethod_GET_SELF(func); - PyObject *klass = PyMethod_GET_CLASS(func); PyObject *result; func = PyMethod_GET_FUNCTION(func); if (self == NULL) { - /* Unbound methods must be called with an instance of - the class (or a derived class) as first argument */ - int ok; - if (PyTuple_Size(arg) >= 1) - self = PyTuple_GET_ITEM(arg, 0); - if (self == NULL) - ok = 0; - else { - ok = PyObject_IsInstance(self, klass); - if (ok < 0) - return NULL; - } - if (!ok) { - char clsbuf[256]; - char instbuf[256]; - getclassname(klass, clsbuf, sizeof(clsbuf)); - getinstclassname(self, instbuf, sizeof(instbuf)); - PyErr_Format(PyExc_TypeError, - "unbound method %s%s must be called with " - "%s instance as first argument " - "(got %s%s instead)", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - clsbuf, - instbuf, - self == NULL ? "" : " instance"); - return NULL; - } - Py_INCREF(arg); + PyErr_BadInternalCall(); + return NULL; } else { Py_ssize_t argcount = PyTuple_Size(arg); @@ -402,27 +315,15 @@ method_call(PyObject *func, PyObject *arg, PyObject *kw) static PyObject * method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls) { - /* Don't rebind an already bound method, or an unbound method - of a class that's not a base class of cls. */ - + /* Don't rebind an already bound method of a class that's not a base + class of cls. */ if (PyMethod_GET_SELF(meth) != NULL) { /* Already bound */ Py_INCREF(meth); return meth; } - /* No, it is an unbound method */ - if (PyMethod_GET_CLASS(meth) != NULL && cls != NULL) { - /* Do subclass test. If it fails, return meth unchanged. */ - int ok = PyObject_IsSubclass(cls, PyMethod_GET_CLASS(meth)); - if (ok < 0) - return NULL; - if (!ok) { - Py_INCREF(meth); - return meth; - } - } /* Bind it to obj */ - return PyMethod_New(PyMethod_GET_FUNCTION(meth), obj, cls); + return PyMethod_New(PyMethod_GET_FUNCTION(meth), obj); } PyTypeObject PyMethod_Type = { |