diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -123,34 +123,66 @@ are also provided to help in implementing the core ABCs. -.. class:: Finder +.. class:: MetaPathFinder - 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:`meta path finder`. - .. method:: find_loader(self, fullname): + .. versionadded:: 3.3 - 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()`. + .. method:: find_module(fullname, path) - .. versionadded: 3.3 + An abstract method for finding a :term:`loader` for the specified + module. If 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. - .. 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:: PathEntryFinder + + 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. + + .. method:: find_module(fullname) + + An abstract method for finding a :term:`loader` for the specified + module. + + .. deprecated:: 3.3 + This method is replaced by :meth:`find_loader`. It is still + available for compatilibity reasons. .. 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. + + +.. class:: Finder + + An abstract base class representing a :term:`finder`. It is registered + as a subclass of :class:`MetaPathFinder` and :class:`PathEntryFinder`. + + .. deprecated:: 3.3 + This class is deprecated in favor of :class:`MetaPathFinder` and + :class:`PathEntryFinder`. It is still available for compatibility + purposes. + + .. 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:: Loader @@ -569,8 +601,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 +611,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 +621,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 +648,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,64 @@ abstract_cls.register(frozen_cls) +class MetaPathFinder(metaclass=abc.ABCMeta): + + """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(metaclass=abc.ABCMeta): + + """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 + + def find_module(self, fullname): + """An optional legacy method that should find a module. + The fullname is a str and the optional path is a str or None. + This method is available for compatibilty. The path finder will + use this method only if find_loader() does not exist. + Returns a Loader object. + """ + raise NotImplementedError + +_register(PathEntryFinder, machinery.FileFinder) + + +@PathEntryFinder.register +@MetaPathFinder.register +class Finder(metaclass=abc.ABCMeta): + + """Legacy abstract base class for import finders. + Instead, use MetaPathFinder or PathEntryFinder. + """ + + @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. + """ + raise NotImplementedError + + class Loader(metaclass=abc.ABCMeta): """Abstract base class for import loaders.""" @@ -40,33 +98,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(_)