mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
PyImport_ExecCodeModuleEx(): remove module from sys.modules in error cases.
PyImport_ReloadModule(): restore the module to sys.modules in error cases. load_package(): semantic-neutral refactoring from an earlier stab at this patch; giving it a common error exit made the code easier to follow, so retaining that part. _RemoveModule(): new little utility to delete a key from sys.modules.
This commit is contained in:
parent
94f9b86930
commit
1cd701732f
1 changed files with 46 additions and 16 deletions
|
@ -557,10 +557,25 @@ PyImport_AddModule(char *name)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove name from sys.modules, if it's there. */
|
||||||
|
static void
|
||||||
|
_RemoveModule(const char *name)
|
||||||
|
{
|
||||||
|
PyObject *modules = PyImport_GetModuleDict();
|
||||||
|
if (PyDict_GetItemString(modules, name) == NULL)
|
||||||
|
return;
|
||||||
|
if (PyDict_DelItemString(modules, name) < 0)
|
||||||
|
Py_FatalError("import: deleting existing key in"
|
||||||
|
"sys.modules failed");
|
||||||
|
}
|
||||||
|
|
||||||
/* Execute a code object in a module and return the module object
|
/* Execute a code object in a module and return the module object
|
||||||
WITH INCREMENTED REFERENCE COUNT */
|
* WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is
|
||||||
|
* removed from sys.modules, to avoid leaving damaged module objects
|
||||||
|
* in sys.modules. The caller may wish to restore the original
|
||||||
|
* module object (if any) in this case; PyImport_ReloadModule is an
|
||||||
|
* example.
|
||||||
|
*/
|
||||||
PyObject *
|
PyObject *
|
||||||
PyImport_ExecCodeModule(char *name, PyObject *co)
|
PyImport_ExecCodeModule(char *name, PyObject *co)
|
||||||
{
|
{
|
||||||
|
@ -582,7 +597,7 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
|
||||||
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
|
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
|
||||||
if (PyDict_SetItemString(d, "__builtins__",
|
if (PyDict_SetItemString(d, "__builtins__",
|
||||||
PyEval_GetBuiltins()) != 0)
|
PyEval_GetBuiltins()) != 0)
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
/* Remember the filename as the __file__ attribute */
|
/* Remember the filename as the __file__ attribute */
|
||||||
v = NULL;
|
v = NULL;
|
||||||
|
@ -601,7 +616,7 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
|
||||||
|
|
||||||
v = PyEval_EvalCode((PyCodeObject *)co, d, d);
|
v = PyEval_EvalCode((PyCodeObject *)co, d, d);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return NULL;
|
goto error;
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
|
|
||||||
if ((m = PyDict_GetItemString(modules, name)) == NULL) {
|
if ((m = PyDict_GetItemString(modules, name)) == NULL) {
|
||||||
|
@ -614,6 +629,10 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
|
||||||
Py_INCREF(m);
|
Py_INCREF(m);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|
||||||
|
error:
|
||||||
|
_RemoveModule(name);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -888,7 +907,9 @@ static struct _frozen *find_frozen(char *name);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
load_package(char *name, char *pathname)
|
load_package(char *name, char *pathname)
|
||||||
{
|
{
|
||||||
PyObject *m, *d, *file, *path;
|
PyObject *m, *d;
|
||||||
|
PyObject *file = NULL;
|
||||||
|
PyObject *path = NULL;
|
||||||
int err;
|
int err;
|
||||||
char buf[MAXPATHLEN+1];
|
char buf[MAXPATHLEN+1];
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
@ -903,19 +924,15 @@ load_package(char *name, char *pathname)
|
||||||
d = PyModule_GetDict(m);
|
d = PyModule_GetDict(m);
|
||||||
file = PyString_FromString(pathname);
|
file = PyString_FromString(pathname);
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return NULL;
|
goto error;
|
||||||
path = Py_BuildValue("[O]", file);
|
path = Py_BuildValue("[O]", file);
|
||||||
if (path == NULL) {
|
if (path == NULL)
|
||||||
Py_DECREF(file);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
err = PyDict_SetItemString(d, "__file__", file);
|
err = PyDict_SetItemString(d, "__file__", file);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
err = PyDict_SetItemString(d, "__path__", path);
|
err = PyDict_SetItemString(d, "__path__", path);
|
||||||
if (err != 0) {
|
if (err != 0)
|
||||||
m = NULL;
|
goto error;
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
|
fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
|
||||||
if (fdp == NULL) {
|
if (fdp == NULL) {
|
||||||
|
@ -930,6 +947,10 @@ load_package(char *name, char *pathname)
|
||||||
m = load_module(name, fp, buf, fdp->type, NULL);
|
m = load_module(name, fp, buf, fdp->type, NULL);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
error:
|
||||||
|
m = NULL;
|
||||||
cleanup:
|
cleanup:
|
||||||
Py_XDECREF(path);
|
Py_XDECREF(path);
|
||||||
Py_XDECREF(file);
|
Py_XDECREF(file);
|
||||||
|
@ -2234,6 +2255,7 @@ PyImport_ReloadModule(PyObject *m)
|
||||||
char buf[MAXPATHLEN+1];
|
char buf[MAXPATHLEN+1];
|
||||||
struct filedescr *fdp;
|
struct filedescr *fdp;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
PyObject *newm;
|
||||||
|
|
||||||
if (m == NULL || !PyModule_Check(m)) {
|
if (m == NULL || !PyModule_Check(m)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
@ -2275,10 +2297,18 @@ PyImport_ReloadModule(PyObject *m)
|
||||||
Py_XDECREF(path);
|
Py_XDECREF(path);
|
||||||
if (fdp == NULL)
|
if (fdp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
m = load_module(name, fp, buf, fdp->type, NULL);
|
newm = load_module(name, fp, buf, fdp->type, NULL);
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return m;
|
if (newm == NULL) {
|
||||||
|
/* load_module probably removed name from modules because of
|
||||||
|
* the error. Put back the original module object. We're
|
||||||
|
* going to return NULL in this case regardless of whether
|
||||||
|
* replacing name succeeds, so the return value is ignored.
|
||||||
|
*/
|
||||||
|
PyDict_SetItemString(modules, name, m);
|
||||||
|
}
|
||||||
|
return newm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue