[Python-Dev] Fix import errors to have data (original) (raw)

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


And one more time.

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 */

@@ -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