mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
Do a little bit of reorganization on importlib._bootstrap.
This commit is contained in:
parent
3eeaa0a821
commit
ce43ddfee5
1 changed files with 69 additions and 58 deletions
|
@ -16,6 +16,8 @@ work. One should use importlib as the public-facing version of this module.
|
|||
# anything specified at the class level.
|
||||
|
||||
|
||||
# Bootstrap-related code ######################################################
|
||||
|
||||
# XXX Could also expose Modules/getpath.c:joinpath()
|
||||
def _path_join(*args):
|
||||
"""Replacement for os.path.join."""
|
||||
|
@ -97,6 +99,8 @@ def _wrap(new, old):
|
|||
new.__dict__.update(old.__dict__)
|
||||
|
||||
|
||||
# Finder/loader utility code ##################################################
|
||||
|
||||
def set_package(fxn):
|
||||
"""Set __package__ on the returned module."""
|
||||
def wrapper(*args, **kwargs):
|
||||
|
@ -121,6 +125,56 @@ def set_loader(fxn):
|
|||
return wrapper
|
||||
|
||||
|
||||
def module_for_loader(fxn):
|
||||
"""Decorator to handle selecting the proper module for loaders.
|
||||
|
||||
Decorated modules are passed the module to use instead of the module name.
|
||||
The module is either from sys.modules if it already exists (for reloading)
|
||||
or is a new module which has __name__ set. If any exception is raised by
|
||||
the decorated method and the decorator added a module to sys.modules, then
|
||||
the module is deleted from sys.modules.
|
||||
|
||||
The decorator assumes that the decorated method takes self/cls as a first
|
||||
argument and the module as the second argument.
|
||||
|
||||
"""
|
||||
def decorated(self, fullname):
|
||||
module = sys.modules.get(fullname)
|
||||
is_reload = bool(module)
|
||||
if not is_reload:
|
||||
# This must be done before open() is called as the 'io' module
|
||||
# implicitly imports 'locale' and would otherwise trigger an
|
||||
# infinite loop.
|
||||
module = imp.new_module(fullname)
|
||||
sys.modules[fullname] = module
|
||||
try:
|
||||
return fxn(self, module)
|
||||
except:
|
||||
if not is_reload:
|
||||
del sys.modules[fullname]
|
||||
raise
|
||||
_wrap(decorated, fxn)
|
||||
return decorated
|
||||
|
||||
|
||||
def _check_name(method):
|
||||
"""Decorator to verify that the module being requested matches the one the
|
||||
loader can handle.
|
||||
|
||||
The first argument (self) must define _name which the second argument is
|
||||
comapred against. If the comparison fails then ImportError is raised.
|
||||
|
||||
"""
|
||||
def inner(self, name, *args, **kwargs):
|
||||
if self._name != name:
|
||||
raise ImportError("loader cannot handle %s" % name)
|
||||
return method(self, name, *args, **kwargs)
|
||||
_wrap(inner, method)
|
||||
return inner
|
||||
|
||||
|
||||
# Finders/loaders #############################################################
|
||||
|
||||
class BuiltinImporter:
|
||||
|
||||
"""Meta path loader for built-in modules.
|
||||
|
@ -224,21 +278,6 @@ class _ChainedFinder:
|
|||
return None
|
||||
|
||||
|
||||
def _check_name(method):
|
||||
"""Decorator to verify that the module being requested matches the one the
|
||||
loader can handle.
|
||||
|
||||
The first argument (self) must define _name which the second argument is
|
||||
comapred against. If the comparison fails then ImportError is raised.
|
||||
|
||||
"""
|
||||
def inner(self, name, *args, **kwargs):
|
||||
if self._name != name:
|
||||
raise ImportError("loader cannot handle %s" % name)
|
||||
return method(self, name, *args, **kwargs)
|
||||
_wrap(inner, method)
|
||||
return inner
|
||||
|
||||
|
||||
class _ExtensionFileLoader:
|
||||
|
||||
|
@ -295,37 +334,6 @@ def _suffix_list(suffix_type):
|
|||
if suffix[2] == suffix_type]
|
||||
|
||||
|
||||
def module_for_loader(fxn):
|
||||
"""Decorator to handle selecting the proper module for loaders.
|
||||
|
||||
Decorated modules are passed the module to use instead of the module name.
|
||||
The module is either from sys.modules if it already exists (for reloading)
|
||||
or is a new module which has __name__ set. If any exception is raised by
|
||||
the decorated method and the decorator added a module to sys.modules, then
|
||||
the module is deleted from sys.modules.
|
||||
|
||||
The decorator assumes that the decorated method takes self/cls as a first
|
||||
argument and the module as the second argument.
|
||||
|
||||
"""
|
||||
def decorated(self, fullname):
|
||||
module = sys.modules.get(fullname)
|
||||
is_reload = bool(module)
|
||||
if not is_reload:
|
||||
# This must be done before open() is called as the 'io' module
|
||||
# implicitly imports 'locale' and would otherwise trigger an
|
||||
# infinite loop.
|
||||
module = imp.new_module(fullname)
|
||||
sys.modules[fullname] = module
|
||||
try:
|
||||
return fxn(self, module)
|
||||
except:
|
||||
if not is_reload:
|
||||
del sys.modules[fullname]
|
||||
raise
|
||||
_wrap(decorated, fxn)
|
||||
return decorated
|
||||
|
||||
|
||||
class PyLoader:
|
||||
|
||||
|
@ -738,6 +746,21 @@ class PathFinder:
|
|||
return None
|
||||
|
||||
|
||||
# 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()
|
||||
|
||||
|
||||
_DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder)
|
||||
|
||||
class _DefaultPathFinder(PathFinder):
|
||||
|
@ -761,18 +784,6 @@ class _DefaultPathFinder(PathFinder):
|
|||
return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK)
|
||||
|
||||
|
||||
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()
|
||||
|
||||
|
||||
_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder]
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue