Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a9080f

Browse files
committed
Issue #15502: Bring the importlib ABCs into line with the current state of the import protocols given PEP 420. Original patch by Eric Snow.
1 parent a90f311 commit 8a9080f

5 files changed

Lines changed: 116 additions & 54 deletions

File tree

Doc/library/importlib.rst

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -125,32 +125,49 @@ are also provided to help in implementing the core ABCs.
125125

126126
.. class:: Finder
127127

128-
An abstract base class representing a :term:`finder`.
129-
See :pep:`302` for the exact definition for a finder.
128+
An abstract base class representing a :term:`finder`. Finder
129+
implementations should derive from (or register with) the more specific
130+
:class:`MetaPathFinder` or :class:`PathEntryFinder` ABCs.
130131

131-
.. method:: find_loader(self, fullname):
132+
.. method:: invalidate_caches()
132133

133-
An abstract method for finding a :term:`loader` for the specified
134-
module. Returns a 2-tuple of ``(loader, portion)`` where portion is a
135-
sequence of file system locations contributing to part of a namespace
136-
package. The sequence may be empty. When present, `find_loader()` is
137-
preferred over `find_module()`.
134+
An optional method which, when called, should invalidate any internal
135+
cache used by the finder. Used by :func:`invalidate_caches()` when
136+
invalidating the caches of all cached finders.
138137

139-
.. versionadded: 3.3
138+
.. versionchanged:: 3.3
139+
The API signatures for meta path finders and path entry finders
140+
were separated by PEP 420. Accordingly, the Finder ABC no
141+
longer requires implementation of a ``find_module()`` method.
140142

141-
.. method:: find_module(fullname, path=None)
142143

143-
An abstract method for finding a :term:`loader` for the specified
144-
module. If the :term:`finder` is found on :data:`sys.meta_path` and the
145-
module to be searched for is a subpackage or module then *path* will
146-
be the value of :attr:`__path__` from the parent package. If a loader
147-
cannot be found, ``None`` is returned.
144+
.. class:: MetaPathFinder(Finder)
148145

149-
.. method:: invalidate_caches()
146+
An abstract base class representing a :term:`meta path finder`.
147+
148+
.. versionadded:: 3.3
149+
150+
.. method:: find_module(fullname, path)
151+
152+
An abstract method for finding a :term:`loader` for the specified
153+
module. If this is a top-level import, *path* will be ``None``.
154+
Otheriwse, this is a search for a subpackage or module and *path*
155+
will be the value of :attr:`__path__` from the parent
156+
package. If a loader cannot be found, ``None`` is returned.
157+
158+
159+
.. class:: PathEntryFinder(Finder)
160+
161+
An abstract base class representing a :term:`path entry finder`.
162+
163+
.. versionadded:: 3.3
164+
165+
.. method:: find_loader(self, fullname):
150166

151-
An optional method which, when called, should invalidate any internal
152-
cache used by the finder. Used by :func:`invalidate_caches()` when
153-
invalidating the caches of all cached finders.
167+
An abstract method for finding a :term:`loader` for the specified
168+
module. Returns a 2-tuple of ``(loader, portion)`` where portion is a
169+
sequence of file system locations contributing to part of a namespace
170+
package. The sequence may be empty.
154171

155172

156173
.. class:: Loader
@@ -569,8 +586,8 @@ find and load modules.
569586

570587
An :term:`importer` for built-in modules. All known built-in modules are
571588
listed in :data:`sys.builtin_module_names`. This class implements the
572-
:class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader`
573-
ABCs.
589+
:class:`importlib.abc.MetaPathFinder` and
590+
:class:`importlib.abc.InspectLoader` ABCs.
574591

575592
Only class methods are defined by this class to alleviate the need for
576593
instantiation.
@@ -579,8 +596,8 @@ find and load modules.
579596
.. class:: FrozenImporter
580597

581598
An :term:`importer` for frozen modules. This class implements the
582-
:class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader`
583-
ABCs.
599+
:class:`importlib.abc.MetaPathFinder` and
600+
:class:`importlib.abc.InspectLoader` ABCs.
584601

585602
Only class methods are defined by this class to alleviate the need for
586603
instantiation.
@@ -589,7 +606,7 @@ find and load modules.
589606
.. class:: PathFinder
590607

591608
:term:`Finder` for :data:`sys.path`. This class implements the
592-
:class:`importlib.abc.Finder` ABC.
609+
:class:`importlib.abc.MetaPathFinder` ABC.
593610

594611
This class does not perfectly mirror the semantics of :keyword:`import` in
595612
terms of :data:`sys.path`. No implicit path hooks are assumed for
@@ -616,8 +633,8 @@ find and load modules.
616633

617634
.. class:: FileFinder(path, \*loader_details)
618635

619-
A concrete implementation of :class:`importlib.abc.Finder` which caches
620-
results from the file system.
636+
A concrete implementation of :class:`importlib.abc.PathEntryFinder` which
637+
caches results from the file system.
621638

622639
The *path* argument is the directory for which the finder is in charge of
623640
searching.

Lib/importlib/abc.py

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,48 +23,76 @@ def _register(abstract_cls, *classes):
2323
abstract_cls.register(frozen_cls)
2424

2525

26-
class Loader(metaclass=abc.ABCMeta):
26+
class Finder(metaclass=abc.ABCMeta):
2727

28-
"""Abstract base class for import loaders."""
28+
"""Common abstract base class for import finders.
2929
30-
@abc.abstractmethod
31-
def load_module(self, fullname):
32-
"""Abstract method which when implemented should load a module.
33-
The fullname is a str."""
30+
Finder implementations should derive from the more specific
31+
MetaPathFinder or PathEntryFinder ABCs rather than directly from Finder.
32+
"""
33+
34+
def find_module(self, fullname, path=None):
35+
"""An optional legacy method that should find a module.
36+
The fullname is a str and the optional path is a str or None.
37+
Returns a Loader object.
38+
39+
The path finder will use this method only if find_loader() does
40+
not exist. It may optionally be implemented for compatibility
41+
with legacy third party reimplementations of the import system.
42+
"""
3443
raise NotImplementedError
3544

45+
# invalidate_caches() is a completely optional method, so no default
46+
# implementation is provided. See the docs for details.
47+
48+
49+
class MetaPathFinder(Finder):
50+
51+
"""Abstract base class for import finders on sys.meta_path."""
52+
3653
@abc.abstractmethod
37-
def module_repr(self, module):
38-
"""Abstract method which when implemented calculates and returns the
39-
given module's repr."""
54+
def find_module(self, fullname, path):
55+
"""Abstract method which when implemented should find a module.
56+
The fullname is a str and the path is a str or None.
57+
Returns a Loader object.
58+
"""
4059
raise NotImplementedError
4160

61+
_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
62+
machinery.PathFinder)
4263

43-
class Finder(metaclass=abc.ABCMeta):
4464

45-
"""Abstract base class for import finders."""
65+
class PathEntryFinder(Finder):
66+
67+
"""Abstract base class for path entry finders used by PathFinder."""
4668

4769
@abc.abstractmethod
4870
def find_loader(self, fullname):
4971
"""Abstract method which when implemented returns a module loader.
5072
The fullname is a str. Returns a 2-tuple of (Loader, portion) where
5173
portion is a sequence of file system locations contributing to part of
52-
a namespace package. The sequence may be empty. When present,
53-
`find_loader()` is preferred over `find_module()`.
74+
a namespace package. The sequence may be empty.
5475
"""
5576
raise NotImplementedError
5677

78+
_register(PathEntryFinder, machinery.FileFinder)
79+
80+
81+
class Loader(metaclass=abc.ABCMeta):
82+
83+
"""Abstract base class for import loaders."""
84+
5785
@abc.abstractmethod
58-
def find_module(self, fullname, path=None):
59-
"""Abstract method which when implemented should find a module.
60-
The fullname is a str and the optional path is a str or None.
61-
Returns a Loader object. This method is only called if
62-
`find_loader()` is not present.
63-
"""
86+
def load_module(self, fullname):
87+
"""Abstract method which when implemented should load a module.
88+
The fullname is a str."""
6489
raise NotImplementedError
6590

66-
_register(Finder, machinery.BuiltinImporter, machinery.FrozenImporter,
67-
machinery.PathFinder, machinery.FileFinder)
91+
@abc.abstractmethod
92+
def module_repr(self, module):
93+
"""Abstract method which when implemented calculates and returns the
94+
given module's repr."""
95+
raise NotImplementedError
6896

6997

7098
class ResourceLoader(Loader):

Lib/test/test_importlib/source/test_abc_loader.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -778,23 +778,32 @@ def test_universal_newlines(self):
778778
expect = io.IncrementalNewlineDecoder(None, True).decode(source)
779779
self.assertEqual(mock.get_source(name), expect)
780780

781+
781782
class AbstractMethodImplTests(unittest.TestCase):
782783

783784
"""Test the concrete abstractmethod implementations."""
784785

785-
class Loader(abc.Loader):
786-
def load_module(self, fullname):
787-
super().load_module(fullname)
788-
def module_repr(self, module):
789-
super().module_repr(module)
786+
class MetaPathFinder(abc.MetaPathFinder):
787+
def find_module(self, fullname, path):
788+
super().find_module(fullname, path)
790789

791-
class Finder(abc.Finder):
790+
class PathEntryFinder(abc.PathEntryFinder):
792791
def find_module(self, _):
793792
super().find_module(_)
794793

795794
def find_loader(self, _):
796795
super().find_loader(_)
797796

797+
class Finder(abc.Finder):
798+
def find_module(self, fullname, path):
799+
super().find_module(fullname, path)
800+
801+
class Loader(abc.Loader):
802+
def load_module(self, fullname):
803+
super().load_module(fullname)
804+
def module_repr(self, module):
805+
super().module_repr(module)
806+
798807
class ResourceLoader(Loader, abc.ResourceLoader):
799808
def get_data(self, _):
800809
super().get_data(_)

Lib/test/test_importlib/test_abc.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ def test_superclasses(self):
3030
"{0} is not a superclass of {1}".format(superclass, self.__test))
3131

3232

33-
class Finder(InheritanceTests, unittest.TestCase):
33+
class MetaPathFinder(InheritanceTests, unittest.TestCase):
3434

35+
superclasses = [abc.Finder]
3536
subclasses = [machinery.BuiltinImporter, machinery.FrozenImporter,
3637
machinery.PathFinder]
3738

39+
class PathEntryFinder(InheritanceTests, unittest.TestCase):
40+
41+
superclasses = [abc.Finder]
42+
subclasses = [machinery.FileFinder]
3843

3944
class Loader(InheritanceTests, unittest.TestCase):
4045

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ Core and Builtins
7272
Library
7373
-------
7474

75+
- Issue #15502: Bring the importlib ABCs into line with the current state
76+
of the import protocols given PEP 420. Original patch by Eric Snow.
77+
7578
- Issue #15499: Launching a webbrowser in Unix used to sleep for a few
7679
seconds. Original patch by Anton Barkovsky.
7780

0 commit comments

Comments
 (0)