[Python-Dev] Fix import errors to have data

Tim Peters tim.peters at gmail.com
Sun Aug 1 07:50:57 CEST 2004


Attached patch builds on Guido's:

- refactored
- load_package() now also removes stuff from sys.modules if an error
  occurs and the stuff wasn't in sys.modules to begin with
- patches test_pkgimport so it passes again (it was relying on
  junk remaining in sys.modules in one spot)
- regrtest -uall passes on Windows with this patch (247 tests OK,
  37 tests skipped).
- oops -- fixes obsolute stuff in a docstring too (the LaTeX docs had
  already been corrected)
- does not remove insane workarounds in .py modules (contortions trying
  to worm around that non-working modules were left behind by failing
  imports)

"curses on Windows" no longer screws up.  Before:

$ regrtest.py -uall test_sundry test___all__ test_curses
test_sundry
test___all__
test test___all__ failed -- Traceback (most recent call last):
  File "C:\Code\python\lib\test\test___all__.py", line 150, in test_all
    self.check_all("rlcompleter")
  File "C:\Code\python\lib\test\test___all__.py", line 40, in check_all
    "%s has no __all__ attribute" % modname)
  File "C:\Code\python\lib\test\test_support.py", line 208, in verify
    raise TestFailed(reason)
TestFailed: rlcompleter has no __all__ attribute

test_curses
test test_curses crashed -- exceptions.AttributeError: 'module' object
has no attribute 'endwin'
1 test OK.
2 tests failed:
    test___all__ test_curses

After:

$ regrtest.py -uall test_sundry test___all__ test_curses
test_sundry
test___all__
test_curses
test_curses skipped -- No module named _curses
2 tests OK.
1 test skipped:
    test_curses
Those skips are all expected on win32.
-------------- 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 05:30:10 -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 05:30:11 -0000
@@ -557,6 +557,33 @@
 	return m;
 }
 
+/* The same as PyImport_AddModule, except also sets created to 1 if a
+ * new module object is created, or to 0 if an existing module object
+ * is found.
+ */
+static PyObject *
+_AddModuleEx(const char *name, int *created)
+{
+	PyObject *modules = PyImport_GetModuleDict();
+	PyObject *m;
+
+	*created = 0;
+	if ((m = PyDict_GetItemString(modules, name)) != NULL &&
+	    PyModule_Check(m))
+		return m;
+	m = PyImport_AddModule((char *)name);
+	if (m != NULL)
+		*created = 1;
+	return m;
+}
+
+/* Remove name from sys.modules.  It must already be in sys.modules. */
+static void
+_RemoveModule(const char *name)
+{
+	PyObject *modules = PyImport_GetModuleDict();
+	PyDict_DelItemString(modules, name); /* if it fails, too bad */
+}
 
 /* Execute a code object in a module and return the module object
    WITH INCREMENTED REFERENCE COUNT */
@@ -572,8 +599,9 @@
 {
 	PyObject *modules = PyImport_GetModuleDict();
 	PyObject *m, *d, *v;
+	int created;
 
-	m = PyImport_AddModule(name);
+	m = _AddModuleEx(name, &created);
 	if (m == NULL)
 		return NULL;
 	/* If the module is being reloaded, we get the old module back
@@ -582,7 +610,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 +629,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 +642,11 @@
 	Py_INCREF(m);
 
 	return m;
+
+  error:
+	if (created)
+		_RemoveModule(name);
+	return NULL;
 }
 
 
@@ -888,13 +921,16 @@
 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;
 	struct filedescr *fdp;
+	int created;
 
-	m = PyImport_AddModule(name);
+	m = _AddModuleEx(name, &created);
 	if (m == NULL)
 		return NULL;
 	if (Py_VerboseFlag)
@@ -903,19 +939,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,9 +962,15 @@
 	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);
+	if (created && m == NULL)
+		_RemoveModule(name);
 	return m;
 }
 
@@ -1272,7 +1310,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) {
@@ -2520,7 +2558,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 +2730,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