diff options
author | Brett Cannon <bcannon@gmail.com> | 2009-02-21 03:15:37 (GMT) |
---|---|---|
committer | Brett Cannon <bcannon@gmail.com> | 2009-02-21 03:15:37 (GMT) |
commit | 2dee597e0593a8f7b477f58afe5e46f94b994541 (patch) | |
tree | b3ddcc23c894a377ff78502209998aeae4f37dc7 /Lib/importlib/_bootstrap.py | |
parent | a2fcb1d964af0a0aa5cecb7e37f8abe7d0a1f867 (diff) | |
download | cpython-2dee597e0593a8f7b477f58afe5e46f94b994541.zip cpython-2dee597e0593a8f7b477f58afe5e46f94b994541.tar.gz cpython-2dee597e0593a8f7b477f58afe5e46f94b994541.tar.bz2 |
Do some cleanup in importlib:
+ Ditch using arguments to super().
+ Ditch subclassing from object directly.
+ Move directory check out of chaining path hook to file path hook/finder.
+ Rename some classes to better reflect they are finders, not importers.
Diffstat (limited to 'Lib/importlib/_bootstrap.py')
-rw-r--r-- | Lib/importlib/_bootstrap.py | 100 |
1 files changed, 47 insertions, 53 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 65e9f17..4db61da 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -174,51 +174,43 @@ class FrozenImporter: raise -class ChainedImporter(object): +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, *importers): - self._importers = importers + def __init__(self, *finders): + self._finders = finders def find_module(self, fullname, path=None): - for importer in self._importers: - result = importer.find_module(fullname, path) + for finder in self._finders: + result = finder.find_module(fullname, path) if result: return result else: return None -# XXX Don't make filesystem-specific and instead make generic for any path -# hooks. -def chaining_fs_path_hook(*path_hooks): - """Create a closure which calls the path hooks sequentially looking for - which path hooks can handle a path entry. - - - Passed-in path hooks work as any other path hooks, raising ImportError if - they cannot handle the path, otherwise returning a finder. - - """ - def chained_fs_path_hook(path_entry): - """Closure which sees which of the captured path hooks can handle the - path entry.""" - absolute_path = _path_absolute(path_entry) - if not _path_isdir(absolute_path): - raise ImportError("only directories are supported") - accepted = [] - for path_hook in path_hooks: - try: - accepted.append(path_hook(absolute_path)) - except ImportError: - continue - if not accepted: - raise ImportError("no path hooks could handle %s" % path_entry) - return ChainedImporter(*accepted) - return chained_fs_path_hook - - def check_name(method): """Decorator to verify that the module being requested matches the one the loader can handle. @@ -235,11 +227,11 @@ def check_name(method): return inner -class _ExtensionFileLoader(object): +class _ExtensionFileLoader: """Loader for extension modules. - The constructor is designed to work with FileImporter. + The constructor is designed to work with FileFinder. """ @@ -323,10 +315,10 @@ def module_for_loader(fxn): return decorated -class _PyFileLoader(object): +class _PyFileLoader: # XXX Still smart to have this as a separate class? Or would it work - # better to integrate with PyFileImporter? Could cache _is_pkg info. - # FileImporter can be changed to return self instead of a specific loader + # better to integrate with PyFileFinder? Could cache _is_pkg info. + # FileFinder can be changed to return self instead of a specific loader # call. Otherwise _base_path can be calculated on the fly without issue if # it is known whether a module should be treated as a path or package to # minimize stat calls. Could even go as far as to stat the directory the @@ -515,9 +507,9 @@ class _PyFileLoader(object): return self._is_pkg -class FileImporter(object): +class FileFinder: - """Base class for file importers. + """Base class for file finders. Subclasses are expected to define the following attributes: @@ -541,10 +533,13 @@ class FileImporter(object): Can be used as an entry on sys.path_hook. """ - self._path_entry = path_entry + absolute_path = _path_absolute(path_entry) + if not _path_isdir(absolute_path): + raise ImportError("only directories are supported") + self._path_entry = absolute_path def find_module(self, fullname, path=None): - tail_module = fullname.rsplit('.', 1)[-1] + tail_module = fullname.rpartition('.')[2] package_directory = None if self._possible_package: for ext in self._suffixes: @@ -571,7 +566,7 @@ class FileImporter(object): return None -class ExtensionFileImporter(FileImporter): +class ExtensionFileFinder(FileFinder): """Importer for extension files.""" @@ -582,10 +577,10 @@ class ExtensionFileImporter(FileImporter): # 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(ExtensionFileImporter, self).__init__(path_entry) + super().__init__(path_entry) -class PyFileImporter(FileImporter): +class PyFileFinder(FileFinder): """Importer for source/bytecode files.""" @@ -598,7 +593,7 @@ class PyFileImporter(FileImporter): # optimization by the loader. self._suffixes = suffix_list(imp.PY_SOURCE) self._suffixes += suffix_list(imp.PY_COMPILED) - super(PyFileImporter, self).__init__(path_entry) + super().__init__(path_entry) class PathFinder: @@ -664,31 +659,30 @@ class PathFinder: return None +_DEFAULT_PATH_HOOK = chained_path_hook(ExtensionFileFinder, PyFileFinder) + class _DefaultPathFinder(PathFinder): """Subclass of PathFinder that implements implicit semantics for __import__.""" - _default_hook = staticmethod(chaining_fs_path_hook(ExtensionFileImporter, - PyFileImporter)) - @classmethod def _path_hooks(cls, path): """Search sys.path_hooks as well as implicit path hooks.""" try: return super()._path_hooks(path) except ImportError: - implicit_hooks = [cls._default_hook, imp.NullImporter] + implicit_hooks = [_DEFAULT_PATH_HOOK, imp.NullImporter] return super()._path_hooks(path, implicit_hooks) @classmethod def _path_importer_cache(cls, path): """Use the default path hook when None is stored in sys.path_importer_cache.""" - return super()._path_importer_cache(path, cls._default_hook) + return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) -class ImportLockContext(object): +class ImportLockContext: """Context manager for the import lock.""" |