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);
+}