summaryrefslogtreecommitdiffstats
path: root/Objects/methodobject.c
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2003-01-31 18:33:18 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2003-01-31 18:33:18 (GMT)
commit4f0dcc9a9a4629607d4fff79912e8d0c86cd3914 (patch)
treebba33e033f6a51fec1c01a79a5f6e931f65e44f2 /Objects/methodobject.c
parent8f24cdc0d5e30e2f924ed2e8a71400fa87a70983 (diff)
downloadcpython-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.c46
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);
+}