diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2003-01-31 18:33:18 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2003-01-31 18:33:18 (GMT) |
commit | 4f0dcc9a9a4629607d4fff79912e8d0c86cd3914 (patch) | |
tree | bba33e033f6a51fec1c01a79a5f6e931f65e44f2 /Objects/methodobject.c | |
parent | 8f24cdc0d5e30e2f924ed2e8a71400fa87a70983 (diff) | |
download | cpython-4f0dcc9a9a4629607d4fff79912e8d0c86cd3914.zip cpython-4f0dcc9a9a4629607d4fff79912e8d0c86cd3914.tar.gz cpython-4f0dcc9a9a4629607d4fff79912e8d0c86cd3914.tar.bz2 |
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.
Diffstat (limited to 'Objects/methodobject.c')
-rw-r--r-- | Objects/methodobject.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/Objects/methodobject.c b/Objects/methodobject.c index a1f325d..aa64ff1 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -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 @@ PyCFunction_New(PyMethodDef *ml, PyObject *self) 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 @@ meth_dealloc(PyCFunctionObject *m) { _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 @@ meth_get__name__(PyCFunctionObject *m, void *closure) 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 @@ static PyGetSetDef meth_getsets [] = { {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 @@ PyTypeObject PyCFunction_Type = { 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 @@ Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, char *name) 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 @@ PyCFunction_Fini(void) 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); +} |