]> granicus.if.org Git - python/commitdiff
Do some cleanup in importlib:
authorBrett Cannon <bcannon@gmail.com>
Sat, 21 Feb 2009 03:15:37 +0000 (03:15 +0000)
committerBrett Cannon <bcannon@gmail.com>
Sat, 21 Feb 2009 03:15:37 +0000 (03:15 +0000)
+ 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.

Lib/importlib/_bootstrap.py
Lib/importlib/test/extension/test_case_sensitivity.py
Lib/importlib/test/extension/test_finder.py
Lib/importlib/test/extension/test_path_hook.py
Lib/importlib/test/import_/test_path.py
Lib/importlib/test/source/test_case_sensitivity.py
Lib/importlib/test/source/test_finder.py
Lib/importlib/test/source/test_path_hook.py

index 65e9f1786e0ac0bf73534f30b167a6f078217e59..4db61da079b5a3914f9cfff737e550a4840c9fda 100644 (file)
@@ -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."""
 
index eb05ad3b9a7d671c49d6d8e008802deb9ebe95b7..39e6facc9902c08d10d13f9ae16491604deccedc 100644 (file)
@@ -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):
index 7321e312bb50abdc0eae93b46da972d35b24e091..3fc9b0b77e0d40681606f042fdb6a528cc5c1b5b 100644 (file)
@@ -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):
index 674fd9031703f274c915a85ef62e60b9bed4d5ab..76f4995ad8f32899b737659c20b81956c45dcfcd 100644 (file)
@@ -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
index 8cf5699764c89737dee53120538fa6278bd609d8..3d9b1a1ccd8e74d8173f955357932a2a5939ac5d 100644 (file)
@@ -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():
index 6bd86cfcd9c8265cbf7109ec0bc64ad851dc8448..df6d3bcff6e6c56fd9ef604e77cbc987e9e8653e 100644 (file)
@@ -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):
index 0f1f549baa79378c3f50b7ae55fd4d68daa4323a..0cfb14f3e194375137e682687029b547fad02624 100644 (file)
@@ -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):
index 5aac42e5ff9d3c2eda5e0793d57db5781b549d28..9a4ccbe3d7845aff7dd7cc555d3518bdebcec596 100644 (file)
@@ -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'))