summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/importlib/__init__.py13
-rw-r--r--Lib/pkgutil.py2
-rw-r--r--Lib/runpy.py2
-rwxr-xr-xLib/test/regrtest.py3
-rw-r--r--Lib/test/test_import.py12
5 files changed, 27 insertions, 5 deletions
diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py
index 0935ada..d30691a 100644
--- a/Lib/importlib/__init__.py
+++ b/Lib/importlib/__init__.py
@@ -2,14 +2,21 @@
__all__ = ['__import__', 'import_module', 'invalidate_caches']
# Bootstrap help #####################################################
-import imp
+
+# Until bootstrapping is complete, DO NOT import any modules that attempt
+# to import importlib._bootstrap (directly or indirectly). Since this
+# partially initialised package would be present in sys.modules, those
+# modules would get an uninitialised copy of the source version, instead
+# of a fully initialised version (either the frozen one or the one
+# initialised below if the frozen one is not available).
+import _imp # Just the builtin component, NOT the full Python module
import sys
try:
import _frozen_importlib as _bootstrap
except ImportError:
from . import _bootstrap
- _bootstrap._setup(sys, imp)
+ _bootstrap._setup(sys, _imp)
else:
# importlib._bootstrap is the built-in import, ensure we don't create
# a second copy of the module.
@@ -22,6 +29,8 @@ else:
_w_long = _bootstrap._w_long
_r_long = _bootstrap._r_long
+# Fully bootstrapped at this point, import whatever you like, circular
+# dependencies and startup overhead minimisation permitting :)
# Public API #########################################################
diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py
index 8407b6d..8bdeb32 100644
--- a/Lib/pkgutil.py
+++ b/Lib/pkgutil.py
@@ -2,8 +2,8 @@
import os
import sys
-import imp
import importlib
+import imp
import os.path
from warnings import warn
from types import ModuleType
diff --git a/Lib/runpy.py b/Lib/runpy.py
index d612727..39c0e9f 100644
--- a/Lib/runpy.py
+++ b/Lib/runpy.py
@@ -12,8 +12,8 @@ importers when locating support scripts as well as when importing modules.
import os
import sys
+import importlib.machinery # importlib first so we can test #15386 via -m
import imp
-import importlib.machinery
from pkgutil import read_code, get_loader, get_importer
__all__ = [
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 28655f0..3c8359a 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -165,6 +165,9 @@ example, to run all the tests except for the gui tests, give the
option '-uall,-gui'.
"""
+# We import importlib *ASAP* in order to test #15386
+import importlib
+
import builtins
import faulthandler
import getopt
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index 89ec8dc..51b52c7 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -1,8 +1,9 @@
+# We import importlib *ASAP* in order to test #15386
+import importlib
import builtins
import imp
from importlib.test.import_ import test_suite as importlib_import_test_suite
from importlib.test.import_ import util as importlib_util
-import importlib
import marshal
import os
import platform
@@ -777,6 +778,15 @@ class ImportlibBootstrapTests(unittest.TestCase):
self.assertEqual(mod.__package__, 'importlib')
self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__)
+ def test_there_can_be_only_one(self):
+ # Issue #15386 revealed a tricky loophole in the bootstrapping
+ # This test is technically redundant, since the bug caused importing
+ # this test module to crash completely, but it helps prove the point
+ from importlib import machinery
+ mod = sys.modules['_frozen_importlib']
+ self.assertIs(machinery.FileFinder, mod.FileFinder)
+ self.assertIs(imp.new_module, mod.new_module)
+
class ImportTracebackTests(unittest.TestCase):