summaryrefslogtreecommitdiffstats
path: root/Lib/importlib
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-11-19 12:43:43 (GMT)
committerGitHub <noreply@github.com>2020-11-19 12:43:43 (GMT)
commit3390347aa036404453213d589fe1e35902e55fd4 (patch)
tree49309f502a12cfece7b30190f3f36a8ab1143d46 /Lib/importlib
parent7d9d25dbedfffce61fc76bc7ccbfa9ae901bf56f (diff)
downloadcpython-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__.py2
-rw-r--r--Lib/importlib/_bootstrap.py7
-rw-r--r--Lib/importlib/_bootstrap_external.py111
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)