Mercurial > cpython-lru_cache-weakref
diff Objects/methodobject.c @ 27559:faabd9867fb8 legacy-trunk
Provide __module__ attributes for functions defined in C and Python.
__module__ is the string name of the module the function was defined
in, just like __module__ of classes. In some cases, particularly for
C functions, the __module__ may be None.
Change PyCFunction_New() from a function to a macro, but keep an
unused copy of the function around so that we don't change the binary
API.
Change pickle's save_global() to use whichmodule() if __module__ is
None, but add the __module__ logic to whichmodule() since it might be
used outside of pickle.
| author | Jeremy Hylton <jeremy@alum.mit.edu> |
|---|---|
| date | Fri, 31 Jan 2003 18:33:18 +0000 |
| parents | bd750378d5c1 |
| children | 1bd485717564 |
line wrap: on
line diff
--- a/Objects/methodobject.c Fri Jan 31 18:15:58 2003 +0000 +++ b/Objects/methodobject.c Fri Jan 31 18:33:18 2003 +0000 @@ -2,11 +2,12 @@ /* Method object implementation */ #include "Python.h" +#include "structmember.h" static PyCFunctionObject *free_list = NULL; PyObject * -PyCFunction_New(PyMethodDef *ml, PyObject *self) +PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) { PyCFunctionObject *op; op = free_list; @@ -22,6 +23,8 @@ op->m_ml = ml; Py_XINCREF(self); op->m_self = self; + Py_XINCREF(module); + op->m_module = module; _PyObject_GC_TRACK(op); return (PyObject *)op; } @@ -121,6 +124,7 @@ { _PyObject_GC_UNTRACK(m); Py_XDECREF(m->m_self); + Py_XDECREF(m->m_module); m->m_self = (PyObject *)free_list; free_list = m; } @@ -145,10 +149,18 @@ static int meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) { - if (m->m_self != NULL) - return visit(m->m_self, arg); - else - return 0; + int err; + if (m->m_self != NULL) { + err = visit(m->m_self, arg); + if (err) + return err; + } + if (m->m_module != NULL) { + err = visit(m->m_module, arg); + if (err) + return err; + } + return 0; } static PyObject * @@ -174,6 +186,13 @@ {0} }; +#define OFF(x) offsetof(PyCFunctionObject, x) + +static PyMemberDef meth_members[] = { + {"__module__", T_OBJECT, OFF(m_module), READONLY}, + {NULL} +}; + static PyObject * meth_repr(PyCFunctionObject *m) { @@ -250,7 +269,7 @@ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - 0, /* tp_members */ + meth_members, /* tp_members */ meth_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ @@ -308,6 +327,7 @@ for (; ml->ml_name != NULL; ml++) { if (name[0] == ml->ml_name[0] && strcmp(name+1, ml->ml_name+1) == 0) + /* XXX */ return PyCFunction_New(ml, self); } chain = chain->link; @@ -338,3 +358,17 @@ PyObject_GC_Del(v); } } + +/* 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. +*/ + +#undef PyCFunction_New +PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *); + +PyObject * +PyCFunction_New(PyMethodDef *ml, PyObject *self) +{ + return PyCFunction_NewEx(ml, self, NULL); +}
