Unbinding of methods - Code Review (original) (raw)

Index: Objects/methodobject.c

===================================================================

--- a/Objects/methodobject.c

+++ b/Objects/methodobject.c

@@ -14,7 +14,8 @@

#endif

PyObject *

-PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)

+PyCFunction_NewExEx(PyMethodDef *ml, PyObject *self, PyObject *module,

+ PyObject *unbound)

{

PyCFunctionObject *op;

op = free_list;

@@ -33,6 +34,8 @@

op->m_self = self;

Py_XINCREF(module);

op->m_module = module;

+ Py_XINCREF(unbound);

+ op->m_unbound = unbound;

_PyObject_GC_TRACK(op);

return (PyObject *)op;

}

@@ -206,11 +209,30 @@

return self;

}

+static PyObject *

+meth_get__func__(PyCFunctionObject *m, void *closure)

+{

+ if (m->m_self == NULL || PyModule_Check(m->m_self) ) {

+ //XXX for classmethods add: || PyType_CheckExact(m->m_self))

+ //XXX also change in classobject.c's __func__

+ Py_INCREF(m);

+ return (PyObject*)m;

+ }

+ if (m->m_unbound != NULL) {

+ Py_XINCREF(m->m_unbound);

+ return m->m_unbound;

+ }

+ // this PyCFunctionObject was not provided with the unbounded version of

+ // the method, so we'll create one ourselves by replacing self with NULL

+ return PyCFunction_NewEx(m->m_ml, NULL, m->m_module);

+}

static PyGetSetDef meth_getsets [] = {

{"__doc__", (getter)meth_get__doc__, NULL, NULL},

{"__name__", (getter)meth_get__name__, NULL, NULL},

{"__qualname__", (getter)meth_get__qualname__, NULL, NULL},

{"__self__", (getter)meth_get__self__, NULL, NULL},

+ {"__func__", (getter)meth_get__func__, NULL, NULL},

{0}

};

@@ -347,16 +369,25 @@

numfree, sizeof(PyCFunction));

}

-/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),

- but it's part of the API so we need to keep a function around that

- existing C extensions can call.

+/* PyCFunction_New() and PyCFunction_NewEx() are now just macros that call

+ PyCFunction_NewExEx(), but they're part of the API so we need to keep

+ functions around that existing C extensions can call.

*/

#undef PyCFunction_New

+#undef PyCFunction_NewEx

PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);

+PyAPI_FUNC(PyObject *) PyCFunction_NewEx(

+ PyMethodDef *, PyObject *, PyObject *);

PyObject *

PyCFunction_New(PyMethodDef *ml, PyObject *self)

{

- return PyCFunction_NewEx(ml, self, NULL);

+ return PyCFunction_NewExEx(ml, self, NULL, NULL);

}

+PyObject *

+PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)

+{

+ return PyCFunction_NewExEx(ml, self, module, NULL);

+}