mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
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.
This commit is contained in:
parent
8f24cdc0d5
commit
4f0dcc9a9a
8 changed files with 114 additions and 18 deletions
|
@ -14,6 +14,7 @@ PyFunction_New(PyObject *code, PyObject *globals)
|
|||
if (op != NULL) {
|
||||
PyObject *doc;
|
||||
PyObject *consts;
|
||||
PyObject *module;
|
||||
op->func_weakreflist = NULL;
|
||||
Py_INCREF(code);
|
||||
op->func_code = code;
|
||||
|
@ -34,6 +35,16 @@ PyFunction_New(PyObject *code, PyObject *globals)
|
|||
Py_INCREF(doc);
|
||||
op->func_doc = doc;
|
||||
op->func_dict = NULL;
|
||||
op->func_module = NULL;
|
||||
|
||||
/* __module__: If module name is in globals, use it.
|
||||
Otherwise, use None.
|
||||
*/
|
||||
module = PyDict_GetItemString(globals, "__name__");
|
||||
if (module) {
|
||||
Py_INCREF(module);
|
||||
op->func_module = module;
|
||||
}
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
@ -61,6 +72,16 @@ PyFunction_GetGlobals(PyObject *op)
|
|||
return ((PyFunctionObject *) op) -> func_globals;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyFunction_GetModule(PyObject *op)
|
||||
{
|
||||
if (!PyFunction_Check(op)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
return ((PyFunctionObject *) op) -> func_module;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyFunction_GetDefaults(PyObject *op)
|
||||
{
|
||||
|
@ -138,6 +159,7 @@ static PyMemberDef func_memberlist[] = {
|
|||
RESTRICTED|READONLY},
|
||||
{"func_name", T_OBJECT, OFF(func_name), READONLY},
|
||||
{"__name__", T_OBJECT, OFF(func_name), READONLY},
|
||||
{"__module__", T_OBJECT, OFF(func_module), READONLY},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
@ -373,6 +395,7 @@ func_dealloc(PyFunctionObject *op)
|
|||
PyObject_ClearWeakRefs((PyObject *) op);
|
||||
Py_DECREF(op->func_code);
|
||||
Py_DECREF(op->func_globals);
|
||||
Py_XDECREF(op->func_module);
|
||||
Py_DECREF(op->func_name);
|
||||
Py_XDECREF(op->func_defaults);
|
||||
Py_XDECREF(op->func_doc);
|
||||
|
@ -405,6 +428,11 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
|
|||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (f->func_module) {
|
||||
err = visit(f->func_module, arg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (f->func_defaults) {
|
||||
err = visit(f->func_defaults, arg);
|
||||
if (err)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue