summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-08-02 11:26:03 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2012-08-02 11:26:03 (GMT)
commit8a9080feffc757360d0d73e4173189586098ffb5 (patch)
tree9199a6a30f436fcc310ad16ff64f145f00822e2c
parenta90f311d0592f6ab56068441413a1925bd7393f4 (diff)
downloadcpython-8a9080feffc757360d0d73e4173189586098ffb5.zip
cpython-8a9080feffc757360d0d73e4173189586098ffb5.tar.gz
cpython-8a9080feffc757360d0d73e4173189586098ffb5.tar.bz2
Issue #15502: Bring the importlib ABCs into line with the current state of the import protocols given PEP 420. Original patch by Eric Snow.
-rw-r--r--Doc/library/importlib.rst69
-rw-r--r--Lib/importlib/abc.py70
-rw-r--r--Lib/test/test_importlib/source/test_abc_loader.py21
-rw-r--r--Lib/test/test_importlib/test_abc.py7
-rw-r--r--Misc/NEWS3
5 files changed, 116 insertions, 54 deletions
diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst
index 05b18d3..49ad46f 100644
--- a/Doc/library/importlib.rst
+++ b/Doc/library/importlib.rst
@@ -125,32 +125,49 @@ are also provided to help in implementing the core ABCs.
.. class:: Finder
- An abstract base class representing a :term:`finder`.
- See :pep:`302` for the exact definition for a finder.
+ An abstract base class representing a :term:`finder`. Finder
+ implementations should derive from (or register with) the more specific
+ :class:`MetaPathFinder` or :class:`PathEntryFinder` ABCs.
- .. method:: find_loader(self, fullname):
+ .. method:: invalidate_caches()
- An abstract method for finding a :term:`loader` for the specified
- module. 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. When present, `find_loader()` is
- preferred over `find_module()`.
+ An optional method which, when called, should invalidate any internal
+ cache used by the finder. Used by :func:`invalidate_caches()` when
+ invalidating the caches of all cached finders.
- .. versionadded: 3.3
+ .. versionchanged:: 3.3
+ The API signatures for meta path finders and path entry finders
+ were separated by PEP 420. Accordingly, the Finder ABC no
+ longer requires implementation of a ``find_module()`` method.
- .. method:: find_module(fullname, path=None)
- An abstract method for finding a :term:`loader` for the specified
- module. If the :term:`finder` is found on :data:`sys.meta_path` and the
- module to be searched for is a subpackage or module then *path* will
- be the value of :attr:`__path__` from the parent package. If a loader
- cannot be found, ``None`` is returned.
+.. class:: MetaPathFinder(Finder)
- .. method:: invalidate_caches()
+ An abstract base class representing a :term:`meta path finder`.
+
+ .. versionadded:: 3.3
+
+ .. method:: find_module(fullname, path)
+
+ An abstract method for finding a :term:`loader` for the specified
+ module. If this is a top-level import, *path* will be ``None``.
+ Otheriwse, this is a search for a subpackage or module and *path*
+ will be the value of :attr:`__path__` from the parent
+ package. If a loader cannot be found, ``None`` is returned.
+
+
+.. class:: PathEntryFinder(Finder)
+
+ An abstract base class representing a :term:`path entry finder`.
+
+ .. versionadded:: 3.3
+
+ .. method:: find_loader(self, fullname):
- An optional method which, when called, should invalidate any internal
- cache used by the finder. Used by :func:`invalidate_caches()` when
- invalidating the caches of all cached finders.
+ An abstract method for finding a :term:`loader` for the specified
+ module. 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.
.. class:: Loader
@@ -569,8 +586,8 @@ find and load modules.
An :term:`importer` for built-in modules. All known built-in modules are
listed in :data:`sys.builtin_module_names`. This class implements the
- :class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader`
- ABCs.
+ :class:`importlib.abc.MetaPathFinder` and
+ :class:`importlib.abc.InspectLoader` ABCs.
Only class methods are defined by this class to alleviate the need for
instantiation.
@@ -579,8 +596,8 @@ find and load modules.
.. class:: FrozenImporter
An :term:`importer` for frozen modules. This class implements the
- :class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader`
- ABCs.
+ :class:`importlib.abc.MetaPathFinder` and
+ :class:`importlib.abc.InspectLoader` ABCs.
Only class methods are defined by this class to alleviate the need for
instantiation.
@@ -589,7 +606,7 @@ find and load modules.
.. class:: PathFinder
:term:`Finder` for :data:`sys.path`. This class implements the
- :class:`importlib.abc.Finder` ABC.
+ :class:`importlib.abc.MetaPathFinder` ABC.
This class does not perfectly mirror the semantics of :keyword:`import` in
terms of :data:`sys.path`. No implicit path hooks are assumed for
@@ -616,8 +633,8 @@ find and load modules.
.. class:: FileFinder(path, \*loader_details)
- A concrete implementation of :class:`importlib.abc.Finder` which caches
- results from the file system.
+ A concrete implementation of :class:`importlib.abc.PathEntryFinder` which
+ caches results from the file system.
The *path* argument is the directory for which the finder is in charge of
searching.
diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py
index 7fcf2de..5e71758 100644
--- a/Lib/importlib/abc.py
+++ b/Lib/importlib/abc.py
@@ -23,48 +23,76 @@ def _register(abstract_cls, *classes):
abstract_cls.register(frozen_cls)
-class Loader(metaclass=abc.ABCMeta):
+class Finder(metaclass=abc.ABCMeta):
- """Abstract base class for import loaders."""
+ """Common abstract base class for import finders.
- @abc.abstractmethod
- def load_module(self, fullname):
- """Abstract method which when implemented should load a module.
- The fullname is a str."""
+ Finder implementations should derive from the more specific
+ MetaPathFinder or PathEntryFinder ABCs rather than directly from Finder.
+ """
+
+ def find_module(self, fullname, path=None):
+ """An optional legacy 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):
+
+ """Abstract base class for import finders on sys.meta_path."""
+
@abc.abstractmethod
- def module_repr(self, module):
- """Abstract method which when implemented calculates and returns the
- given module's repr."""
+ def find_module(self, fullname, path):
+ """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
+_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
+ machinery.PathFinder)
-class Finder(metaclass=abc.ABCMeta):
- """Abstract base class for import finders."""
+class PathEntryFinder(Finder):
+
+ """Abstract base class for path entry finders used by PathFinder."""
@abc.abstractmethod
def find_loader(self, fullname):
"""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. When present,
- `find_loader()` is preferred over `find_module()`.
+ a namespace package. The sequence may be empty.
"""
raise NotImplementedError
+_register(PathEntryFinder, machinery.FileFinder)
+
+
+class Loader(metaclass=abc.ABCMeta):
+
+ """Abstract base class for import loaders."""
+
@abc.abstractmethod
- def find_module(self, fullname, path=None):
- """Abstract method which when implemented should find a module.
- The fullname is a str and the optional path is a str or None.
- Returns a Loader object. This method is only called if
- `find_loader()` is not present.
- """
+ def load_module(self, fullname):
+ """Abstract method which when implemented should load a module.
+ The fullname is a str."""
raise NotImplementedError
-_register(Finder, machinery.BuiltinImporter, machinery.FrozenImporter,
- machinery.PathFinder, machinery.FileFinder)
+ @abc.abstractmethod
+ def module_repr(self, module):
+ """Abstract method which when implemented calculates and returns the
+ given module's repr."""
+ raise NotImplementedError
class ResourceLoader(Loader):
diff --git a/Lib/test/test_importlib/source/test_abc_loader.py b/Lib/test/test_importlib/source/test_abc_loader.py
index 9db4882..0d912b6 100644
--- a/Lib/test/test_importlib/source/test_abc_loader.py
+++ b/Lib/test/test_importlib/source/test_abc_loader.py
@@ -778,23 +778,32 @@ class SourceLoaderGetSourceTests(unittest.TestCase):
expect = io.IncrementalNewlineDecoder(None, True).decode(source)
self.assertEqual(mock.get_source(name), expect)
+
class AbstractMethodImplTests(unittest.TestCase):
"""Test the concrete abstractmethod implementations."""
- class Loader(abc.Loader):
- def load_module(self, fullname):
- super().load_module(fullname)
- def module_repr(self, module):
- super().module_repr(module)
+ class MetaPathFinder(abc.MetaPathFinder):
+ def find_module(self, fullname, path):
+ super().find_module(fullname, path)
- class Finder(abc.Finder):
+ class PathEntryFinder(abc.PathEntryFinder):
def find_module(self, _):
super().find_module(_)
def find_loader(self, _):
super().find_loader(_)
+ class Finder(abc.Finder):
+ def find_module(self, fullname, path):
+ super().find_module(fullname, path)
+
+ class Loader(abc.Loader):
+ def load_module(self, fullname):
+ super().load_module(fullname)
+ def module_repr(self, module):
+ super().module_repr(module)
+
class ResourceLoader(Loader, abc.ResourceLoader):
def get_data(self, _):
super().get_data(_)
diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py
index 008bd21..90f38b8 100644
--- a/Lib/test/test_importlib/test_abc.py
+++ b/Lib/test/test_importlib/test_abc.py
@@ -30,11 +30,16 @@ class InheritanceTests:
"{0} is not a superclass of {1}".format(superclass, self.__test))
-class Finder(InheritanceTests, unittest.TestCase):
+class MetaPathFinder(InheritanceTests, unittest.TestCase):
+ superclasses = [abc.Finder]
subclasses = [machinery.BuiltinImporter, machinery.FrozenImporter,
machinery.PathFinder]
+class PathEntryFinder(InheritanceTests, unittest.TestCase):
+
+ superclasses = [abc.Finder]
+ subclasses = [machinery.FileFinder]
class Loader(InheritanceTests, unittest.TestCase):
diff --git a/Misc/NEWS b/Misc/NEWS
index f4dae73..58a331d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -72,6 +72,9 @@ Core and Builtins
Library
-------
+- Issue #15502: Bring the importlib ABCs into line with the current state
+ of the import protocols given PEP 420. Original patch by Eric Snow.
+
- Issue #15499: Launching a webbrowser in Unix used to sleep for a few
seconds. Original patch by Anton Barkovsky.