From 7859f87fdbcc0679aa6ed9c181ee3826002ac5ca Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 8 Jul 1998 14:58:16 +0000 Subject: [PATCH] Marc-Andre Lemburg's patch to support instance methods with other callable objects than regular Pythonm functions as their im_func. --- Modules/newmodule.c | 18 +++++++++++++++--- Objects/classobject.c | 37 +++++++++++++++++++++---------------- Python/ceval.c | 5 +++++ 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/Modules/newmodule.c b/Modules/newmodule.c index cfe78834c10..52328a967d0 100644 --- a/Modules/newmodule.c +++ b/Modules/newmodule.c @@ -71,11 +71,23 @@ new_instancemethod(unused, args) PyObject* self; PyObject* classObj; - if (!PyArg_ParseTuple(args, "O!O!O!", - &PyFunction_Type, &func, - &PyInstance_Type, &self, + if (!PyArg_ParseTuple(args, "OOO!", + &func, + &self, &PyClass_Type, &classObj)) return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "first argument must be callable"); + return NULL; + } + if (self == Py_None) + self = NULL; + else if (!PyInstance_Check(self)) { + PyErr_SetString(PyExc_TypeError, + "second argument must be instance or None"); + return NULL; + } return PyMethod_New(func, self, classObj); } diff --git a/Objects/classobject.c b/Objects/classobject.c index 21542994777..86fc1d399a7 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -1428,7 +1428,7 @@ PyMethod_New(func, self, class) PyObject *class; { register PyMethodObject *im; - if (!PyFunction_Check(func)) { + if (!PyCallable_Check(func)) { PyErr_BadInternalCall(); return NULL; } @@ -1506,15 +1506,11 @@ instancemethod_getattr(im, name) { char *sname = PyString_AsString(name); if (sname[0] == '_') { - PyFunctionObject *func = (PyFunctionObject *)(im->im_func); - if (strcmp(sname, "__name__") == 0) { - Py_INCREF(func->func_name); - return func->func_name; - } - if (strcmp(sname, "__doc__") == 0) { - Py_INCREF(func->func_doc); - return func->func_doc; - } + /* Inherit __name__ and __doc__ from the callable object + implementing the method */ + if (strcmp(sname, "__name__") == 0 || + strcmp(sname, "__doc__") == 0) + return PyObject_GetAttr(im->im_func, name); } if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, @@ -1550,20 +1546,29 @@ instancemethod_repr(a) { char buf[240]; PyInstanceObject *self = (PyInstanceObject *)(a->im_self); - PyFunctionObject *func = (PyFunctionObject *)(a->im_func); + PyObject *func = a->im_func; PyClassObject *class = (PyClassObject *)(a->im_class); PyObject *fclassname, *iclassname, *funcname; char *fcname, *icname, *fname; fclassname = class->cl_name; - funcname = func->func_name; + if (PyFunction_Check(func)) { + funcname = ((PyFunctionObject *)func)->func_name; + Py_INCREF(funcname); + } + else { + funcname = PyObject_GetAttrString(func,"__name__"); + if (funcname == NULL) + PyErr_Clear(); + } + if (funcname != NULL && PyString_Check(funcname)) + fname = PyString_AS_STRING(funcname); + else + fname = "?"; + Py_XDECREF(funcname); if (fclassname != NULL && PyString_Check(fclassname)) fcname = PyString_AsString(fclassname); else fcname = "?"; - if (funcname != NULL && PyString_Check(funcname)) - fname = PyString_AsString(funcname); - else - fname = "?"; if (self == NULL) sprintf(buf, "", fcname, fname); else { diff --git a/Python/ceval.c b/Python/ceval.c index 5aed5ff8afe..d81f3fd8d9c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2432,6 +2432,11 @@ call_function(func, arg, kw) } arg = newarg; } + if (!PyFunction_Check(func)) { + result = PyEval_CallObjectWithKeywords(func, arg, kw); + Py_DECREF(arg); + return result; + } } else { if (!PyFunction_Check(func)) {