summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/importlib/_bootstrap.py345
1 files changed, 173 insertions, 172 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index 0383c9a..c5588e0 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -173,7 +173,13 @@ def _check_name(method):
return inner
-# Finders/loaders #############################################################
+def _suffix_list(suffix_type):
+ """Return a list of file suffixes based on the imp file type."""
+ return [suffix[0] for suffix in imp.get_suffixes()
+ if suffix[2] == suffix_type]
+
+
+# Loaders #####################################################################
class BuiltinImporter:
@@ -241,100 +247,6 @@ class FrozenImporter:
raise
-def _chained_path_hook(*path_hooks):
- """Create a closure which sequentially checks path hooks to see which ones
- (if any) can work with a path."""
- def path_hook(entry):
- """Check to see if 'entry' matches any of the enclosed path hooks."""
- finders = []
- for hook in path_hooks:
- try:
- finder = hook(entry)
- except ImportError:
- continue
- else:
- finders.append(finder)
- if not finders:
- raise ImportError("no finder found")
- else:
- return _ChainedFinder(*finders)
-
- return path_hook
-
-
-class _ChainedFinder:
-
- """Finder that sequentially calls other finders."""
-
- def __init__(self, *finders):
- self._finders = finders
-
- def find_module(self, fullname, path=None):
- for finder in self._finders:
- result = finder.find_module(fullname, path)
- if result:
- return result
- else:
- return None
-
-
-
-class _ExtensionFileLoader:
-
- """Loader for extension modules.
-
- The constructor is designed to work with FileFinder.
-
- """
-
- def __init__(self, name, path, is_pkg):
- """Initialize the loader.
-
- If is_pkg is True then an exception is raised as extension modules
- cannot be the __init__ module for an extension module.
-
- """
- self._name = name
- self._path = path
- if is_pkg:
- raise ValueError("extension modules cannot be packages")
-
- @_check_name
- @set_package
- @set_loader
- def load_module(self, fullname):
- """Load an extension module."""
- is_reload = fullname in sys.modules
- try:
- return imp.load_dynamic(fullname, self._path)
- except:
- if not is_reload and fullname in sys.modules:
- del sys.modules[fullname]
- raise
-
- @_check_name
- def is_package(self, fullname):
- """Return False as an extension module can never be a package."""
- return False
-
- @_check_name
- def get_code(self, fullname):
- """Return None as an extension module cannot create a code object."""
- return None
-
- @_check_name
- def get_source(self, fullname):
- """Return None as extension modules have no source code."""
- return None
-
-
-def _suffix_list(suffix_type):
- """Return a list of file suffixes based on the imp file type."""
- return [suffix[0] for suffix in imp.get_suffixes()
- if suffix[2] == suffix_type]
-
-
-
class PyLoader:
"""Loader base class for Python source.
@@ -584,6 +496,136 @@ class PyPycFileLoader(PyPycLoader, PyFileLoader):
raise
+class _ExtensionFileLoader:
+
+ """Loader for extension modules.
+
+ The constructor is designed to work with FileFinder.
+
+ """
+
+ def __init__(self, name, path, is_pkg):
+ """Initialize the loader.
+
+ If is_pkg is True then an exception is raised as extension modules
+ cannot be the __init__ module for an extension module.
+
+ """
+ self._name = name
+ self._path = path
+ if is_pkg:
+ raise ValueError("extension modules cannot be packages")
+
+ @_check_name
+ @set_package
+ @set_loader
+ def load_module(self, fullname):
+ """Load an extension module."""
+ is_reload = fullname in sys.modules
+ try:
+ return imp.load_dynamic(fullname, self._path)
+ except:
+ if not is_reload and fullname in sys.modules:
+ del sys.modules[fullname]
+ raise
+
+ @_check_name
+ def is_package(self, fullname):
+ """Return False as an extension module can never be a package."""
+ return False
+
+ @_check_name
+ def get_code(self, fullname):
+ """Return None as an extension module cannot create a code object."""
+ return None
+
+ @_check_name
+ def get_source(self, fullname):
+ """Return None as extension modules have no source code."""
+ return None
+
+
+# Finders #####################################################################
+
+class PathFinder:
+
+ """Meta path finder for sys.(path|path_hooks|path_importer_cache)."""
+
+ @classmethod
+ def _path_hooks(cls, path, hooks=None):
+ """Search sequence of hooks for a finder for 'path'.
+
+ If 'hooks' is false then use sys.path_hooks.
+
+ """
+ if not hooks:
+ hooks = sys.path_hooks
+ for hook in hooks:
+ try:
+ return hook(path)
+ except ImportError:
+ continue
+ else:
+ raise ImportError("no path hook found for {0}".format(path))
+
+ @classmethod
+ def _path_importer_cache(cls, path, default=None):
+ """Get the finder for the path from sys.path_importer_cache.
+
+ If the path is not in the cache, find the appropriate finder and cache
+ it. If None is cached, get the default finder and cache that
+ (if applicable).
+
+ Because of NullImporter, some finder should be returned. The only
+ explicit fail case is if None is cached but the path cannot be used for
+ the default hook, for which ImportError is raised.
+
+ """
+ try:
+ finder = sys.path_importer_cache[path]
+ except KeyError:
+ finder = cls._path_hooks(path)
+ sys.path_importer_cache[path] = finder
+ else:
+ if finder is None and default:
+ # Raises ImportError on failure.
+ finder = default(path)
+ sys.path_importer_cache[path] = finder
+ return finder
+
+ @classmethod
+ def find_module(cls, fullname, path=None):
+ """Find the module on sys.path or 'path'."""
+ if not path:
+ path = sys.path
+ for entry in path:
+ try:
+ finder = cls._path_importer_cache(entry)
+ except ImportError:
+ continue
+ loader = finder.find_module(fullname)
+ if loader:
+ return loader
+ else:
+ return None
+
+
+class _ChainedFinder:
+
+ """Finder that sequentially calls other finders."""
+
+ def __init__(self, *finders):
+ self._finders = finders
+
+ def find_module(self, fullname, path=None):
+ for finder in self._finders:
+ result = finder.find_module(fullname, path)
+ if result:
+ return result
+ else:
+ return None
+
+
class FileFinder:
"""Base class for file finders.
@@ -643,20 +685,6 @@ class FileFinder:
return None
-class ExtensionFileFinder(FileFinder):
-
- """Importer for extension files."""
-
- _possible_package = False
- _loader = _ExtensionFileLoader
-
- def __init__(self, path_entry):
- # Assigning to _suffixes here instead of at the class level because
- # imp is not imported at the time of class creation.
- self._suffixes = _suffix_list(imp.C_EXTENSION)
- super().__init__(path_entry)
-
-
class PyFileFinder(FileFinder):
"""Importer for source/bytecode files."""
@@ -683,82 +711,43 @@ class PyPycFileFinder(PyFileFinder):
self._suffixes += _suffix_list(imp.PY_COMPILED)
-class PathFinder:
- """Meta path finder for sys.(path|path_hooks|path_importer_cache)."""
- @classmethod
- def _path_hooks(cls, path, hooks=None):
- """Search sequence of hooks for a finder for 'path'.
-
- If 'hooks' is false then use sys.path_hooks.
+class ExtensionFileFinder(FileFinder):
- """
- if not hooks:
- hooks = sys.path_hooks
- for hook in hooks:
- try:
- return hook(path)
- except ImportError:
- continue
- else:
- raise ImportError("no path hook found for {0}".format(path))
+ """Importer for extension files."""
- @classmethod
- def _path_importer_cache(cls, path, default=None):
- """Get the finder for the path from sys.path_importer_cache.
+ _possible_package = False
+ _loader = _ExtensionFileLoader
- If the path is not in the cache, find the appropriate finder and cache
- it. If None is cached, get the default finder and cache that
- (if applicable).
+ def __init__(self, path_entry):
+ # Assigning to _suffixes here instead of at the class level because
+ # imp is not imported at the time of class creation.
+ self._suffixes = _suffix_list(imp.C_EXTENSION)
+ super().__init__(path_entry)
- Because of NullImporter, some finder should be returned. The only
- explicit fail case is if None is cached but the path cannot be used for
- the default hook, for which ImportError is raised.
- """
- try:
- finder = sys.path_importer_cache[path]
- except KeyError:
- finder = cls._path_hooks(path)
- sys.path_importer_cache[path] = finder
- else:
- if finder is None and default:
- # Raises ImportError on failure.
- finder = default(path)
- sys.path_importer_cache[path] = finder
- return finder
+# Import itself ###############################################################
- @classmethod
- def find_module(cls, fullname, path=None):
- """Find the module on sys.path or 'path'."""
- if not path:
- path = sys.path
- for entry in path:
+def _chained_path_hook(*path_hooks):
+ """Create a closure which sequentially checks path hooks to see which ones
+ (if any) can work with a path."""
+ def path_hook(entry):
+ """Check to see if 'entry' matches any of the enclosed path hooks."""
+ finders = []
+ for hook in path_hooks:
try:
- finder = cls._path_importer_cache(entry)
+ finder = hook(entry)
except ImportError:
continue
- loader = finder.find_module(fullname)
- if loader:
- return loader
+ else:
+ finders.append(finder)
+ if not finders:
+ raise ImportError("no finder found")
else:
- return None
-
-
-# Import itself ###############################################################
-
-class _ImportLockContext:
-
- """Context manager for the import lock."""
-
- def __enter__(self):
- """Acquire the import lock."""
- imp.acquire_lock()
+ return _ChainedFinder(*finders)
- def __exit__(self, exc_type, exc_value, exc_traceback):
- """Release the import lock regardless of any raised exceptions."""
- imp.release_lock()
+ return path_hook
_DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder)
@@ -784,6 +773,18 @@ 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]