summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <bcannon@gmail.com>2009-02-21 03:15:37 (GMT)
committerBrett Cannon <bcannon@gmail.com>2009-02-21 03:15:37 (GMT)
commit2dee597e0593a8f7b477f58afe5e46f94b994541 (patch)
treeb3ddcc23c894a377ff78502209998aeae4f37dc7
parenta2fcb1d964af0a0aa5cecb7e37f8abe7d0a1f867 (diff)
downloadcpython-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.
-rw-r--r--Lib/importlib/_bootstrap.py100
-rw-r--r--Lib/importlib/test/extension/test_case_sensitivity.py2
-rw-r--r--Lib/importlib/test/extension/test_finder.py2
-rw-r--r--Lib/importlib/test/extension/test_path_hook.py2
-rw-r--r--Lib/importlib/test/import_/test_path.py6
-rw-r--r--Lib/importlib/test/source/test_case_sensitivity.py2
-rw-r--r--Lib/importlib/test/source/test_finder.py2
-rw-r--r--Lib/importlib/test/source/test_path_hook.py2
8 files changed, 56 insertions, 62 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."""
diff --git a/Lib/importlib/test/extension/test_case_sensitivity.py b/Lib/importlib/test/extension/test_case_sensitivity.py
index eb05ad3..39e6fac 100644
--- a/Lib/importlib/test/extension/test_case_sensitivity.py
+++ b/Lib/importlib/test/extension/test_case_sensitivity.py
@@ -13,7 +13,7 @@ class ExtensionModuleCaseSensitivityTest(unittest.TestCase):
good_name = ext_util.NAME
bad_name = good_name.upper()
assert good_name != bad_name
- finder = importlib.ExtensionFileImporter(ext_util.PATH)
+ finder = importlib.ExtensionFileFinder(ext_util.PATH)
return finder.find_module(bad_name)
def test_case_sensitive(self):
diff --git a/Lib/importlib/test/extension/test_finder.py b/Lib/importlib/test/extension/test_finder.py
index 7321e31..3fc9b0b 100644
--- a/Lib/importlib/test/extension/test_finder.py
+++ b/Lib/importlib/test/extension/test_finder.py
@@ -9,7 +9,7 @@ class FinderTests(abc.FinderTests):
"""Test the finder for extension modules."""
def find_module(self, fullname):
- importer = importlib.ExtensionFileImporter(util.PATH)
+ importer = importlib.ExtensionFileFinder(util.PATH)
return importer.find_module(fullname)
def test_module(self):
diff --git a/Lib/importlib/test/extension/test_path_hook.py b/Lib/importlib/test/extension/test_path_hook.py
index 674fd90..76f4995 100644
--- a/Lib/importlib/test/extension/test_path_hook.py
+++ b/Lib/importlib/test/extension/test_path_hook.py
@@ -14,7 +14,7 @@ class PathHookTests(unittest.TestCase):
# XXX Should it only work for directories containing an extension module?
def hook(self, entry):
- return importlib.ExtensionFileImporter(entry)
+ return importlib.ExtensionFileFinder(entry)
def test_success(self):
# Path hook should handle a directory where a known extension module
diff --git a/Lib/importlib/test/import_/test_path.py b/Lib/importlib/test/import_/test_path.py
index 8cf5699..3d9b1a1 100644
--- a/Lib/importlib/test/import_/test_path.py
+++ b/Lib/importlib/test/import_/test_path.py
@@ -87,16 +87,16 @@ class DefaultPathFinderTests(unittest.TestCase):
importer = util.mock_modules(module)
path = '<test path>'
# XXX Not blackbox.
- original_hook = _bootstrap._DefaultPathFinder._default_hook
+ original_hook = _bootstrap._DEFAULT_PATH_HOOK
mock_hook = import_util.mock_path_hook(path, importer=importer)
- _bootstrap._DefaultPathFinder._default_hook = staticmethod(mock_hook)
+ _bootstrap._DEFAULT_PATH_HOOK = mock_hook
try:
with util.import_state(path_importer_cache={path: None}):
loader = _bootstrap._DefaultPathFinder.find_module(module,
path=[path])
self.assert_(loader is importer)
finally:
- _bootstrap._DefaultPathFinder._default_hook = original_hook
+ _bootstrap._DEFAULT_PATH_HOOK = original_hook
def test_main():
diff --git a/Lib/importlib/test/source/test_case_sensitivity.py b/Lib/importlib/test/source/test_case_sensitivity.py
index 6bd86cf..df6d3bc 100644
--- a/Lib/importlib/test/source/test_case_sensitivity.py
+++ b/Lib/importlib/test/source/test_case_sensitivity.py
@@ -19,7 +19,7 @@ class CaseSensitivityTest(unittest.TestCase):
assert name != name.lower()
def find(self, path):
- finder = importlib.PyFileImporter(path)
+ finder = importlib.PyFileFinder(path)
return finder.find_module(self.name)
def sensitivity_test(self):
diff --git a/Lib/importlib/test/source/test_finder.py b/Lib/importlib/test/source/test_finder.py
index 0f1f549..0cfb14f 100644
--- a/Lib/importlib/test/source/test_finder.py
+++ b/Lib/importlib/test/source/test_finder.py
@@ -32,7 +32,7 @@ class FinderTests(abc.FinderTests):
"""
def import_(self, root, module):
- finder = importlib.PyFileImporter(root)
+ finder = importlib.PyFileFinder(root)
return finder.find_module(module)
def run_test(self, test, create=None, *, compile_=None, unlink=None):
diff --git a/Lib/importlib/test/source/test_path_hook.py b/Lib/importlib/test/source/test_path_hook.py
index 5aac42e..9a4ccbe 100644
--- a/Lib/importlib/test/source/test_path_hook.py
+++ b/Lib/importlib/test/source/test_path_hook.py
@@ -10,7 +10,7 @@ class PathHookTest(unittest.TestCase):
def test_success(self):
# XXX Only work on existing directories?
with source_util.create_modules('dummy') as mapping:
- self.assert_(hasattr(importlib.FileImporter(mapping['.root']),
+ self.assert_(hasattr(importlib.FileFinder(mapping['.root']),
'find_module'))