[Python-Dev] Fix import errors to have data
Tim Peters
tim.peters at gmail.com
Mon Aug 2 01:14:39 CEST 2004
Oops, attached a wrong patch. Correct patch attached.
-------------- next part --------------
Index: Lib/test/test_pkgimport.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_pkgimport.py,v
retrieving revision 1.7
diff -u -r1.7 test_pkgimport.py
--- Lib/test/test_pkgimport.py 9 Aug 2002 16:37:36 -0000 1.7
+++ Lib/test/test_pkgimport.py 1 Aug 2004 23:01:43 -0000
@@ -66,12 +66,11 @@
try: __import__(self.module_name)
except NameError: pass
else: raise RuntimeError, 'Failed to induce NameError.'
- module = __import__(self.module_name).foo
# ...now change the module so that the NameError doesn't
# happen
self.rewrite_file('%s = 1' % var)
- reload(module)
+ module = __import__(self.module_name).foo
self.assertEqual(getattr(module, var), 1)
Index: Python/import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.233
diff -u -r2.233 import.c
--- Python/import.c 27 Jun 2004 16:51:46 -0000 2.233
+++ Python/import.c 1 Aug 2004 23:01:44 -0000
@@ -557,10 +557,25 @@
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
- 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 *
PyImport_ExecCodeModule(char *name, PyObject *co)
{
@@ -582,7 +597,7 @@
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
if (PyDict_SetItemString(d, "__builtins__",
PyEval_GetBuiltins()) != 0)
- return NULL;
+ goto error;
}
/* Remember the filename as the __file__ attribute */
v = NULL;
@@ -601,7 +616,7 @@
v = PyEval_EvalCode((PyCodeObject *)co, d, d);
if (v == NULL)
- return NULL;
+ goto error;
Py_DECREF(v);
if ((m = PyDict_GetItemString(modules, name)) == NULL) {
@@ -614,6 +629,10 @@
Py_INCREF(m);
return m;
+
+ error:
+ _RemoveModule(name);
+ return NULL;
}
@@ -888,7 +907,9 @@
static PyObject *
load_package(char *name, char *pathname)
{
- PyObject *m, *d, *file, *path;
+ PyObject *m, *d;
+ PyObject *file = NULL;
+ PyObject *path = NULL;
int err;
char buf[MAXPATHLEN+1];
FILE *fp = NULL;
@@ -903,19 +924,15 @@
d = PyModule_GetDict(m);
file = PyString_FromString(pathname);
if (file == NULL)
- return NULL;
+ goto error;
path = Py_BuildValue("[O]", file);
- if (path == NULL) {
- Py_DECREF(file);
- return NULL;
- }
+ if (path == NULL)
+ goto error;
err = PyDict_SetItemString(d, "__file__", file);
if (err == 0)
err = PyDict_SetItemString(d, "__path__", path);
- if (err != 0) {
- m = NULL;
- goto cleanup;
- }
+ if (err != 0)
+ goto error;
buf[0] = '\0';
fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
if (fdp == NULL) {
@@ -930,6 +947,10 @@
m = load_module(name, fp, buf, fdp->type, NULL);
if (fp != NULL)
fclose(fp);
+ goto cleanup;
+
+ error:
+ m = NULL;
cleanup:
Py_XDECREF(path);
Py_XDECREF(file);
@@ -1272,7 +1293,7 @@
if (Py_VerboseFlag > 1)
PySys_WriteStderr("# trying %s\n", buf);
filemode = fdp->mode;
- if (filemode[0] == 'U')
+ if (filemode[0] == 'U')
filemode = "r" PY_STDIOTEXTMODE;
fp = fopen(buf, filemode);
if (fp != NULL) {
@@ -2234,6 +2255,7 @@
char buf[MAXPATHLEN+1];
struct filedescr *fdp;
FILE *fp = NULL;
+ PyObject *newm;
if (m == NULL || !PyModule_Check(m)) {
PyErr_SetString(PyExc_TypeError,
@@ -2275,10 +2297,18 @@
Py_XDECREF(path);
if (fdp == NULL)
return NULL;
- m = load_module(name, fp, buf, fdp->type, NULL);
+ newm = load_module(name, fp, buf, fdp->type, NULL);
if (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;
}
@@ -2520,7 +2550,7 @@
{
FILE *fp;
if (fob == NULL) {
- if (mode[0] == 'U')
+ if (mode[0] == 'U')
mode = "r" PY_STDIOTEXTMODE;
fp = fopen(pathname, mode);
if (fp == NULL)
@@ -2692,9 +2722,9 @@
The module name must include the full package name, if any.");
PyDoc_STRVAR(doc_lock_held,
-"lock_held() -> 0 or 1\n\
-Return 1 if the import lock is currently held.\n\
-On platforms without threads, return 0.");
+"lock_held() -> boolean\n\
+Return True if the import lock is currently held, else False.\n\
+On platforms without threads, return False.");
PyDoc_STRVAR(doc_acquire_lock,
"acquire_lock() -> None\n\
More information about the Python-Dev
mailing list