diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py index cc424afb1d7..b89f09b393c 100644 --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -17,6 +17,15 @@ else: # Another brief digression to test the accuracy of manifest float constants. import double_const # don't blink -- that *was* the test +def remove_files(name): + for f in (name + os.extsep + "py", + name + os.extsep + "pyc", + name + os.extsep + "pyo", + name + os.extsep + "pyw", + name + "$py.class"): + if os.path.exists(f): + os.remove(f) + def test_with_extension(ext): # ext normally ".py"; perhaps ".pyw" source = TESTFN + ext pyo = TESTFN + os.extsep + "pyo" @@ -108,3 +117,78 @@ def test_module_with_large_stack(module): os.unlink(fname) test_module_with_large_stack('longlist') + +def test_failing_import_sticks(): + source = TESTFN + os.extsep + "py" + f = open(source, "w") + print >> f, "a = 1/0" + f.close() + + # New in 2.4, we shouldn't be able to import that no matter how often + # we try. + sys.path.insert(0, os.curdir) + try: + for i in 1, 2, 3: + try: + mod = __import__(TESTFN) + except ZeroDivisionError: + if TESTFN in sys.modules: + raise TestFailed("damaged module in sys.modules", i) + else: + raise TestFailed("was able to import a damaged module", i) + finally: + sys.path.pop(0) + remove_files(TESTFN) + +test_failing_import_sticks() + +def test_failing_reload(): + # A failing reload should leave the module object in sys.modules. + source = TESTFN + os.extsep + "py" + f = open(source, "w") + print >> f, "a = 1" + print >> f, "b = 2" + f.close() + + sys.path.insert(0, os.curdir) + try: + mod = __import__(TESTFN) + if TESTFN not in sys.modules: + raise TestFailed("expected module in sys.modules") + if mod.a != 1 or mod.b != 2: + raise TestFailed("module has wrong attribute values") + + # On WinXP, just replacing the .py file wasn't enough to + # convince reload() to reparse it. Maybe the timestamp didn't + # move enough. We force it to get reparsed by removing the + # compiled file too. + remove_files(TESTFN) + + # Now damage the module. + f = open(source, "w") + print >> f, "a = 10" + print >> f, "b = 20//0" + f.close() + try: + reload(mod) + except ZeroDivisionError: + pass + else: + raise TestFailed("was able to reload a damaged module") + + # But we still expect the module to be in sys.modules. + mod = sys.modules.get(TESTFN) + if mod is None: + raise TestFailed("expected module to still be in sys.modules") + # We should have replaced a w/ 10, but the old b value should + # stick. + if mod.a != 10 or mod.b != 2: + raise TestFailed("module has wrong attribute values") + + finally: + sys.path.pop(0) + remove_files(TESTFN) + if TESTFN in sys.modules: + del sys.modules[TESTFN] + +test_failing_reload()