Issue #3080: Add PyImport_AddModuleObject() and PyImport_ExecCodeModuleObject()

This commit is contained in:
Victor Stinner 2011-03-04 12:57:09 +00:00
parent 0639b56672
commit 27ee089c35
3 changed files with 94 additions and 23 deletions

View File

@ -86,7 +86,7 @@ Importing Modules
an exception set on failure (the module still exists in this case). an exception set on failure (the module still exists in this case).
.. c:function:: PyObject* PyImport_AddModule(const char *name) .. c:function:: PyObject* PyImport_AddModuleObject(PyObject *name)
Return the module object corresponding to a module name. The *name* argument Return the module object corresponding to a module name. The *name* argument
may be of the form ``package.module``. First check the modules dictionary if may be of the form ``package.module``. First check the modules dictionary if
@ -100,6 +100,14 @@ Importing Modules
or one of its variants to import a module. Package structures implied by a or one of its variants to import a module. Package structures implied by a
dotted name for *name* are not created if not already present. dotted name for *name* are not created if not already present.
.. versionadded:: 3.3
.. c:function:: PyObject* PyImport_AddModule(const char *name)
Similar to :c:func:`PyImport_AddModuleObject`, but the name is an UTF-8
encoded string instead of a Unicode object.
.. c:function:: PyObject* PyImport_ExecCodeModule(char *name, PyObject *co) .. c:function:: PyObject* PyImport_ExecCodeModule(char *name, PyObject *co)
@ -136,14 +144,23 @@ Importing Modules
See also :c:func:`PyImport_ExecCodeModuleWithPathnames`. See also :c:func:`PyImport_ExecCodeModuleWithPathnames`.
.. c:function:: PyObject* PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, char *cpathname) .. c:function:: PyObject* PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, PyObject *cpathname)
Like :c:func:`PyImport_ExecCodeModuleEx`, but the :attr:`__cached__` Like :c:func:`PyImport_ExecCodeModuleEx`, but the :attr:`__cached__`
attribute of the module object is set to *cpathname* if it is attribute of the module object is set to *cpathname* if it is
non-``NULL``. Of the three functions, this is the preferred one to use. non-``NULL``. Of the three functions, this is the preferred one to use.
.. versionadded:: 3.3
.. c:function:: PyObject* PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, char *cpathname)
Like :c:func:`PyImport_ExecCodeModuleObject`, but *name*, *pathname* and
*cpathname* are UTF-8 encoded strings.
.. versionadded:: 3.2 .. versionadded:: 3.2
.. c:function:: long PyImport_GetMagicNumber() .. c:function:: long PyImport_GetMagicNumber()
Return the magic number for Python bytecode files (a.k.a. :file:`.pyc` and Return the magic number for Python bytecode files (a.k.a. :file:`.pyc` and

View File

@ -24,7 +24,16 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleWithPathnames(
char *pathname, /* decoded from the filesystem encoding */ char *pathname, /* decoded from the filesystem encoding */
char *cpathname /* decoded from the filesystem encoding */ char *cpathname /* decoded from the filesystem encoding */
); );
PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject(
PyObject *name,
PyObject *co,
PyObject *pathname,
PyObject *cpathname
);
PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void);
PyAPI_FUNC(PyObject *) PyImport_AddModuleObject(
PyObject *name
);
PyAPI_FUNC(PyObject *) PyImport_AddModule( PyAPI_FUNC(PyObject *) PyImport_AddModule(
const char *name /* UTF-8 encoded string */ const char *name /* UTF-8 encoded string */
); );

View File

@ -698,18 +698,18 @@ _PyImport_FindBuiltin(const char *name)
'NEW' REFERENCE! */ 'NEW' REFERENCE! */
PyObject * PyObject *
PyImport_AddModule(const char *name) PyImport_AddModuleObject(PyObject *name)
{ {
PyObject *modules = PyImport_GetModuleDict(); PyObject *modules = PyImport_GetModuleDict();
PyObject *m; PyObject *m;
if ((m = PyDict_GetItemString(modules, name)) != NULL && if ((m = PyDict_GetItem(modules, name)) != NULL &&
PyModule_Check(m)) PyModule_Check(m))
return m; return m;
m = PyModule_New(name); m = PyModule_NewObject(name);
if (m == NULL) if (m == NULL)
return NULL; return NULL;
if (PyDict_SetItemString(modules, name, m) != 0) { if (PyDict_SetItem(modules, name, m) != 0) {
Py_DECREF(m); Py_DECREF(m);
return NULL; return NULL;
} }
@ -718,14 +718,27 @@ PyImport_AddModule(const char *name)
return m; return m;
} }
PyObject *
PyImport_AddModule(const char *name)
{
PyObject *nameobj, *module;
nameobj = PyUnicode_FromString(name);
if (nameobj == NULL)
return NULL;
module = PyImport_AddModuleObject(nameobj);
Py_DECREF(nameobj);
return module;
}
/* Remove name from sys.modules, if it's there. */ /* Remove name from sys.modules, if it's there. */
static void static void
remove_module(const char *name) remove_module(PyObject *name)
{ {
PyObject *modules = PyImport_GetModuleDict(); PyObject *modules = PyImport_GetModuleDict();
if (PyDict_GetItemString(modules, name) == NULL) if (PyDict_GetItem(modules, name) == NULL)
return; return;
if (PyDict_DelItemString(modules, name) < 0) if (PyDict_DelItem(modules, name) < 0)
Py_FatalError("import: deleting existing key in" Py_FatalError("import: deleting existing key in"
"sys.modules failed"); "sys.modules failed");
} }
@ -762,11 +775,43 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
PyObject * PyObject *
PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname,
char *cpathname) char *cpathname)
{
PyObject *m = NULL;
PyObject *nameobj, *pathobj = NULL, *cpathobj = NULL;
nameobj = PyUnicode_FromString(name);
if (nameobj == NULL)
return NULL;
if (pathname != NULL) {
pathobj = PyUnicode_DecodeFSDefault(pathname);
if (pathobj == NULL)
goto error;
} else
pathobj = NULL;
if (cpathname != NULL) {
cpathobj = PyUnicode_DecodeFSDefault(cpathname);
if (cpathobj == NULL)
goto error;
} else
cpathobj = NULL;
m = PyImport_ExecCodeModuleObject(nameobj, co, pathobj, cpathobj);
error:
Py_DECREF(nameobj);
Py_XDECREF(pathobj);
Py_XDECREF(cpathobj);
return m;
}
PyObject*
PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname,
PyObject *cpathname)
{ {
PyObject *modules = PyImport_GetModuleDict(); PyObject *modules = PyImport_GetModuleDict();
PyObject *m, *d, *v; PyObject *m, *d, *v;
PyObject *pathbytes;
m = PyImport_AddModule(name); m = PyImport_AddModuleObject(name);
if (m == NULL) if (m == NULL)
return NULL; return NULL;
/* If the module is being reloaded, we get the old module back /* If the module is being reloaded, we get the old module back
@ -778,12 +823,18 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname,
goto error; goto error;
} }
/* Remember the filename as the __file__ attribute */ /* Remember the filename as the __file__ attribute */
v = NULL;
if (pathname != NULL) { if (pathname != NULL) {
v = get_sourcefile(pathname); pathbytes = PyUnicode_EncodeFSDefault(pathname);
if (pathbytes != NULL) {
v = get_sourcefile(PyBytes_AS_STRING(pathbytes));
Py_DECREF(pathbytes);
} else
v = NULL;
if (v == NULL) if (v == NULL)
PyErr_Clear(); PyErr_Clear();
} }
else
v = NULL;
if (v == NULL) { if (v == NULL) {
v = ((PyCodeObject *)co)->co_filename; v = ((PyCodeObject *)co)->co_filename;
Py_INCREF(v); Py_INCREF(v);
@ -793,27 +844,21 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname,
Py_DECREF(v); Py_DECREF(v);
/* Remember the pyc path name as the __cached__ attribute. */ /* Remember the pyc path name as the __cached__ attribute. */
if (cpathname == NULL) { if (cpathname != NULL)
v = cpathname;
else
v = Py_None; v = Py_None;
Py_INCREF(v);
}
else if ((v = PyUnicode_FromString(cpathname)) == NULL) {
PyErr_Clear(); /* Not important enough to report */
v = Py_None;
Py_INCREF(v);
}
if (PyDict_SetItemString(d, "__cached__", v) != 0) if (PyDict_SetItemString(d, "__cached__", v) != 0)
PyErr_Clear(); /* Not important enough to report */ PyErr_Clear(); /* Not important enough to report */
Py_DECREF(v);
v = PyEval_EvalCode(co, d, d); v = PyEval_EvalCode(co, d, d);
if (v == NULL) if (v == NULL)
goto error; goto error;
Py_DECREF(v); Py_DECREF(v);
if ((m = PyDict_GetItemString(modules, name)) == NULL) { if ((m = PyDict_GetItem(modules, name)) == NULL) {
PyErr_Format(PyExc_ImportError, PyErr_Format(PyExc_ImportError,
"Loaded module %.200s not found in sys.modules", "Loaded module %R not found in sys.modules",
name); name);
return NULL; return NULL;
} }