diff --git a/docs/changelog.rst b/docs/changelog.rst index 8e1ddc1a..4a3a5612 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -30,6 +30,12 @@ Enhancements `_ functionality, which will be addressed in a future release. +Fixes +^^^^^ + +* `#590 `_: the importer can handle + modules that replace themselves in :mod:`sys.modules` during import. + Thanks! ~~~~~~~ diff --git a/mitogen/core.py b/mitogen/core.py index ff77bba9..0d88d7f0 100644 --- a/mitogen/core.py +++ b/mitogen/core.py @@ -1355,7 +1355,10 @@ class Importer(object): exec(code, vars(mod)) else: exec('exec code in vars(mod)') - return mod + + # #590: if a module replaces itself in sys.modules during import, below + # is necessary. This matches PyImport_ExecCodeModuleEx() + return sys.modules.get(fullname, mod) def get_filename(self, fullname): if fullname in self._cache: diff --git a/tests/data/simple_pkg/imports_replaces_self.py b/tests/data/simple_pkg/imports_replaces_self.py new file mode 100644 index 00000000..b1b43813 --- /dev/null +++ b/tests/data/simple_pkg/imports_replaces_self.py @@ -0,0 +1,6 @@ +# issue #590: this module imports a module that replaces itself in sys.modules +# during initialization. +import simple_pkg.replaces_self + +def subtract_one(n): + return simple_pkg.replaces_self.subtract_one(n) diff --git a/tests/data/simple_pkg/replaces_self.py b/tests/data/simple_pkg/replaces_self.py new file mode 100644 index 00000000..5d853ebf --- /dev/null +++ b/tests/data/simple_pkg/replaces_self.py @@ -0,0 +1,4 @@ +# issue #590: this module replaces itself in sys.modules during initialization. +import sys +import simple_pkg.b +sys.modules[__name__] = simple_pkg.b diff --git a/tests/importer_test.py b/tests/importer_test.py index fc6f4bd6..c796f7d0 100644 --- a/tests/importer_test.py +++ b/tests/importer_test.py @@ -12,6 +12,7 @@ import mitogen.utils from mitogen.core import b import testlib +import simple_pkg.imports_replaces_self class ImporterMixin(testlib.RouterMixin): @@ -214,5 +215,13 @@ class Python24LineCacheTest(testlib.TestCase): pass +class SelfReplacingModuleTest(testlib.RouterMixin, testlib.TestCase): + # issue #590 + def test_importer_handles_self_replacement(self): + c = self.router.local() + self.assertEquals(0, + c.call(simple_pkg.imports_replaces_self.subtract_one, 1)) + + if __name__ == '__main__': unittest2.main()