diff options
author | Victor Stinner <vstinner@python.org> | 2020-11-19 12:43:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-19 12:43:43 (GMT) |
commit | 3390347aa036404453213d589fe1e35902e55fd4 (patch) | |
tree | 49309f502a12cfece7b30190f3f36a8ab1143d46 /Lib/importlib | |
parent | 7d9d25dbedfffce61fc76bc7ccbfa9ae901bf56f (diff) | |
download | cpython-3390347aa036404453213d589fe1e35902e55fd4.zip cpython-3390347aa036404453213d589fe1e35902e55fd4.tar.gz cpython-3390347aa036404453213d589fe1e35902e55fd4.tar.bz2 |
bpo-42403: Simplify importlib external bootstrap (GH-23397)
Simplify the importlib external bootstrap code:
importlib._bootstrap_external now uses regular imports to import
builtin modules. When it is imported, the builtin __import__()
function is already fully working and so can be used to import
builtin modules like sys.
Diffstat (limited to 'Lib/importlib')
-rw-r--r-- | Lib/importlib/__init__.py | 2 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap.py | 7 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap_external.py | 111 |
3 files changed, 55 insertions, 65 deletions
diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py index bea37d7..03ff714 100644 --- a/Lib/importlib/__init__.py +++ b/Lib/importlib/__init__.py @@ -34,7 +34,7 @@ try: import _frozen_importlib_external as _bootstrap_external except ImportError: from . import _bootstrap_external - _bootstrap_external._setup(_bootstrap) + _bootstrap_external._set_bootstrap_module(_bootstrap) _bootstrap._bootstrap_external = _bootstrap_external else: _bootstrap_external.__name__ = 'importlib._bootstrap_external' diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index e00b27e..854b603 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -22,8 +22,15 @@ work. One should use importlib as the public-facing version of this module. # Bootstrap-related code ###################################################### +# Modules injected manually by _setup() +_thread = None +_warnings = None +_weakref = None + +# Import done by _install_external_importers() _bootstrap_external = None + def _wrap(new, old): """Simple substitute for functools.update_wrapper.""" for replace in ['__module__', '__name__', '__qualname__', '__doc__']: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 5c30a67..a0236c4 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -19,6 +19,36 @@ work. One should use importlib as the public-facing version of this module. # reference any injected objects! This includes not only global code but also # anything specified at the class level. +# Module injected manually by _set_bootstrap_module() +_bootstrap = None + +# Import builtin modules +import _imp +import _io +import sys +import _warnings +import marshal + + +_MS_WINDOWS = (sys.platform == 'win32') +if _MS_WINDOWS: + import nt as _os + import winreg +else: + import posix as _os + + +if _MS_WINDOWS: + path_separators = ['\\', '/'] +else: + path_separators = ['/'] +# Assumption made in _path_join() +assert all(len(sep) == 1 for sep in path_separators) +path_sep = path_separators[0] +path_separators = ''.join(path_separators) +_pathseps_with_colon = {f':{s}' for s in path_separators} + + # Bootstrap-related code ###################################################### _CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win', _CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin' @@ -42,6 +72,8 @@ def _make_relax_case(): return False return _relax_case +_relax_case = _make_relax_case() + def _pack_uint32(x): """Convert a 32-bit integer to little-endian.""" @@ -294,7 +326,11 @@ _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' _OPT = 'opt-' -SOURCE_SUFFIXES = ['.py'] # _setup() adds .pyw as needed. +SOURCE_SUFFIXES = ['.py'] +if _MS_WINDOWS: + SOURCE_SUFFIXES.append('.pyw') + +EXTENSION_SUFFIXES = _imp.extension_suffixes() BYTECODE_SUFFIXES = ['.pyc'] # Deprecated. @@ -469,15 +505,18 @@ def _check_name(method): raise ImportError('loader for %s cannot handle %s' % (self.name, name), name=name) return method(self, name, *args, **kwargs) - try: + + # FIXME: @_check_name is used to define class methods before the + # _bootstrap module is set by _set_bootstrap_module(). + if _bootstrap is not None: _wrap = _bootstrap._wrap - except NameError: - # XXX yuck + else: def _wrap(new, old): for replace in ['__module__', '__name__', '__qualname__', '__doc__']: if hasattr(old, replace): setattr(new, replace, getattr(old, replace)) new.__dict__.update(old.__dict__) + _wrap(_check_name_wrapper, method) return _check_name_wrapper @@ -713,7 +752,7 @@ class WindowsRegistryFinder: REGISTRY_KEY_DEBUG = ( 'Software\\Python\\PythonCore\\{sys_version}' '\\Modules\\{fullname}\\Debug') - DEBUG_BUILD = False # Changed in _setup() + DEBUG_BUILD = (_MS_WINDOWS and '_d.pyd' in EXTENSION_SUFFIXES) @classmethod def _open_registry(cls, key): @@ -1060,10 +1099,6 @@ class SourcelessFileLoader(FileLoader, _LoaderBasics): return None -# Filled in by _setup(). -EXTENSION_SUFFIXES = [] - - class ExtensionFileLoader(FileLoader, _LoaderBasics): """Loader for extension modules. @@ -1552,66 +1587,14 @@ def _get_supported_file_loaders(): return [extensions, source, bytecode] -def _setup(_bootstrap_module): - """Setup the path-based importers for importlib by importing needed - built-in modules and injecting them into the global namespace. - - Other components are extracted from the core bootstrap module. - - """ - global sys, _imp, _bootstrap +def _set_bootstrap_module(_bootstrap_module): + global _bootstrap _bootstrap = _bootstrap_module - sys = _bootstrap.sys - _imp = _bootstrap._imp - - self_module = sys.modules[__name__] - - # Directly load the os module (needed during bootstrap). - os_details = ('posix', ['/']), ('nt', ['\\', '/']) - for builtin_os, path_separators in os_details: - # Assumption made in _path_join() - assert all(len(sep) == 1 for sep in path_separators) - path_sep = path_separators[0] - if builtin_os in sys.modules: - os_module = sys.modules[builtin_os] - break - else: - try: - os_module = _bootstrap._builtin_from_name(builtin_os) - break - except ImportError: - continue - else: - raise ImportError('importlib requires posix or nt') - - setattr(self_module, '_os', os_module) - setattr(self_module, 'path_sep', path_sep) - setattr(self_module, 'path_separators', ''.join(path_separators)) - setattr(self_module, '_pathseps_with_colon', {f':{s}' for s in path_separators}) - - # Directly load built-in modules needed during bootstrap. - builtin_names = ['_io', '_warnings', 'marshal'] - if builtin_os == 'nt': - builtin_names.append('winreg') - for builtin_name in builtin_names: - if builtin_name not in sys.modules: - builtin_module = _bootstrap._builtin_from_name(builtin_name) - else: - builtin_module = sys.modules[builtin_name] - setattr(self_module, builtin_name, builtin_module) - - # Constants - setattr(self_module, '_relax_case', _make_relax_case()) - EXTENSION_SUFFIXES.extend(_imp.extension_suffixes()) - if builtin_os == 'nt': - SOURCE_SUFFIXES.append('.pyw') - if '_d.pyd' in EXTENSION_SUFFIXES: - WindowsRegistryFinder.DEBUG_BUILD = True def _install(_bootstrap_module): """Install the path-based import components.""" - _setup(_bootstrap_module) + _set_bootstrap_module(_bootstrap_module) supported_loaders = _get_supported_file_loaders() sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)]) sys.meta_path.append(PathFinder) |