diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2015-09-05 11:05:05 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2015-09-05 11:05:05 (GMT) |
commit | 9d3c61c86a20678d604c96a68bbf4a966877f0b9 (patch) | |
tree | 77e38b72e9258da435606d28543cc0362787eeff | |
parent | 1b6691053701e92490c6b68171d6d6a645f8e708 (diff) | |
download | cpython-9d3c61c86a20678d604c96a68bbf4a966877f0b9.zip cpython-9d3c61c86a20678d604c96a68bbf4a966877f0b9.tar.gz cpython-9d3c61c86a20678d604c96a68bbf4a966877f0b9.tar.bz2 |
Close #24748: Restore imp.load_dynamic compatibility
To resolve a compatibility problem found with py2exe and
pywin32, imp.load_dynamic() once again ignores previously loaded modules
to support Python modules replacing themselves with extension modules.
Patch by Petr Viktorin.
-rw-r--r-- | Lib/imp.py | 8 | ||||
-rw-r--r-- | Lib/test/imp_dummy.py | 3 | ||||
-rw-r--r-- | Lib/test/test_imp.py | 24 | ||||
-rw-r--r-- | Misc/NEWS | 5 | ||||
-rw-r--r-- | Modules/_testmultiphase.c | 10 |
5 files changed, 49 insertions, 1 deletions
@@ -334,6 +334,12 @@ if create_dynamic: """ import importlib.machinery loader = importlib.machinery.ExtensionFileLoader(name, path) - return loader.load_module() + + # Issue #24748: Skip the sys.modules check in _load_module_shim; + # always load new extension + spec = importlib.machinery.ModuleSpec( + name=name, loader=loader, origin=path) + return _load(spec) + else: load_dynamic = None diff --git a/Lib/test/imp_dummy.py b/Lib/test/imp_dummy.py new file mode 100644 index 0000000..2a4deb4 --- /dev/null +++ b/Lib/test/imp_dummy.py @@ -0,0 +1,3 @@ +# Fodder for test of issue24748 in test_imp + +dummy_name = True diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index 47bf1de..ee9ee1a 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -3,6 +3,7 @@ try: except ImportError: _thread = None import importlib +import importlib.util import os import os.path import shutil @@ -275,6 +276,29 @@ class ImportTests(unittest.TestCase): self.skipTest("found module doesn't appear to be a C extension") imp.load_module(name, None, *found[1:]) + @requires_load_dynamic + def test_issue24748_load_module_skips_sys_modules_check(self): + name = 'test.imp_dummy' + try: + del sys.modules[name] + except KeyError: + pass + try: + module = importlib.import_module(name) + spec = importlib.util.find_spec('_testmultiphase') + module = imp.load_dynamic(name, spec.origin) + self.assertEqual(module.__name__, name) + self.assertEqual(module.__spec__.name, name) + self.assertEqual(module.__spec__.origin, spec.origin) + self.assertRaises(AttributeError, getattr, module, 'dummy_name') + self.assertEqual(module.int_const, 1969) + self.assertIs(sys.modules[name], module) + finally: + try: + del sys.modules[name] + except KeyError: + pass + @unittest.skipIf(sys.dont_write_bytecode, "test meaningful only when writing bytecode") def test_bug7732(self): @@ -15,6 +15,11 @@ Core and Builtins Library ------- +- Issue #24748: To resolve a compatibility problem found with py2exe and + pywin32, imp.load_dynamic() once again ignores previously loaded modules + to support Python modules replacing themselves with extension modules. + Patch by Petr Viktorin. + - Issue #24635: Fixed a bug in typing.py where isinstance([], typing.Iterable) would return True once, then False on subsequent calls. diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 2919687..2005205 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -582,3 +582,13 @@ PyInit__testmultiphase_exec_unreported_exception(PyObject *spec) { return PyModuleDef_Init(&def_exec_unreported_exception); } + +/*** Helper for imp test ***/ + +static PyModuleDef imp_dummy_def = TEST_MODULE_DEF("imp_dummy", main_slots, testexport_methods); + +PyMODINIT_FUNC +PyInit_imp_dummy(PyObject *spec) +{ + return PyModuleDef_Init(&imp_dummy_def); +} |