summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2012-08-10 16:21:12 (GMT)
committerBrett Cannon <brett@python.org>2012-08-10 16:21:12 (GMT)
commitf4dc9204cc406ab41c2d643c1a64375a6a2954e5 (patch)
treec0cf92198b707bac6a68b801305ad86b24eb814f /Lib
parent2d6266d5f148549979df024459e29b73307b86c4 (diff)
downloadcpython-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__.py6
-rw-r--r--Lib/importlib/_bootstrap.py12
-rw-r--r--Lib/importlib/abc.py42
-rw-r--r--Lib/test/test_importlib/test_abc.py2
-rw-r--r--Lib/test/test_importlib/test_api.py10
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.