Issue #15502: Bring the importlib ABCs into line with the current state of the import protocols given PEP 420. Original patch by Eric Snow.
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,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