Commit 5a5886dc authored by Nick Coghlan's avatar Nick Coghlan

Close #15386: There was a loophole that meant importlib.machinery and imp...

Close #15386: There was a loophole that meant importlib.machinery and imp would sometimes reference an uninitialised copy of importlib._bootstrap
parent a6d880aa
...@@ -2,14 +2,21 @@ ...@@ -2,14 +2,21 @@
__all__ = ['__import__', 'import_module', 'invalidate_caches'] __all__ = ['__import__', 'import_module', 'invalidate_caches']
# Bootstrap help ##################################################### # 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 import sys
try: try:
import _frozen_importlib as _bootstrap import _frozen_importlib as _bootstrap
except ImportError: except ImportError:
from . import _bootstrap from . import _bootstrap
_bootstrap._setup(sys, imp) _bootstrap._setup(sys, _imp)
else: else:
# importlib._bootstrap is the built-in import, ensure we don't create # importlib._bootstrap is the built-in import, ensure we don't create
# a second copy of the module. # a second copy of the module.
...@@ -22,6 +29,8 @@ else: ...@@ -22,6 +29,8 @@ else:
_w_long = _bootstrap._w_long _w_long = _bootstrap._w_long
_r_long = _bootstrap._r_long _r_long = _bootstrap._r_long
# Fully bootstrapped at this point, import whatever you like, circular
# dependencies and startup overhead minimisation permitting :)
# Public API ######################################################### # Public API #########################################################
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
import os import os
import sys import sys
import imp
import importlib import importlib
import imp
import os.path import os.path
from warnings import warn from warnings import warn
from types import ModuleType from types import ModuleType
......
...@@ -12,8 +12,8 @@ importers when locating support scripts as well as when importing modules. ...@@ -12,8 +12,8 @@ importers when locating support scripts as well as when importing modules.
import os import os
import sys import sys
import importlib.machinery # importlib first so we can test #15386 via -m
import imp import imp
import importlib.machinery
from pkgutil import read_code, get_loader, get_importer from pkgutil import read_code, get_loader, get_importer
__all__ = [ __all__ = [
......
...@@ -165,6 +165,9 @@ example, to run all the tests except for the gui tests, give the ...@@ -165,6 +165,9 @@ example, to run all the tests except for the gui tests, give the
option '-uall,-gui'. option '-uall,-gui'.
""" """
# We import importlib *ASAP* in order to test #15386
import importlib
import builtins import builtins
import faulthandler import faulthandler
import getopt import getopt
......
# We import importlib *ASAP* in order to test #15386
import importlib
import builtins import builtins
import imp import imp
from importlib.test.import_ import test_suite as importlib_import_test_suite from importlib.test.import_ import test_suite as importlib_import_test_suite
from importlib.test.import_ import util as importlib_util from importlib.test.import_ import util as importlib_util
import importlib
import marshal import marshal
import os import os
import platform import platform
...@@ -777,6 +778,15 @@ class ImportlibBootstrapTests(unittest.TestCase): ...@@ -777,6 +778,15 @@ class ImportlibBootstrapTests(unittest.TestCase):
self.assertEqual(mod.__package__, 'importlib') self.assertEqual(mod.__package__, 'importlib')
self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__) 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): class ImportTracebackTests(unittest.TestCase):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment