Re: [Python-Dev] [Python-checkins] cpython: Issue #15502: Bring the importlib ABCs into line with the current state of the
Mostly as a note to myself (although if someone else wants to change this,
then great), PathEntryFinder.find_loader() specifies self while the other
docs don't bother to list it.
And I just realized that the other classes defined in the importlib docs
don't list their superclasses like MetaPathFinder and PathEntryFinder now
do.
On Thu, Aug 2, 2012 at 7:26 AM, nick.coghlan
http://hg.python.org/cpython/rev/184700df5b6a changeset: 78379:184700df5b6a parent: 78376:8ace059cdffd user: Nick Coghlan
date: Thu Aug 02 21:26:03 2012 +1000 summary: Issue #15502: Bring the importlib ABCs into line with the current state of the import protocols given PEP 420. Original patch by Eric Snow. files: Doc/library/importlib.rst | 77 +++++--- Lib/importlib/abc.py | 82 ++++++--- Lib/test/test_importlib/source/test_abc_loader.py | 23 +- Lib/test/test_importlib/test_abc.py | 7 +- Misc/NEWS | 3 + 5 files changed, 127 insertions(+), 65 deletions(-)
diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -125,32 +125,49 @@
.. class:: Finder
- An abstract base class representing a :term:`finder`. - See :pep:`302` for the exact definition for a finder. - - .. method:: find_loader(self, fullname): - - 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()`. - - .. versionadded: 3.3 - - .. 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. + 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:: invalidate_caches()
- 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 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. + + .. 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. + + +.. class:: MetaPathFinder(Finder) + + 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 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 @@
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 @@ .. 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 @@ .. 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 @@
.. 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 --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -23,6 +23,61 @@ abstract_cls.register(frozen_cls)
+class Finder(metaclass=abc.ABCMeta): + + """Common abstract base class for import finders. + + 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 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 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. + """ + raise NotImplementedError + +_register(PathEntryFinder, machinery.FileFinder) + + class Loader(metaclass=abc.ABCMeta):
"""Abstract base class for import loaders.""" @@ -40,33 +95,6 @@ raise NotImplementedError
-class Finder(metaclass=abc.ABCMeta): - - """Abstract base class for import finders.""" - - @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()`. - """ - raise NotImplementedError - - @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. - """ - raise NotImplementedError - -_register(Finder, machinery.BuiltinImporter, machinery.FrozenImporter, - machinery.PathFinder, machinery.FileFinder) - - class ResourceLoader(Loader):
"""Abstract base class for loaders which can return data from their diff --git a/Lib/test/test_importlib/source/test_abc_loader.py b/Lib/test/test_importlib/source/test_abc_loader.py --- a/Lib/test/test_importlib/source/test_abc_loader.py +++ b/Lib/test/test_importlib/source/test_abc_loader.py @@ -778,23 +778,32 @@ expect = io.IncrementalNewlineDecoder(None, True).decode(source) self.assertEqual(mock.get_source(name), expect)
+ class AbstractMethodImplTests(unittest.TestCase):
"""Test the concrete abstractmethod implementations."""
+ class MetaPathFinder(abc.MetaPathFinder): + def find_module(self, fullname, path): + super().find_module(fullname, path) + + 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 Finder(abc.Finder): - def find_module(self, _): - super().find_module(_) - - def find_loader(self, _): - super().find_loader(_) - 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 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -30,11 +30,16 @@ "{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 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,6 +72,9 @@ 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.
-- Repository URL: http://hg.python.org/cpython
_______________________________________________ Python-checkins mailing list Python-checkins@python.org http://mail.python.org/mailman/listinfo/python-checkins
participants (1)
-
Brett Cannon