[Python-Dev] Fix import errors to have data

Tim Peters tim.peters at gmail.com
Mon Aug 2 01:37:30 CEST 2004


And one more time.

- regen'ed against current CVS import.c
- removes some now-needless workarounds in .py files
-------------- next part --------------
Index: Lib/pty.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/pty.py,v
retrieving revision 1.16
diff -u -r1.16 pty.py
--- Lib/pty.py	5 Jun 2004 16:27:16 -0000	1.16
+++ Lib/pty.py	1 Aug 2004 23:36:00 -0000
@@ -8,17 +8,6 @@
 
 from select import select
 import os
-
-# Absurd:  import termios and then delete it.  This is to force an attempt
-# to import pty to raise an ImportError on platforms that lack termios.
-# Without this explicit import of termios here, some other module may
-# import tty first, which in turn imports termios and dies with an
-# ImportError then.  But since tty *does* exist across platforms, that
-# leaves a damaged module object for tty in sys.modules, and the import
-# of tty here then appears to work despite that the tty imported is junk.
-import termios
-del termios
-
 import tty
 
 __all__ = ["openpty","fork","spawn"]
Index: Lib/test/test___all__.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test___all__.py,v
retrieving revision 1.39
diff -u -r1.39 test___all__.py
--- Lib/test/test___all__.py	1 Jul 2004 11:15:39 -0000	1.39
+++ Lib/test/test___all__.py	1 Aug 2004 23:36:00 -0000
@@ -21,20 +21,6 @@
         except ImportError:
             # Silent fail here seems the best route since some modules
             # may not be available in all environments.
-            # Since an ImportError may leave a partial module object in
-            # sys.modules, get rid of that first.  Here's what happens if
-            # you don't:  importing pty fails on Windows because pty tries to
-            # import FCNTL, which doesn't exist.  That raises an ImportError,
-            # caught here.  It also leaves a partial pty module in sys.modules.
-            # So when test_pty is called later, the import of pty succeeds,
-            # but shouldn't.  As a result, test_pty crashes with an
-            # AttributeError instead of an ImportError, and regrtest interprets
-            # the latter as a test failure (ImportError is treated as "test
-            # skipped" -- which is what test_pty should say on Windows).
-            try:
-                del sys.modules[modname]
-            except KeyError:
-                pass
             return
         verify(hasattr(sys.modules[modname], "__all__"),
                "%s has no __all__ attribute" % modname)
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:36:00 -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.235
diff -u -r2.235 import.c
--- Python/import.c	1 Aug 2004 23:26:05 -0000	2.235
+++ Python/import.c	1 Aug 2004 23:36:01 -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);
@@ -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;
 }
 
 


More information about the Python-Dev mailing list