diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/tools/python3/src/Lib/importlib/_bootstrap.py | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/tools/python3/src/Lib/importlib/_bootstrap.py')
-rw-r--r-- | contrib/tools/python3/src/Lib/importlib/_bootstrap.py | 1209 |
1 files changed, 0 insertions, 1209 deletions
diff --git a/contrib/tools/python3/src/Lib/importlib/_bootstrap.py b/contrib/tools/python3/src/Lib/importlib/_bootstrap.py deleted file mode 100644 index 527bc9c63c..0000000000 --- a/contrib/tools/python3/src/Lib/importlib/_bootstrap.py +++ /dev/null @@ -1,1209 +0,0 @@ -"""Core implementation of import. - -This module is NOT meant to be directly imported! It has been designed such -that it can be bootstrapped into Python as the implementation of import. As -such it requires the injection of specific modules and attributes in order to -work. One should use importlib as the public-facing version of this module. - -""" -# -# IMPORTANT: Whenever making changes to this module, be sure to run a top-level -# `make regen-importlib` followed by `make` in order to get the frozen version -# of the module updated. Not doing so will result in the Makefile to fail for -# all others who don't have a ./python around to freeze the module -# in the early stages of compilation. -# - -# See importlib._setup() for what is injected into the global namespace. - -# When editing this code be aware that code executed at import time CANNOT -# reference any injected objects! This includes not only global code but also -# anything specified at the class level. - -def _object_name(obj): - try: - return obj.__qualname__ - except AttributeError: - return type(obj).__qualname__ - -# 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__']: - if hasattr(old, replace): - setattr(new, replace, getattr(old, replace)) - new.__dict__.update(old.__dict__) - - -def _new_module(name): - return type(sys)(name) - - -# Module-level locking ######################################################## - -# A dict mapping module names to weakrefs of _ModuleLock instances -# Dictionary protected by the global import lock -_module_locks = {} -# A dict mapping thread ids to _ModuleLock instances -_blocking_on = {} - - -class _DeadlockError(RuntimeError): - pass - - -class _ModuleLock: - """A recursive lock implementation which is able to detect deadlocks - (e.g. thread 1 trying to take locks A then B, and thread 2 trying to - take locks B then A). - """ - - def __init__(self, name): - self.lock = _thread.allocate_lock() - self.wakeup = _thread.allocate_lock() - self.name = name - self.owner = None - self.count = 0 - self.waiters = 0 - - def has_deadlock(self): - # Deadlock avoidance for concurrent circular imports. - me = _thread.get_ident() - tid = self.owner - seen = set() - while True: - lock = _blocking_on.get(tid) - if lock is None: - return False - tid = lock.owner - if tid == me: - return True - if tid in seen: - # bpo 38091: the chain of tid's we encounter here - # eventually leads to a fixpoint or a cycle, but - # does not reach 'me'. This means we would not - # actually deadlock. This can happen if other - # threads are at the beginning of acquire() below. - return False - seen.add(tid) - - def acquire(self): - """ - Acquire the module lock. If a potential deadlock is detected, - a _DeadlockError is raised. - Otherwise, the lock is always acquired and True is returned. - """ - tid = _thread.get_ident() - _blocking_on[tid] = self - try: - while True: - with self.lock: - if self.count == 0 or self.owner == tid: - self.owner = tid - self.count += 1 - return True - if self.has_deadlock(): - raise _DeadlockError('deadlock detected by %r' % self) - if self.wakeup.acquire(False): - self.waiters += 1 - # Wait for a release() call - self.wakeup.acquire() - self.wakeup.release() - finally: - del _blocking_on[tid] - - def release(self): - tid = _thread.get_ident() - with self.lock: - if self.owner != tid: - raise RuntimeError('cannot release un-acquired lock') - assert self.count > 0 - self.count -= 1 - if self.count == 0: - self.owner = None - if self.waiters: - self.waiters -= 1 - self.wakeup.release() - - def __repr__(self): - return '_ModuleLock({!r}) at {}'.format(self.name, id(self)) - - -class _DummyModuleLock: - """A simple _ModuleLock equivalent for Python builds without - multi-threading support.""" - - def __init__(self, name): - self.name = name - self.count = 0 - - def acquire(self): - self.count += 1 - return True - - def release(self): - if self.count == 0: - raise RuntimeError('cannot release un-acquired lock') - self.count -= 1 - - def __repr__(self): - return '_DummyModuleLock({!r}) at {}'.format(self.name, id(self)) - - -class _ModuleLockManager: - - def __init__(self, name): - self._name = name - self._lock = None - - def __enter__(self): - self._lock = _get_module_lock(self._name) - self._lock.acquire() - - def __exit__(self, *args, **kwargs): - self._lock.release() - - -# The following two functions are for consumption by Python/import.c. - -def _get_module_lock(name): - """Get or create the module lock for a given module name. - - Acquire/release internally the global import lock to protect - _module_locks.""" - - _imp.acquire_lock() - try: - try: - lock = _module_locks[name]() - except KeyError: - lock = None - - if lock is None: - if _thread is None: - lock = _DummyModuleLock(name) - else: - lock = _ModuleLock(name) - - def cb(ref, name=name): - _imp.acquire_lock() - try: - # bpo-31070: Check if another thread created a new lock - # after the previous lock was destroyed - # but before the weakref callback was called. - if _module_locks.get(name) is ref: - del _module_locks[name] - finally: - _imp.release_lock() - - _module_locks[name] = _weakref.ref(lock, cb) - finally: - _imp.release_lock() - - return lock - - -def _lock_unlock_module(name): - """Acquires then releases the module lock for a given module name. - - This is used to ensure a module is completely initialized, in the - event it is being imported by another thread. - """ - lock = _get_module_lock(name) - try: - lock.acquire() - except _DeadlockError: - # Concurrent circular import, we'll accept a partially initialized - # module object. - pass - else: - lock.release() - -# Frame stripping magic ############################################### -def _call_with_frames_removed(f, *args, **kwds): - """remove_importlib_frames in import.c will always remove sequences - of importlib frames that end with a call to this function - - Use it instead of a normal call in places where including the importlib - frames introduces unwanted noise into the traceback (e.g. when executing - module code) - """ - return f(*args, **kwds) - - -def _verbose_message(message, *args, verbosity=1): - """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" - if sys.flags.verbose >= verbosity: - if not message.startswith(('#', 'import ')): - message = '# ' + message - print(message.format(*args), file=sys.stderr) - - -def _requires_builtin(fxn): - """Decorator to verify the named module is built-in.""" - def _requires_builtin_wrapper(self, fullname): - if fullname not in sys.builtin_module_names: - raise ImportError('{!r} is not a built-in module'.format(fullname), - name=fullname) - return fxn(self, fullname) - _wrap(_requires_builtin_wrapper, fxn) - return _requires_builtin_wrapper - - -def _requires_frozen(fxn): - """Decorator to verify the named module is frozen.""" - def _requires_frozen_wrapper(self, fullname): - if not _imp.is_frozen(fullname): - raise ImportError('{!r} is not a frozen module'.format(fullname), - name=fullname) - return fxn(self, fullname) - _wrap(_requires_frozen_wrapper, fxn) - return _requires_frozen_wrapper - - -# Typically used by loader classes as a method replacement. -def _load_module_shim(self, fullname): - """Load the specified module into sys.modules and return it. - - This method is deprecated. Use loader.exec_module() instead. - - """ - msg = ("the load_module() method is deprecated and slated for removal in " - "Python 3.12; use exec_module() instead") - _warnings.warn(msg, DeprecationWarning) - spec = spec_from_loader(fullname, self) - if fullname in sys.modules: - module = sys.modules[fullname] - _exec(spec, module) - return sys.modules[fullname] - else: - return _load(spec) - -# Module specifications ####################################################### - -def _module_repr(module): - """The implementation of ModuleType.__repr__().""" - loader = getattr(module, '__loader__', None) - if spec := getattr(module, "__spec__", None): - return _module_repr_from_spec(spec) - elif hasattr(loader, 'module_repr'): - try: - return loader.module_repr(module) - except Exception: - pass - # Fall through to a catch-all which always succeeds. - try: - name = module.__name__ - except AttributeError: - name = '?' - try: - filename = module.__file__ - except AttributeError: - if loader is None: - return '<module {!r}>'.format(name) - else: - return '<module {!r} ({!r})>'.format(name, loader) - else: - return '<module {!r} from {!r}>'.format(name, filename) - - -class ModuleSpec: - """The specification for a module, used for loading. - - A module's spec is the source for information about the module. For - data associated with the module, including source, use the spec's - loader. - - `name` is the absolute name of the module. `loader` is the loader - to use when loading the module. `parent` is the name of the - package the module is in. The parent is derived from the name. - - `is_package` determines if the module is considered a package or - not. On modules this is reflected by the `__path__` attribute. - - `origin` is the specific location used by the loader from which to - load the module, if that information is available. When filename is - set, origin will match. - - `has_location` indicates that a spec's "origin" reflects a location. - When this is True, `__file__` attribute of the module is set. - - `cached` is the location of the cached bytecode file, if any. It - corresponds to the `__cached__` attribute. - - `submodule_search_locations` is the sequence of path entries to - search when importing submodules. If set, is_package should be - True--and False otherwise. - - Packages are simply modules that (may) have submodules. If a spec - has a non-None value in `submodule_search_locations`, the import - system will consider modules loaded from the spec as packages. - - Only finders (see importlib.abc.MetaPathFinder and - importlib.abc.PathEntryFinder) should modify ModuleSpec instances. - - """ - - def __init__(self, name, loader, *, origin=None, loader_state=None, - is_package=None): - self.name = name - self.loader = loader - self.origin = origin - self.loader_state = loader_state - self.submodule_search_locations = [] if is_package else None - - # file-location attributes - self._set_fileattr = False - self._cached = None - - def __repr__(self): - args = ['name={!r}'.format(self.name), - 'loader={!r}'.format(self.loader)] - if self.origin is not None: - args.append('origin={!r}'.format(self.origin)) - if self.submodule_search_locations is not None: - args.append('submodule_search_locations={}' - .format(self.submodule_search_locations)) - return '{}({})'.format(self.__class__.__name__, ', '.join(args)) - - def __eq__(self, other): - smsl = self.submodule_search_locations - try: - return (self.name == other.name and - self.loader == other.loader and - self.origin == other.origin and - smsl == other.submodule_search_locations and - self.cached == other.cached and - self.has_location == other.has_location) - except AttributeError: - return NotImplemented - - @property - def cached(self): - if self._cached is None: - if self.origin is not None and self._set_fileattr: - if _bootstrap_external is None: - raise NotImplementedError - self._cached = _bootstrap_external._get_cached(self.origin) - return self._cached - - @cached.setter - def cached(self, cached): - self._cached = cached - - @property - def parent(self): - """The name of the module's parent.""" - if self.submodule_search_locations is None: - return self.name.rpartition('.')[0] - else: - return self.name - - @property - def has_location(self): - return self._set_fileattr - - @has_location.setter - def has_location(self, value): - self._set_fileattr = bool(value) - - -def spec_from_loader(name, loader, *, origin=None, is_package=None): - """Return a module spec based on various loader methods.""" - if hasattr(loader, 'get_filename'): - if _bootstrap_external is None: - raise NotImplementedError - spec_from_file_location = _bootstrap_external.spec_from_file_location - - if is_package is None: - return spec_from_file_location(name, loader=loader) - search = [] if is_package else None - return spec_from_file_location(name, loader=loader, - submodule_search_locations=search) - - if is_package is None: - if hasattr(loader, 'is_package'): - try: - is_package = loader.is_package(name) - except ImportError: - is_package = None # aka, undefined - else: - # the default - is_package = False - - return ModuleSpec(name, loader, origin=origin, is_package=is_package) - - -def _spec_from_module(module, loader=None, origin=None): - # This function is meant for use in _setup(). - try: - spec = module.__spec__ - except AttributeError: - pass - else: - if spec is not None: - return spec - - name = module.__name__ - if loader is None: - try: - loader = module.__loader__ - except AttributeError: - # loader will stay None. - pass - try: - location = module.__file__ - except AttributeError: - location = None - if origin is None: - if location is None: - try: - origin = loader._ORIGIN - except AttributeError: - origin = None - else: - origin = location - try: - cached = module.__cached__ - except AttributeError: - cached = None - try: - submodule_search_locations = list(module.__path__) - except AttributeError: - submodule_search_locations = None - - spec = ModuleSpec(name, loader, origin=origin) - spec._set_fileattr = False if location is None else True - spec.cached = cached - spec.submodule_search_locations = submodule_search_locations - return spec - - -def _init_module_attrs(spec, module, *, override=False): - # The passed-in module may be not support attribute assignment, - # in which case we simply don't set the attributes. - # __name__ - if (override or getattr(module, '__name__', None) is None): - try: - module.__name__ = spec.name - except AttributeError: - pass - # __loader__ - if override or getattr(module, '__loader__', None) is None: - loader = spec.loader - if loader is None: - # A backward compatibility hack. - if spec.submodule_search_locations is not None: - if _bootstrap_external is None: - raise NotImplementedError - _NamespaceLoader = _bootstrap_external._NamespaceLoader - - loader = _NamespaceLoader.__new__(_NamespaceLoader) - loader._path = spec.submodule_search_locations - spec.loader = loader - # While the docs say that module.__file__ is not set for - # built-in modules, and the code below will avoid setting it if - # spec.has_location is false, this is incorrect for namespace - # packages. Namespace packages have no location, but their - # __spec__.origin is None, and thus their module.__file__ - # should also be None for consistency. While a bit of a hack, - # this is the best place to ensure this consistency. - # - # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module - # and bpo-32305 - module.__file__ = None - try: - module.__loader__ = loader - except AttributeError: - pass - # __package__ - if override or getattr(module, '__package__', None) is None: - try: - module.__package__ = spec.parent - except AttributeError: - pass - # __spec__ - try: - module.__spec__ = spec - except AttributeError: - pass - # __path__ - if override or getattr(module, '__path__', None) is None: - if spec.submodule_search_locations is not None: - try: - module.__path__ = spec.submodule_search_locations - except AttributeError: - pass - # __file__/__cached__ - if spec.has_location: - if override or getattr(module, '__file__', None) is None: - try: - module.__file__ = spec.origin - except AttributeError: - pass - - if override or getattr(module, '__cached__', None) is None: - if spec.cached is not None: - try: - module.__cached__ = spec.cached - except AttributeError: - pass - return module - - -def module_from_spec(spec): - """Create a module based on the provided spec.""" - # Typically loaders will not implement create_module(). - module = None - if hasattr(spec.loader, 'create_module'): - # If create_module() returns `None` then it means default - # module creation should be used. - module = spec.loader.create_module(spec) - elif hasattr(spec.loader, 'exec_module'): - raise ImportError('loaders that define exec_module() ' - 'must also define create_module()') - if module is None: - module = _new_module(spec.name) - _init_module_attrs(spec, module) - return module - - -def _module_repr_from_spec(spec): - """Return the repr to use for the module.""" - # We mostly replicate _module_repr() using the spec attributes. - name = '?' if spec.name is None else spec.name - if spec.origin is None: - if spec.loader is None: - return '<module {!r}>'.format(name) - else: - return '<module {!r} ({!r})>'.format(name, spec.loader) - else: - if spec.has_location: - return '<module {!r} from {!r}>'.format(name, spec.origin) - else: - return '<module {!r} ({})>'.format(spec.name, spec.origin) - - -# Used by importlib.reload() and _load_module_shim(). -def _exec(spec, module): - """Execute the spec's specified module in an existing module's namespace.""" - name = spec.name - with _ModuleLockManager(name): - if sys.modules.get(name) is not module: - msg = 'module {!r} not in sys.modules'.format(name) - raise ImportError(msg, name=name) - try: - if spec.loader is None: - if spec.submodule_search_locations is None: - raise ImportError('missing loader', name=spec.name) - # Namespace package. - _init_module_attrs(spec, module, override=True) - else: - _init_module_attrs(spec, module, override=True) - if not hasattr(spec.loader, 'exec_module'): - msg = (f"{_object_name(spec.loader)}.exec_module() not found; " - "falling back to load_module()") - _warnings.warn(msg, ImportWarning) - spec.loader.load_module(name) - else: - spec.loader.exec_module(module) - finally: - # Update the order of insertion into sys.modules for module - # clean-up at shutdown. - module = sys.modules.pop(spec.name) - sys.modules[spec.name] = module - return module - - -def _load_backward_compatible(spec): - # It is assumed that all callers have been warned about using load_module() - # appropriately before calling this function. - try: - spec.loader.load_module(spec.name) - except: - if spec.name in sys.modules: - module = sys.modules.pop(spec.name) - sys.modules[spec.name] = module - raise - # The module must be in sys.modules at this point! - # Move it to the end of sys.modules. - module = sys.modules.pop(spec.name) - sys.modules[spec.name] = module - if getattr(module, '__loader__', None) is None: - try: - module.__loader__ = spec.loader - except AttributeError: - pass - if getattr(module, '__package__', None) is None: - try: - # Since module.__path__ may not line up with - # spec.submodule_search_paths, we can't necessarily rely - # on spec.parent here. - module.__package__ = module.__name__ - if not hasattr(module, '__path__'): - module.__package__ = spec.name.rpartition('.')[0] - except AttributeError: - pass - if getattr(module, '__spec__', None) is None: - try: - module.__spec__ = spec - except AttributeError: - pass - return module - -def _load_unlocked(spec): - # A helper for direct use by the import system. - if spec.loader is not None: - # Not a namespace package. - if not hasattr(spec.loader, 'exec_module'): - msg = (f"{_object_name(spec.loader)}.exec_module() not found; " - "falling back to load_module()") - _warnings.warn(msg, ImportWarning) - return _load_backward_compatible(spec) - - module = module_from_spec(spec) - - # This must be done before putting the module in sys.modules - # (otherwise an optimization shortcut in import.c becomes - # wrong). - spec._initializing = True - try: - sys.modules[spec.name] = module - try: - if spec.loader is None: - if spec.submodule_search_locations is None: - raise ImportError('missing loader', name=spec.name) - # A namespace package so do nothing. - else: - spec.loader.exec_module(module) - except: - try: - del sys.modules[spec.name] - except KeyError: - pass - raise - # Move the module to the end of sys.modules. - # We don't ensure that the import-related module attributes get - # set in the sys.modules replacement case. Such modules are on - # their own. - module = sys.modules.pop(spec.name) - sys.modules[spec.name] = module - _verbose_message('import {!r} # {!r}', spec.name, spec.loader) - finally: - spec._initializing = False - - return module - -# A method used during testing of _load_unlocked() and by -# _load_module_shim(). -def _load(spec): - """Return a new module object, loaded by the spec's loader. - - The module is not added to its parent. - - If a module is already in sys.modules, that existing module gets - clobbered. - - """ - with _ModuleLockManager(spec.name): - return _load_unlocked(spec) - - -# Loaders ##################################################################### - -class BuiltinImporter: - - """Meta path import for built-in modules. - - All methods are either class or static methods to avoid the need to - instantiate the class. - - """ - - _ORIGIN = "built-in" - - @staticmethod - def module_repr(module): - """Return repr for the module. - - The method is deprecated. The import machinery does the job itself. - - """ - _warnings.warn("BuiltinImporter.module_repr() is deprecated and " - "slated for removal in Python 3.12", DeprecationWarning) - return f'<module {module.__name__!r} ({BuiltinImporter._ORIGIN})>' - - @classmethod - def find_spec(cls, fullname, path=None, target=None): - if path is not None: - return None - if _imp.is_builtin(fullname): - return spec_from_loader(fullname, cls, origin=cls._ORIGIN) - else: - return None - - @classmethod - def find_module(cls, fullname, path=None): - """Find the built-in module. - - If 'path' is ever specified then the search is considered a failure. - - This method is deprecated. Use find_spec() instead. - - """ - _warnings.warn("BuiltinImporter.find_module() is deprecated and " - "slated for removal in Python 3.12; use find_spec() instead", - DeprecationWarning) - spec = cls.find_spec(fullname, path) - return spec.loader if spec is not None else None - - @staticmethod - def create_module(spec): - """Create a built-in module""" - if spec.name not in sys.builtin_module_names: - raise ImportError('{!r} is not a built-in module'.format(spec.name), - name=spec.name) - return _call_with_frames_removed(_imp.create_builtin, spec) - - @staticmethod - def exec_module(module): - """Exec a built-in module""" - _call_with_frames_removed(_imp.exec_builtin, module) - - @classmethod - @_requires_builtin - def get_code(cls, fullname): - """Return None as built-in modules do not have code objects.""" - return None - - @classmethod - @_requires_builtin - def get_source(cls, fullname): - """Return None as built-in modules do not have source code.""" - return None - - @classmethod - @_requires_builtin - def is_package(cls, fullname): - """Return False as built-in modules are never packages.""" - return False - - load_module = classmethod(_load_module_shim) - - -class FrozenImporter: - - """Meta path import for frozen modules. - - All methods are either class or static methods to avoid the need to - instantiate the class. - - """ - - _ORIGIN = "frozen" - - @staticmethod - def module_repr(m): - """Return repr for the module. - - The method is deprecated. The import machinery does the job itself. - - """ - _warnings.warn("FrozenImporter.module_repr() is deprecated and " - "slated for removal in Python 3.12", DeprecationWarning) - return '<module {!r} ({})>'.format(m.__name__, FrozenImporter._ORIGIN) - - @classmethod - def find_spec(cls, fullname, path=None, target=None): - if _imp.is_frozen(fullname): - return spec_from_loader(fullname, cls, origin=cls._ORIGIN) - else: - return None - - @classmethod - def find_module(cls, fullname, path=None): - """Find a frozen module. - - This method is deprecated. Use find_spec() instead. - - """ - _warnings.warn("FrozenImporter.find_module() is deprecated and " - "slated for removal in Python 3.12; use find_spec() instead", - DeprecationWarning) - return cls if _imp.is_frozen(fullname) else None - - @staticmethod - def create_module(spec): - """Use default semantics for module creation.""" - - @staticmethod - def exec_module(module): - name = module.__spec__.name - if not _imp.is_frozen(name): - raise ImportError('{!r} is not a frozen module'.format(name), - name=name) - code = _call_with_frames_removed(_imp.get_frozen_object, name) - exec(code, module.__dict__) - - @classmethod - def load_module(cls, fullname): - """Load a frozen module. - - This method is deprecated. Use exec_module() instead. - - """ - # Warning about deprecation implemented in _load_module_shim(). - return _load_module_shim(cls, fullname) - - @classmethod - @_requires_frozen - def get_code(cls, fullname): - """Return the code object for the frozen module.""" - return _imp.get_frozen_object(fullname) - - @classmethod - @_requires_frozen - def get_source(cls, fullname): - """Return None as frozen modules do not have source code.""" - return None - - @classmethod - @_requires_frozen - def is_package(cls, fullname): - """Return True if the frozen module is a package.""" - return _imp.is_frozen_package(fullname) - - -# Import itself ############################################################### - -class _ImportLockContext: - - """Context manager for the import lock.""" - - def __enter__(self): - """Acquire the import lock.""" - _imp.acquire_lock() - - def __exit__(self, exc_type, exc_value, exc_traceback): - """Release the import lock regardless of any raised exceptions.""" - _imp.release_lock() - - -def _resolve_name(name, package, level): - """Resolve a relative module name to an absolute one.""" - bits = package.rsplit('.', level - 1) - if len(bits) < level: - raise ImportError('attempted relative import beyond top-level package') - base = bits[0] - return '{}.{}'.format(base, name) if name else base - - -def _find_spec_legacy(finder, name, path): - msg = (f"{_object_name(finder)}.find_spec() not found; " - "falling back to find_module()") - _warnings.warn(msg, ImportWarning) - loader = finder.find_module(name, path) - if loader is None: - return None - return spec_from_loader(name, loader) - - -def _find_spec(name, path, target=None): - """Find a module's spec.""" - meta_path = sys.meta_path - if meta_path is None: - # PyImport_Cleanup() is running or has been called. - raise ImportError("sys.meta_path is None, Python is likely " - "shutting down") - - if not meta_path: - _warnings.warn('sys.meta_path is empty', ImportWarning) - - # We check sys.modules here for the reload case. While a passed-in - # target will usually indicate a reload there is no guarantee, whereas - # sys.modules provides one. - is_reload = name in sys.modules - for finder in meta_path: - with _ImportLockContext(): - try: - find_spec = finder.find_spec - except AttributeError: - spec = _find_spec_legacy(finder, name, path) - if spec is None: - continue - else: - spec = find_spec(name, path, target) - if spec is not None: - # The parent import may have already imported this module. - if not is_reload and name in sys.modules: - module = sys.modules[name] - try: - __spec__ = module.__spec__ - except AttributeError: - # We use the found spec since that is the one that - # we would have used if the parent module hadn't - # beaten us to the punch. - return spec - else: - if __spec__ is None: - return spec - else: - return __spec__ - else: - return spec - else: - return None - - -def _sanity_check(name, package, level): - """Verify arguments are "sane".""" - if not isinstance(name, str): - raise TypeError('module name must be str, not {}'.format(type(name))) - if level < 0: - raise ValueError('level must be >= 0') - if level > 0: - if not isinstance(package, str): - raise TypeError('__package__ not set to a string') - elif not package: - raise ImportError('attempted relative import with no known parent ' - 'package') - if not name and level == 0: - raise ValueError('Empty module name') - - -_ERR_MSG_PREFIX = 'No module named ' -_ERR_MSG = _ERR_MSG_PREFIX + '{!r}' - -def _find_and_load_unlocked(name, import_): - path = None - parent = name.rpartition('.')[0] - if parent: - if parent not in sys.modules: - _call_with_frames_removed(import_, parent) - # Crazy side-effects! - if name in sys.modules: - return sys.modules[name] - parent_module = sys.modules[parent] - try: - path = parent_module.__path__ - except AttributeError: - msg = (_ERR_MSG + '; {!r} is not a package').format(name, parent) - raise ModuleNotFoundError(msg, name=name) from None - spec = _find_spec(name, path) - if spec is None: - raise ModuleNotFoundError(_ERR_MSG.format(name), name=name) - else: - module = _load_unlocked(spec) - if parent: - # Set the module as an attribute on its parent. - parent_module = sys.modules[parent] - child = name.rpartition('.')[2] - try: - setattr(parent_module, child, module) - except AttributeError: - msg = f"Cannot set an attribute on {parent!r} for child module {child!r}" - _warnings.warn(msg, ImportWarning) - return module - - -_NEEDS_LOADING = object() - - -def _find_and_load(name, import_): - """Find and load the module.""" - with _ModuleLockManager(name): - module = sys.modules.get(name, _NEEDS_LOADING) - if module is _NEEDS_LOADING: - return _find_and_load_unlocked(name, import_) - - if module is None: - message = ('import of {} halted; ' - 'None in sys.modules'.format(name)) - raise ModuleNotFoundError(message, name=name) - - _lock_unlock_module(name) - return module - - -def _gcd_import(name, package=None, level=0): - """Import and return the module based on its name, the package the call is - being made from, and the level adjustment. - - This function represents the greatest common denominator of functionality - between import_module and __import__. This includes setting __package__ if - the loader did not. - - """ - _sanity_check(name, package, level) - if level > 0: - name = _resolve_name(name, package, level) - return _find_and_load(name, _gcd_import) - - -def _handle_fromlist(module, fromlist, import_, *, recursive=False): - """Figure out what __import__ should return. - - The import_ parameter is a callable which takes the name of module to - import. It is required to decouple the function from assuming importlib's - import implementation is desired. - - """ - # The hell that is fromlist ... - # If a package was imported, try to import stuff from fromlist. - for x in fromlist: - if not isinstance(x, str): - if recursive: - where = module.__name__ + '.__all__' - else: - where = "``from list''" - raise TypeError(f"Item in {where} must be str, " - f"not {type(x).__name__}") - elif x == '*': - if not recursive and hasattr(module, '__all__'): - _handle_fromlist(module, module.__all__, import_, - recursive=True) - elif not hasattr(module, x): - from_name = '{}.{}'.format(module.__name__, x) - try: - _call_with_frames_removed(import_, from_name) - except ModuleNotFoundError as exc: - # Backwards-compatibility dictates we ignore failed - # imports triggered by fromlist for modules that don't - # exist. - if (exc.name == from_name and - sys.modules.get(from_name, _NEEDS_LOADING) is not None): - continue - raise - return module - - -def _calc___package__(globals): - """Calculate what __package__ should be. - - __package__ is not guaranteed to be defined or could be set to None - to represent that its proper value is unknown. - - """ - package = globals.get('__package__') - spec = globals.get('__spec__') - if package is not None: - if spec is not None and package != spec.parent: - _warnings.warn("__package__ != __spec__.parent " - f"({package!r} != {spec.parent!r})", - ImportWarning, stacklevel=3) - return package - elif spec is not None: - return spec.parent - else: - _warnings.warn("can't resolve package from __spec__ or __package__, " - "falling back on __name__ and __path__", - ImportWarning, stacklevel=3) - package = globals['__name__'] - if '__path__' not in globals: - package = package.rpartition('.')[0] - return package - - -def __import__(name, globals=None, locals=None, fromlist=(), level=0): - """Import a module. - - The 'globals' argument is used to infer where the import is occurring from - to handle relative imports. The 'locals' argument is ignored. The - 'fromlist' argument specifies what should exist as attributes on the module - being imported (e.g. ``from module import <fromlist>``). The 'level' - argument represents the package location to import from in a relative - import (e.g. ``from ..pkg import mod`` would have a 'level' of 2). - - """ - if level == 0: - module = _gcd_import(name) - else: - globals_ = globals if globals is not None else {} - package = _calc___package__(globals_) - module = _gcd_import(name, package, level) - if not fromlist: - # Return up to the first dot in 'name'. This is complicated by the fact - # that 'name' may be relative. - if level == 0: - return _gcd_import(name.partition('.')[0]) - elif not name: - return module - else: - # Figure out where to slice the module's name up to the first dot - # in 'name'. - cut_off = len(name) - len(name.partition('.')[0]) - # Slice end needs to be positive to alleviate need to special-case - # when ``'.' not in name``. - return sys.modules[module.__name__[:len(module.__name__)-cut_off]] - elif hasattr(module, '__path__'): - return _handle_fromlist(module, fromlist, _gcd_import) - else: - return module - - -def _builtin_from_name(name): - spec = BuiltinImporter.find_spec(name) - if spec is None: - raise ImportError('no built-in module named ' + name) - return _load_unlocked(spec) - - -def _setup(sys_module, _imp_module): - """Setup importlib by importing needed built-in modules and injecting them - into the global namespace. - - As sys is needed for sys.modules access and _imp is needed to load built-in - modules, those two modules must be explicitly passed in. - - """ - global _imp, sys - _imp = _imp_module - sys = sys_module - - # Set up the spec for existing builtin/frozen modules. - module_type = type(sys) - for name, module in sys.modules.items(): - if isinstance(module, module_type): - if name in sys.builtin_module_names: - loader = BuiltinImporter - elif _imp.is_frozen(name): - loader = FrozenImporter - else: - continue - spec = _spec_from_module(module, loader) - _init_module_attrs(spec, module) - - # Directly load built-in modules needed during bootstrap. - self_module = sys.modules[__name__] - for builtin_name in ('_thread', '_warnings', '_weakref'): - if builtin_name not in sys.modules: - builtin_module = _builtin_from_name(builtin_name) - else: - builtin_module = sys.modules[builtin_name] - setattr(self_module, builtin_name, builtin_module) - - -def _install(sys_module, _imp_module): - """Install importers for builtin and frozen modules""" - _setup(sys_module, _imp_module) - - sys.meta_path.append(BuiltinImporter) - sys.meta_path.append(FrozenImporter) - - -def _install_external_importers(): - """Install importers that require external filesystem access""" - global _bootstrap_external - import _frozen_importlib_external - _bootstrap_external = _frozen_importlib_external - _frozen_importlib_external._install(sys.modules[__name__]) |