Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7859f87

Browse files
committed
Marc-Andre Lemburg's patch to support instance methods with other
callable objects than regular Pythonm functions as their im_func.
1 parent bb71ab6 commit 7859f87

3 files changed

Lines changed: 41 additions & 19 deletions

File tree

Modules/newmodule.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,23 @@ new_instancemethod(unused, args)
7171
PyObject* self;
7272
PyObject* classObj;
7373

74-
if (!PyArg_ParseTuple(args, "O!O!O!",
75-
&PyFunction_Type, &func,
76-
&PyInstance_Type, &self,
74+
if (!PyArg_ParseTuple(args, "OOO!",
75+
&func,
76+
&self,
7777
&PyClass_Type, &classObj))
7878
return NULL;
79+
if (!PyCallable_Check(func)) {
80+
PyErr_SetString(PyExc_TypeError,
81+
"first argument must be callable");
82+
return NULL;
83+
}
84+
if (self == Py_None)
85+
self = NULL;
86+
else if (!PyInstance_Check(self)) {
87+
PyErr_SetString(PyExc_TypeError,
88+
"second argument must be instance or None");
89+
return NULL;
90+
}
7991
return PyMethod_New(func, self, classObj);
8092
}
8193

Objects/classobject.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,7 @@ PyMethod_New(func, self, class)
14281428
PyObject *class;
14291429
{
14301430
register PyMethodObject *im;
1431-
if (!PyFunction_Check(func)) {
1431+
if (!PyCallable_Check(func)) {
14321432
PyErr_BadInternalCall();
14331433
return NULL;
14341434
}
@@ -1506,15 +1506,11 @@ instancemethod_getattr(im, name)
15061506
{
15071507
char *sname = PyString_AsString(name);
15081508
if (sname[0] == '_') {
1509-
PyFunctionObject *func = (PyFunctionObject *)(im->im_func);
1510-
if (strcmp(sname, "__name__") == 0) {
1511-
Py_INCREF(func->func_name);
1512-
return func->func_name;
1513-
}
1514-
if (strcmp(sname, "__doc__") == 0) {
1515-
Py_INCREF(func->func_doc);
1516-
return func->func_doc;
1517-
}
1509+
/* Inherit __name__ and __doc__ from the callable object
1510+
implementing the method */
1511+
if (strcmp(sname, "__name__") == 0 ||
1512+
strcmp(sname, "__doc__") == 0)
1513+
return PyObject_GetAttr(im->im_func, name);
15181514
}
15191515
if (PyEval_GetRestricted()) {
15201516
PyErr_SetString(PyExc_RuntimeError,
@@ -1550,20 +1546,29 @@ instancemethod_repr(a)
15501546
{
15511547
char buf[240];
15521548
PyInstanceObject *self = (PyInstanceObject *)(a->im_self);
1553-
PyFunctionObject *func = (PyFunctionObject *)(a->im_func);
1549+
PyObject *func = a->im_func;
15541550
PyClassObject *class = (PyClassObject *)(a->im_class);
15551551
PyObject *fclassname, *iclassname, *funcname;
15561552
char *fcname, *icname, *fname;
15571553
fclassname = class->cl_name;
1558-
funcname = func->func_name;
1554+
if (PyFunction_Check(func)) {
1555+
funcname = ((PyFunctionObject *)func)->func_name;
1556+
Py_INCREF(funcname);
1557+
}
1558+
else {
1559+
funcname = PyObject_GetAttrString(func,"__name__");
1560+
if (funcname == NULL)
1561+
PyErr_Clear();
1562+
}
1563+
if (funcname != NULL && PyString_Check(funcname))
1564+
fname = PyString_AS_STRING(funcname);
1565+
else
1566+
fname = "?";
1567+
Py_XDECREF(funcname);
15591568
if (fclassname != NULL && PyString_Check(fclassname))
15601569
fcname = PyString_AsString(fclassname);
15611570
else
15621571
fcname = "?";
1563-
if (funcname != NULL && PyString_Check(funcname))
1564-
fname = PyString_AsString(funcname);
1565-
else
1566-
fname = "?";
15671572
if (self == NULL)
15681573
sprintf(buf, "<unbound method %.100s.%.100s>", fcname, fname);
15691574
else {

Python/ceval.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,6 +2432,11 @@ call_function(func, arg, kw)
24322432
}
24332433
arg = newarg;
24342434
}
2435+
if (!PyFunction_Check(func)) {
2436+
result = PyEval_CallObjectWithKeywords(func, arg, kw);
2437+
Py_DECREF(arg);
2438+
return result;
2439+
}
24352440
}
24362441
else {
24372442
if (!PyFunction_Check(func)) {

0 commit comments

Comments
 (0)