diff options
author | Brett Cannon <brett@python.org> | 2012-08-10 16:21:12 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2012-08-10 16:21:12 (GMT) |
commit | f4dc9204cc406ab41c2d643c1a64375a6a2954e5 (patch) | |
tree | c0cf92198b707bac6a68b801305ad86b24eb814f /Lib | |
parent | 2d6266d5f148549979df024459e29b73307b86c4 (diff) | |
download | cpython-f4dc9204cc406ab41c2d643c1a64375a6a2954e5.zip cpython-f4dc9204cc406ab41c2d643c1a64375a6a2954e5.tar.gz cpython-f4dc9204cc406ab41c2d643c1a64375a6a2954e5.tar.bz2 |
Issue #15502: Finish bringing importlib.abc in line with the current
state of the import system. Also make importlib.invalidate_caches()
work with sys.meta_path instead of sys.path_importer_cache to
completely separate the path-based import system from the overall
import system.
Patch by Eric Snow.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/importlib/__init__.py | 6 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap.py | 12 | ||||
-rw-r--r-- | Lib/importlib/abc.py | 42 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_abc.py | 2 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_api.py | 10 |
5 files changed, 50 insertions, 22 deletions
diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py index d30691a..6f40dac 100644 --- a/Lib/importlib/__init__.py +++ b/Lib/importlib/__init__.py @@ -38,9 +38,9 @@ from ._bootstrap import __import__ def invalidate_caches(): - """Call the invalidate_caches() method on all finders stored in - sys.path_importer_caches (where implemented).""" - for finder in sys.path_importer_cache.values(): + """Call the invalidate_caches() method on all meta path finders stored in + sys.meta_path (where implemented).""" + for finder in sys.meta_path: if hasattr(finder, 'invalidate_caches'): finder.invalidate_caches() diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 4f61a5b..7b12ab0 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -1186,6 +1186,14 @@ class PathFinder: """Meta path finder for sys.path and package __path__ attributes.""" @classmethod + def invalidate_caches(cls): + """Call the invalidate_caches() method on all path entry finders + stored in sys.path_importer_caches (where implemented).""" + for finder in sys.path_importer_cache.values(): + if hasattr(finder, 'invalidate_caches'): + finder.invalidate_caches() + + @classmethod def _path_hooks(cls, path): """Search sequence of hooks for a finder for 'path'. @@ -1235,14 +1243,14 @@ class PathFinder: portions = [] if loader is not None: # We found a loader: return it immediately. - return (loader, namespace_path) + return loader, namespace_path # This is possibly part of a namespace package. # Remember these path entries (if any) for when we # create a namespace package, and continue iterating # on path. namespace_path.extend(portions) else: - return (None, namespace_path) + return None, namespace_path @classmethod def find_module(cls, fullname, path=None): diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py index e8a0541..cd687e8 100644 --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -25,26 +25,22 @@ def _register(abstract_cls, *classes): class Finder(metaclass=abc.ABCMeta): - """Common abstract base class for import finders. + """Legacy abstract base class for import finders. - Finder implementations should derive from the more specific - MetaPathFinder or PathEntryFinder ABCs rather than directly from Finder. + It may be subclassed for compatibility with legacy third party + reimplementations of the import system. Otherwise, finder + implementations should derive from the more specific MetaPathFinder + or PathEntryFinder ABCs. """ + @abc.abstractmethod def find_module(self, fullname, path=None): - """An optional legacy method that should find a module. + """An abstract method that should find a module. The fullname is a str and the optional path is a str or None. Returns a Loader object. - - The path finder will use this method only if find_loader() does - not exist. It may optionally be implemented for compatibility - with legacy third party reimplementations of the import system. """ raise NotImplementedError - # invalidate_caches() is a completely optional method, so no default - # implementation is provided. See the docs for details. - class MetaPathFinder(Finder): @@ -52,12 +48,18 @@ class MetaPathFinder(Finder): @abc.abstractmethod def find_module(self, fullname, path): - """Abstract method which when implemented should find a module. + """Abstract method which, when implemented, should find a module. The fullname is a str and the path is a str or None. Returns a Loader object. """ raise NotImplementedError + def invalidate_caches(self): + """An optional method for clearing the finder's cache, if any. + This method is used by importlib.invalidate_caches(). + """ + return NotImplemented + _register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter, machinery.PathFinder, machinery.WindowsRegistryFinder) @@ -68,13 +70,25 @@ class PathEntryFinder(Finder): @abc.abstractmethod def find_loader(self, fullname): - """Abstract method which when implemented returns a module loader. + """Abstract method which, when implemented, returns a module loader. The fullname is a str. Returns a 2-tuple of (Loader, portion) where portion is a sequence of file system locations contributing to part of - a namespace package. The sequence may be empty. + a namespace package. The sequence may be empty and the loader may be + None. """ raise NotImplementedError + def find_module(self, fullname): + """Compatibility function which is the equivalent of + self.find_loader(fullname)[0].""" + return self.find_loader(fullname)[0] + + def invalidate_caches(self): + """An optional method for clearing the finder's cache, if any. + This method is used by PathFinder.invalidate_caches(). + """ + return NotImplemented + _register(PathEntryFinder, machinery.FileFinder) diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py index aa87591..c620c37 100644 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -36,11 +36,13 @@ class MetaPathFinder(InheritanceTests, unittest.TestCase): subclasses = [machinery.BuiltinImporter, machinery.FrozenImporter, machinery.PathFinder, machinery.WindowsRegistryFinder] + class PathEntryFinder(InheritanceTests, unittest.TestCase): superclasses = [abc.Finder] subclasses = [machinery.FileFinder] + class Loader(InheritanceTests, unittest.TestCase): subclasses = [abc.PyLoader] diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py index ba2a721..ef6629a 100644 --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -148,11 +148,15 @@ class InvalidateCacheTests(unittest.TestCase): self.called = True key = 'gobledeegook' - ins = InvalidatingNullFinder() - sys.path_importer_cache[key] = ins + meta_ins = InvalidatingNullFinder() + path_ins = InvalidatingNullFinder() + sys.meta_path.insert(0, meta_ins) self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key)) + sys.path_importer_cache[key] = path_ins + self.addCleanup(lambda: sys.meta_path.remove(meta_ins)) importlib.invalidate_caches() - self.assertTrue(ins.called) + self.assertTrue(meta_ins.called) + self.assertTrue(path_ins.called) def test_method_lacking(self): # There should be no issues if the method is not defined. |