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.
This commit is contained in:
parent
7d9d25dbed
commit
3390347aa0
|
@ -34,7 +34,7 @@ try:
|
||||||
import _frozen_importlib_external as _bootstrap_external
|
import _frozen_importlib_external as _bootstrap_external
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from . import _bootstrap_external
|
from . import _bootstrap_external
|
||||||
_bootstrap_external._setup(_bootstrap)
|
_bootstrap_external._set_bootstrap_module(_bootstrap)
|
||||||
_bootstrap._bootstrap_external = _bootstrap_external
|
_bootstrap._bootstrap_external = _bootstrap_external
|
||||||
else:
|
else:
|
||||||
_bootstrap_external.__name__ = 'importlib._bootstrap_external'
|
_bootstrap_external.__name__ = 'importlib._bootstrap_external'
|
||||||
|
|
|
@ -22,8 +22,15 @@ work. One should use importlib as the public-facing version of this module.
|
||||||
|
|
||||||
# Bootstrap-related code ######################################################
|
# Bootstrap-related code ######################################################
|
||||||
|
|
||||||
|
# Modules injected manually by _setup()
|
||||||
|
_thread = None
|
||||||
|
_warnings = None
|
||||||
|
_weakref = None
|
||||||
|
|
||||||
|
# Import done by _install_external_importers()
|
||||||
_bootstrap_external = None
|
_bootstrap_external = None
|
||||||
|
|
||||||
|
|
||||||
def _wrap(new, old):
|
def _wrap(new, old):
|
||||||
"""Simple substitute for functools.update_wrapper."""
|
"""Simple substitute for functools.update_wrapper."""
|
||||||
for replace in ['__module__', '__name__', '__qualname__', '__doc__']:
|
for replace in ['__module__', '__name__', '__qualname__', '__doc__']:
|
||||||
|
|
|
@ -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
|
# reference any injected objects! This includes not only global code but also
|
||||||
# anything specified at the class level.
|
# 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 ######################################################
|
# Bootstrap-related code ######################################################
|
||||||
_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
|
_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
|
||||||
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin'
|
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin'
|
||||||
|
@ -42,6 +72,8 @@ def _make_relax_case():
|
||||||
return False
|
return False
|
||||||
return _relax_case
|
return _relax_case
|
||||||
|
|
||||||
|
_relax_case = _make_relax_case()
|
||||||
|
|
||||||
|
|
||||||
def _pack_uint32(x):
|
def _pack_uint32(x):
|
||||||
"""Convert a 32-bit integer to little-endian."""
|
"""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__'
|
_PYCACHE = '__pycache__'
|
||||||
_OPT = 'opt-'
|
_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']
|
BYTECODE_SUFFIXES = ['.pyc']
|
||||||
# Deprecated.
|
# Deprecated.
|
||||||
|
@ -469,15 +505,18 @@ def _check_name(method):
|
||||||
raise ImportError('loader for %s cannot handle %s' %
|
raise ImportError('loader for %s cannot handle %s' %
|
||||||
(self.name, name), name=name)
|
(self.name, name), name=name)
|
||||||
return method(self, name, *args, **kwargs)
|
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
|
_wrap = _bootstrap._wrap
|
||||||
except NameError:
|
else:
|
||||||
# XXX yuck
|
|
||||||
def _wrap(new, old):
|
def _wrap(new, old):
|
||||||
for replace in ['__module__', '__name__', '__qualname__', '__doc__']:
|
for replace in ['__module__', '__name__', '__qualname__', '__doc__']:
|
||||||
if hasattr(old, replace):
|
if hasattr(old, replace):
|
||||||
setattr(new, replace, getattr(old, replace))
|
setattr(new, replace, getattr(old, replace))
|
||||||
new.__dict__.update(old.__dict__)
|
new.__dict__.update(old.__dict__)
|
||||||
|
|
||||||
_wrap(_check_name_wrapper, method)
|
_wrap(_check_name_wrapper, method)
|
||||||
return _check_name_wrapper
|
return _check_name_wrapper
|
||||||
|
|
||||||
|
@ -713,7 +752,7 @@ class WindowsRegistryFinder:
|
||||||
REGISTRY_KEY_DEBUG = (
|
REGISTRY_KEY_DEBUG = (
|
||||||
'Software\\Python\\PythonCore\\{sys_version}'
|
'Software\\Python\\PythonCore\\{sys_version}'
|
||||||
'\\Modules\\{fullname}\\Debug')
|
'\\Modules\\{fullname}\\Debug')
|
||||||
DEBUG_BUILD = False # Changed in _setup()
|
DEBUG_BUILD = (_MS_WINDOWS and '_d.pyd' in EXTENSION_SUFFIXES)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _open_registry(cls, key):
|
def _open_registry(cls, key):
|
||||||
|
@ -1060,10 +1099,6 @@ class SourcelessFileLoader(FileLoader, _LoaderBasics):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# Filled in by _setup().
|
|
||||||
EXTENSION_SUFFIXES = []
|
|
||||||
|
|
||||||
|
|
||||||
class ExtensionFileLoader(FileLoader, _LoaderBasics):
|
class ExtensionFileLoader(FileLoader, _LoaderBasics):
|
||||||
|
|
||||||
"""Loader for extension modules.
|
"""Loader for extension modules.
|
||||||
|
@ -1552,66 +1587,14 @@ def _get_supported_file_loaders():
|
||||||
return [extensions, source, bytecode]
|
return [extensions, source, bytecode]
|
||||||
|
|
||||||
|
|
||||||
def _setup(_bootstrap_module):
|
def _set_bootstrap_module(_bootstrap_module):
|
||||||
"""Setup the path-based importers for importlib by importing needed
|
global _bootstrap
|
||||||
built-in modules and injecting them into the global namespace.
|
|
||||||
|
|
||||||
Other components are extracted from the core bootstrap module.
|
|
||||||
|
|
||||||
"""
|
|
||||||
global sys, _imp, _bootstrap
|
|
||||||
_bootstrap = _bootstrap_module
|
_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):
|
def _install(_bootstrap_module):
|
||||||
"""Install the path-based import components."""
|
"""Install the path-based import components."""
|
||||||
_setup(_bootstrap_module)
|
_set_bootstrap_module(_bootstrap_module)
|
||||||
supported_loaders = _get_supported_file_loaders()
|
supported_loaders = _get_supported_file_loaders()
|
||||||
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
|
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
|
||||||
sys.meta_path.append(PathFinder)
|
sys.meta_path.append(PathFinder)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Simplify the :mod:`importlib` external bootstrap code:
|
||||||
|
``importlib._bootstrap_external`` now uses regular imports to import builtin
|
||||||
|
modules. When it is imported, the builtin :func:`__import__()` function is
|
||||||
|
already fully working and so can be used to import builtin modules like
|
||||||
|
:mod:`sys`. Patch by Victor Stinner.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue