[Python-checkins] gh-98040: Remove find_loader, find_module and other deprecated APIs (#98059)

warsaw webhook-mailer at python.org
Wed May 3 07:55:30 EDT 2023


https://github.com/python/cpython/commit/326997829d02458246dfd5b6d03297e2418bde52
commit: 326997829d02458246dfd5b6d03297e2418bde52
branch: main
author: Barry Warsaw <barry at python.org>
committer: warsaw <barry at python.org>
date: 2023-05-03T04:55:22-07:00
summary:

gh-98040: Remove find_loader, find_module and other deprecated APIs (#98059)

* Remove deprecated classes from pkgutil
* Remove some other PEP 302 obsolescence
* Use find_spec instead of load_module
* Remove more tests of PEP 302 obsolete APIs
* Remove another bunch of tests using obsolete load_modules()
* Remove deleted names from __all__
* Remove obsolete footnote
* imp is removed
* Remove `imp` from generated stdlib names
* What's new and blurb
* Update zipimport documentation for the removed methods
* Fix some Windows tests
* Remove any test (or part of a test) that references `find_module()`.
* Use assertIsNone() / assertIsNotNone() consistently.
* Update Doc/reference/import.rst
* We don't need pkgutil._get_spec() any more either
*  test.test_importlib.fixtures.NullFinder
* ...BadLoaderFinder.find_module
* ...test_api.InvalidatingNullFinder.find_module
* ...test.test_zipimport test of z.find_module
* Suppress cross-references to find_loader and find_module
* Suppress cross-references to Finder
* Suppress cross-references to pkgutil.ImpImporter and pkgutil.ImpLoader

---------

Co-authored-by: Oleg Iarygin <oleg at arhadthedev.net>
Co-authored-by: Adam Turner <9087854+aa-turner at users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst
M Doc/library/importlib.rst
M Doc/library/pkgutil.rst
M Doc/library/sys.rst
M Doc/library/zipimport.rst
M Doc/reference/import.rst
M Doc/whatsnew/2.3.rst
M Doc/whatsnew/3.10.rst
M Doc/whatsnew/3.11.rst
M Doc/whatsnew/3.12.rst
M Doc/whatsnew/3.3.rst
M Doc/whatsnew/3.4.rst
M Doc/whatsnew/3.7.rst
M Lib/importlib/__init__.py
M Lib/importlib/_bootstrap.py
M Lib/importlib/_bootstrap_external.py
M Lib/importlib/abc.py
M Lib/pkgutil.py
M Lib/pydoc.py
M Lib/test/test_importlib/builtin/test_finder.py
M Lib/test/test_importlib/extension/test_path_hook.py
M Lib/test/test_importlib/fixtures.py
M Lib/test/test_importlib/frozen/test_finder.py
M Lib/test/test_importlib/frozen/test_loader.py
M Lib/test/test_importlib/import_/test___loader__.py
M Lib/test/test_importlib/import_/test___package__.py
M Lib/test/test_importlib/import_/test_api.py
M Lib/test/test_importlib/import_/test_caching.py
M Lib/test/test_importlib/import_/test_meta_path.py
M Lib/test/test_importlib/import_/test_path.py
M Lib/test/test_importlib/source/test_case_sensitivity.py
M Lib/test/test_importlib/source/test_finder.py
M Lib/test/test_importlib/source/test_path_hook.py
M Lib/test/test_importlib/test_abc.py
M Lib/test/test_importlib/test_api.py
M Lib/test/test_importlib/test_windows.py
M Lib/test/test_importlib/util.py
M Lib/test/test_pkgutil.py
M Lib/test/test_zipimport.py

diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst
index 89efa64c6b52..65aaad0df9ee 100644
--- a/Doc/library/importlib.rst
+++ b/Doc/library/importlib.rst
@@ -127,28 +127,6 @@ Functions
     .. versionchanged:: 3.3
        Parent packages are automatically imported.
 
-.. function:: find_loader(name, path=None)
-
-   Find the loader for a module, optionally within the specified *path*. If the
-   module is in :attr:`sys.modules`, then ``sys.modules[name].__loader__`` is
-   returned (unless the loader would be ``None`` or is not set, in which case
-   :exc:`ValueError` is raised). Otherwise a search using :attr:`sys.meta_path`
-   is done. ``None`` is returned if no loader is found.
-
-   A dotted name does not have its parents implicitly imported as that requires
-   loading them and that may not be desired. To properly import a submodule you
-   will need to import all parent packages of the submodule and use the correct
-   argument to *path*.
-
-   .. versionadded:: 3.3
-
-   .. versionchanged:: 3.4
-      If ``__loader__`` is not set, raise :exc:`ValueError`, just like when the
-      attribute is set to ``None``.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.find_spec` instead.
-
 .. function:: invalidate_caches()
 
    Invalidate the internal caches of finders stored at
@@ -247,7 +225,6 @@ are also provided to help in implementing the core ABCs.
 ABC hierarchy::
 
     object
-     +-- Finder (deprecated)
      +-- MetaPathFinder
      +-- PathEntryFinder
      +-- Loader
@@ -258,28 +235,6 @@ ABC hierarchy::
                                      +-- SourceLoader
 
 
-.. class:: Finder
-
-   An abstract base class representing a :term:`finder`.
-
-   .. deprecated:: 3.3
-      Use :class:`MetaPathFinder` or :class:`PathEntryFinder` instead.
-
-   .. abstractmethod:: find_module(fullname, path=None)
-
-      An abstract method for finding a :term:`loader` for the specified
-      module.  Originally specified in :pep:`302`, this method was meant
-      for use in :data:`sys.meta_path` and in the path-based import subsystem.
-
-      .. versionchanged:: 3.4
-         Returns ``None`` when called instead of raising
-         :exc:`NotImplementedError`.
-
-      .. deprecated:: 3.10
-         Implement :meth:`MetaPathFinder.find_spec` or
-         :meth:`PathEntryFinder.find_spec` instead.
-
-
 .. class:: MetaPathFinder
 
    An abstract base class representing a :term:`meta path finder`.
@@ -287,7 +242,7 @@ ABC hierarchy::
    .. versionadded:: 3.3
 
    .. versionchanged:: 3.10
-      No longer a subclass of :class:`Finder`.
+      No longer a subclass of :class:`!Finder`.
 
    .. method:: find_spec(fullname, path, target=None)
 
@@ -303,25 +258,6 @@ ABC hierarchy::
 
       .. versionadded:: 3.4
 
-   .. method:: find_module(fullname, path)
-
-      A legacy method for finding a :term:`loader` for the specified
-      module.  If this is a top-level import, *path* will be ``None``.
-      Otherwise, 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.
-
-      If :meth:`find_spec` is defined, backwards-compatible functionality is
-      provided.
-
-      .. versionchanged:: 3.4
-         Returns ``None`` when called instead of raising
-         :exc:`NotImplementedError`. Can use :meth:`find_spec` to provide
-         functionality.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
    .. method:: invalidate_caches()
 
       An optional method which, when called, should invalidate any internal
@@ -342,7 +278,7 @@ ABC hierarchy::
    .. versionadded:: 3.3
 
    .. versionchanged:: 3.10
-      No longer a subclass of :class:`Finder`.
+      No longer a subclass of :class:`!Finder`.
 
    .. method:: find_spec(fullname, target=None)
 
@@ -356,36 +292,6 @@ ABC hierarchy::
 
       .. versionadded:: 3.4
 
-   .. method:: find_loader(fullname)
-
-      A legacy 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 loader may be ``None`` while specifying ``portion`` to
-      signify the contribution of the file system locations to a namespace
-      package. An empty list can be used for ``portion`` to signify the loader
-      is not part of a namespace package. If ``loader`` is ``None`` and
-      ``portion`` is the empty list then no loader or location for a namespace
-      package were found (i.e. failure to find anything for the module).
-
-      If :meth:`find_spec` is defined then backwards-compatible functionality is
-      provided.
-
-      .. versionchanged:: 3.4
-         Returns ``(None, [])`` instead of raising :exc:`NotImplementedError`.
-         Uses :meth:`find_spec` when available to provide functionality.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
-   .. method:: find_module(fullname)
-
-      A concrete implementation of :meth:`Finder.find_module` which is
-      equivalent to ``self.find_loader(fullname)[0]``.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
    .. method:: invalidate_caches()
 
       An optional method which, when called, should invalidate any internal
@@ -881,13 +787,6 @@ find and load modules.
          is no longer valid then ``None`` is returned but no value is cached
          in :data:`sys.path_importer_cache`.
 
-   .. classmethod:: find_module(fullname, path=None)
-
-      A legacy wrapper around :meth:`find_spec`.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
    .. classmethod:: invalidate_caches()
 
       Calls :meth:`importlib.abc.PathEntryFinder.invalidate_caches` on all
@@ -938,13 +837,6 @@ find and load modules.
 
       .. versionadded:: 3.4
 
-   .. method:: find_loader(fullname)
-
-      Attempt to find the loader to handle *fullname* within :attr:`path`.
-
-      .. deprecated:: 3.10
-         Use :meth:`find_spec` instead.
-
    .. method:: invalidate_caches()
 
       Clear out the internal cache.
diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst
index 64e617b82b48..98e6e294af0c 100644
--- a/Doc/library/pkgutil.rst
+++ b/Doc/library/pkgutil.rst
@@ -48,33 +48,6 @@ support.
    this function to raise an exception (in line with :func:`os.path.isdir`
    behavior).
 
-
-.. class:: ImpImporter(dirname=None)
-
-   :pep:`302` Finder that wraps Python's "classic" import algorithm.
-
-   If *dirname* is a string, a :pep:`302` finder is created that searches that
-   directory.  If *dirname* is ``None``, a :pep:`302` finder is created that
-   searches the current :data:`sys.path`, plus any modules that are frozen or
-   built-in.
-
-   Note that :class:`ImpImporter` does not currently support being used by
-   placement on :data:`sys.meta_path`.
-
-   .. deprecated:: 3.3
-      This emulation is no longer needed, as the standard import mechanism
-      is now fully :pep:`302` compliant and available in :mod:`importlib`.
-
-
-.. class:: ImpLoader(fullname, file, filename, etc)
-
-   :term:`Loader <loader>` that wraps Python's "classic" import algorithm.
-
-   .. deprecated:: 3.3
-      This emulation is no longer needed, as the standard import mechanism
-      is now fully :pep:`302` compliant and available in :mod:`importlib`.
-
-
 .. function:: find_loader(fullname)
 
    Retrieve a module :term:`loader` for the given *fullname*.
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index 95ad243bdde3..57a0d0a1258c 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -1177,7 +1177,7 @@ always available.
 
         :term:`Module specs <module spec>` were introduced in Python 3.4, by
         :pep:`451`. Earlier versions of Python looked for a method called
-        :meth:`~importlib.abc.MetaPathFinder.find_module`.
+        :meth:`!find_module`.
         This is still called as a fallback if a :data:`meta_path` entry doesn't
         have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method.
 
diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst
index fe1adcae163c..11d19e8c863e 100644
--- a/Doc/library/zipimport.rst
+++ b/Doc/library/zipimport.rst
@@ -74,6 +74,11 @@ zipimporter Objects
    :exc:`ZipImportError` is raised if *archivepath* doesn't point to a valid ZIP
    archive.
 
+   .. versionchanged:: 3.12
+
+      Methods ``find_loader()`` and ``find_module()``, deprecated in 3.10 are
+      now removed.  Use :meth:`find_spec` instead.
+
    .. method:: create_module(spec)
 
       Implementation of :meth:`importlib.abc.Loader.create_module` that returns
@@ -89,28 +94,6 @@ zipimporter Objects
       .. versionadded:: 3.10
 
 
-   .. method:: find_loader(fullname, path=None)
-
-      An implementation of :meth:`importlib.abc.PathEntryFinder.find_loader`.
-
-      .. deprecated:: 3.10
-
-         Use :meth:`find_spec` instead.
-
-
-   .. method:: find_module(fullname, path=None)
-
-      Search for a module specified by *fullname*. *fullname* must be the fully
-      qualified (dotted) module name. It returns the zipimporter instance itself
-      if the module was found, or :const:`None` if it wasn't. The optional
-      *path* argument is ignored---it's there for compatibility with the
-      importer protocol.
-
-      .. deprecated:: 3.10
-
-         Use :meth:`find_spec` instead.
-
-
    .. method:: find_spec(fullname, target=None)
 
       An implementation of :meth:`importlib.abc.PathEntryFinder.find_spec`.
diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst
index 57eb5403243e..8f30181ae0a1 100644
--- a/Doc/reference/import.rst
+++ b/Doc/reference/import.rst
@@ -324,15 +324,18 @@ modules, and one that knows how to import modules from an :term:`import path`
 
 .. versionchanged:: 3.4
    The :meth:`~importlib.abc.MetaPathFinder.find_spec` method of meta path
-   finders replaced :meth:`~importlib.abc.MetaPathFinder.find_module`, which
+   finders replaced :meth:`!find_module`, which
    is now deprecated.  While it will continue to work without change, the
    import machinery will try it only if the finder does not implement
    ``find_spec()``.
 
 .. versionchanged:: 3.10
-   Use of :meth:`~importlib.abc.MetaPathFinder.find_module` by the import system
+   Use of :meth:`!find_module` by the import system
    now raises :exc:`ImportWarning`.
 
+.. versionchanged:: 3.12
+   ``find_module()`` has been removed.  Use :meth:`find_spec` instead.
+
 
 Loading
 =======
@@ -837,7 +840,7 @@ stores finder objects rather than being limited to :term:`importer` objects).
 In this way, the expensive search for a particular :term:`path entry`
 location's :term:`path entry finder` need only be done once.  User code is
 free to remove cache entries from :data:`sys.path_importer_cache` forcing
-the path based finder to perform the path entry search again [#fnpic]_.
+the path based finder to perform the path entry search again.
 
 If the path entry is not present in the cache, the path based finder iterates
 over every callable in :data:`sys.path_hooks`.  Each of the :term:`path entry
@@ -887,13 +890,13 @@ module.  ``find_spec()`` returns a fully populated spec for the module.
 This spec will always have "loader" set (with one exception).
 
 To indicate to the import machinery that the spec represents a namespace
-:term:`portion`, the path entry finder sets "submodule_search_locations" to
+:term:`portion`, the path entry finder sets ``submodule_search_locations`` to
 a list containing the portion.
 
 .. versionchanged:: 3.4
    :meth:`~importlib.abc.PathEntryFinder.find_spec` replaced
-   :meth:`~importlib.abc.PathEntryFinder.find_loader` and
-   :meth:`~importlib.abc.PathEntryFinder.find_module`, both of which
+   :meth:`!find_loader` and
+   :meth:`!find_module`, both of which
    are now deprecated, but will be used if ``find_spec()`` is not defined.
 
    Older path entry finders may implement one of these two deprecated methods
@@ -901,7 +904,7 @@ a list containing the portion.
    sake of backward compatibility.  However, if ``find_spec()`` is
    implemented on the path entry finder, the legacy methods are ignored.
 
-   :meth:`~importlib.abc.PathEntryFinder.find_loader` takes one argument, the
+   :meth:`!find_loader` takes one argument, the
    fully qualified name of the module being imported.  ``find_loader()``
    returns a 2-tuple where the first item is the loader and the second item
    is a namespace :term:`portion`.
@@ -920,10 +923,13 @@ a list containing the portion.
    ``find_loader()`` in preference to ``find_module()``.
 
 .. versionchanged:: 3.10
-    Calls to :meth:`~importlib.abc.PathEntryFinder.find_module` and
-    :meth:`~importlib.abc.PathEntryFinder.find_loader` by the import
+    Calls to :meth:`!find_module` and
+    :meth:`!find_loader` by the import
     system will raise :exc:`ImportWarning`.
 
+.. versionchanged:: 3.12
+    ``find_module()`` and ``find_loader()`` have been removed.
+
 
 Replacing the standard import system
 ====================================
@@ -1045,8 +1051,8 @@ The original specification for :data:`sys.meta_path` was :pep:`302`, with
 subsequent extension in :pep:`420`.
 
 :pep:`420` introduced :term:`namespace packages <namespace package>` for
-Python 3.3.  :pep:`420` also introduced the :meth:`find_loader` protocol as an
-alternative to :meth:`find_module`.
+Python 3.3.  :pep:`420` also introduced the :meth:`!find_loader` protocol as an
+alternative to :meth:`!find_module`.
 
 :pep:`366` describes the addition of the ``__package__`` attribute for
 explicit relative imports in main modules.
@@ -1073,9 +1079,3 @@ methods to finders and loaders.
    module may replace itself in :data:`sys.modules`.  This is
    implementation-specific behavior that is not guaranteed to work in other
    Python implementations.
-
-.. [#fnpic] In legacy code, it is possible to find instances of
-   :class:`imp.NullImporter` in the :data:`sys.path_importer_cache`.  It
-   is recommended that code be changed to use ``None`` instead.  See
-   :ref:`portingpythoncode` for more details.  Note that the ``imp`` module
-   was removed in Python 3.12.
diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst
index af489d7cb45c..4eb864f5092d 100644
--- a/Doc/whatsnew/2.3.rst
+++ b/Doc/whatsnew/2.3.rst
@@ -728,7 +728,7 @@ module:
 
 Importer objects must have a single method, ``find_module(fullname,
 path=None)``.  *fullname* will be a module or package name, e.g. ``string`` or
-``distutils.core``.  :meth:`find_module` must return a loader object that has a
+``distutils.core``.  :meth:`!find_module` must return a loader object that has a
 single method, ``load_module(fullname)``, that creates and returns the
 corresponding module object.
 
diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst
index f6a48ed2680c..44c8fa1e9eb2 100644
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -1608,7 +1608,7 @@ Deprecated
 * Starting in this release, there will be a concerted effort to begin
   cleaning up old import semantics that were kept for Python 2.7
   compatibility. Specifically,
-  :meth:`~importlib.abc.PathEntryFinder.find_loader`/:meth:`~importlib.abc.Finder.find_module`
+  :meth:`!find_loader`/:meth:`!find_module`
   (superseded by :meth:`~importlib.abc.Finder.find_spec`),
   :meth:`~importlib.abc.Loader.load_module`
   (superseded by :meth:`~importlib.abc.Loader.exec_module`),
@@ -1645,8 +1645,8 @@ Deprecated
   :meth:`~importlib.abc.Loader.exec_module` is preferred.
   (Contributed by Brett Cannon in :issue:`26131`.)
 
-* The use of :meth:`importlib.abc.MetaPathFinder.find_module` and
-  :meth:`importlib.abc.PathEntryFinder.find_module` by the import system now
+* The use of :meth:`!importlib.abc.MetaPathFinder.find_module` and
+  :meth:`!importlib.abc.PathEntryFinder.find_module` by the import system now
   trigger an :exc:`ImportWarning` as
   :meth:`importlib.abc.MetaPathFinder.find_spec` and
   :meth:`importlib.abc.PathEntryFinder.find_spec`
@@ -1654,40 +1654,40 @@ Deprecated
   :func:`importlib.util.spec_from_loader` to help in porting.
   (Contributed by Brett Cannon in :issue:`42134`.)
 
-* The use of :meth:`importlib.abc.PathEntryFinder.find_loader` by the import
+* The use of :meth:`!importlib.abc.PathEntryFinder.find_loader` by the import
   system now triggers an :exc:`ImportWarning` as
   :meth:`importlib.abc.PathEntryFinder.find_spec` is preferred. You can use
   :func:`importlib.util.spec_from_loader` to help in porting.
   (Contributed by Brett Cannon in :issue:`43672`.)
 
 * The various implementations of
-  :meth:`importlib.abc.MetaPathFinder.find_module` (
-  :meth:`importlib.machinery.BuiltinImporter.find_module`,
-  :meth:`importlib.machinery.FrozenImporter.find_module`,
-  :meth:`importlib.machinery.WindowsRegistryFinder.find_module`,
-  :meth:`importlib.machinery.PathFinder.find_module`,
-  :meth:`importlib.abc.MetaPathFinder.find_module` ),
-  :meth:`importlib.abc.PathEntryFinder.find_module` (
-  :meth:`importlib.machinery.FileFinder.find_module` ), and
-  :meth:`importlib.abc.PathEntryFinder.find_loader` (
-  :meth:`importlib.machinery.FileFinder.find_loader` )
+  :meth:`!importlib.abc.MetaPathFinder.find_module` (
+  :meth:`!importlib.machinery.BuiltinImporter.find_module`,
+  :meth:`!importlib.machinery.FrozenImporter.find_module`,
+  :meth:`!importlib.machinery.WindowsRegistryFinder.find_module`,
+  :meth:`!importlib.machinery.PathFinder.find_module`,
+  :meth:`!importlib.abc.MetaPathFinder.find_module` ),
+  :meth:`!importlib.abc.PathEntryFinder.find_module` (
+  :meth:`!importlib.machinery.FileFinder.find_module` ), and
+  :meth:`!importlib.abc.PathEntryFinder.find_loader` (
+  :meth:`!importlib.machinery.FileFinder.find_loader` )
   now raise :exc:`DeprecationWarning` and are slated for removal in
   Python 3.12 (previously they were documented as deprecated in Python 3.4).
   (Contributed by Brett Cannon in :issue:`42135`.)
 
-* :class:`importlib.abc.Finder` is deprecated (including its sole method,
-  :meth:`~importlib.abc.Finder.find_module`). Both
+* :class:`!importlib.abc.Finder` is deprecated (including its sole method,
+  :meth:`!find_module`). Both
   :class:`importlib.abc.MetaPathFinder` and :class:`importlib.abc.PathEntryFinder`
   no longer inherit from the class. Users should inherit from one of these two
   classes as appropriate instead.
   (Contributed by Brett Cannon in :issue:`42135`.)
 
-* The deprecations of :mod:`imp`, :func:`importlib.find_loader`,
+* The deprecations of :mod:`imp`, :func:`!importlib.find_loader`,
   :func:`importlib.util.set_package_wrapper`,
   :func:`importlib.util.set_loader_wrapper`,
   :func:`importlib.util.module_for_loader`,
-  :class:`pkgutil.ImpImporter`, and
-  :class:`pkgutil.ImpLoader` have all been updated to list Python 3.12 as the
+  :class:`!pkgutil.ImpImporter`, and
+  :class:`!pkgutil.ImpLoader` have all been updated to list Python 3.12 as the
   slated version of removal (they began raising :exc:`DeprecationWarning` in
   previous versions of Python).
   (Contributed by Brett Cannon in :issue:`43720`.)
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 6b591d5e184e..918a6824618c 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1876,24 +1876,24 @@ C APIs pending removal are
 * The :class:`typing.io <typing.IO>` namespace
 * The :class:`typing.re <typing.Pattern>` namespace
 * :func:`!cgi.log`
-* :func:`importlib.find_loader`
+* :func:`!importlib.find_loader`
 * :meth:`importlib.abc.Loader.module_repr`
-* :meth:`importlib.abc.MetaPathFinder.find_module`
-* :meth:`importlib.abc.PathEntryFinder.find_loader`
-* :meth:`importlib.abc.PathEntryFinder.find_module`
+* :meth:`!importlib.abc.MetaPathFinder.find_module`
+* :meth:`!importlib.abc.PathEntryFinder.find_loader`
+* :meth:`!importlib.abc.PathEntryFinder.find_module`
 * :meth:`!importlib.machinery.BuiltinImporter.find_module`
 * :meth:`!importlib.machinery.BuiltinLoader.module_repr`
 * :meth:`!importlib.machinery.FileFinder.find_loader`
 * :meth:`!importlib.machinery.FileFinder.find_module`
 * :meth:`!importlib.machinery.FrozenImporter.find_module`
 * :meth:`!importlib.machinery.FrozenLoader.module_repr`
-* :meth:`importlib.machinery.PathFinder.find_module`
+* :meth:`!importlib.machinery.PathFinder.find_module`
 * :meth:`!importlib.machinery.WindowsRegistryFinder.find_module`
 * :func:`importlib.util.module_for_loader`
 * :func:`!importlib.util.set_loader_wrapper`
 * :func:`!importlib.util.set_package_wrapper`
-* :class:`pkgutil.ImpImporter`
-* :class:`pkgutil.ImpLoader`
+* :class:`!pkgutil.ImpImporter`
+* :class:`!pkgutil.ImpLoader`
 * :meth:`pathlib.Path.link_to`
 * :func:`!sqlite3.enable_shared_cache`
 * :func:`!sqlite3.OptimizedUnicode`
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index 5f8a1f08026d..1139bb89f5cf 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -983,14 +983,20 @@ Removed
 * Many previously deprecated cleanups in :mod:`importlib` have now been
   completed:
 
-  * References to, and support for ``module_repr()`` has been eradicated.
+  * References to, and support for ``module_repr()`` has been removed.
     (Contributed by Barry Warsaw in :gh:`97850`.)
 
-* ``importlib.util.set_package`` has been removed.
-  (Contributed by Brett Cannon in :gh:`65961`.)
+  * ``importlib.util.set_package`` has been removed. (Contributed by Brett
+    Cannon in :gh:`65961`.)
+
+  * Support for ``find_loader()`` and ``find_module()`` APIs have been
+    removed.  (Contributed by Barry Warsaw in :gh:`98040`.)
+
+  * ``importlib.abc.Finder``, ``pkg.ImpImporter``, and ``pkg.ImpLoader`` have
+    been removed.  (Contributed by Barry Warsaw in :gh:`98040`.)
 
-* The ``imp`` module has been removed.  (Contributed by Barry Warsaw in
-  :gh:`98040`.)
+  * The ``imp`` module has been removed.  (Contributed by Barry Warsaw in
+    :gh:`98040`.)
 
 * Removed the ``suspicious`` rule from the documentation Makefile, and
   removed ``Doc/tools/rstlint.py``, both in favor of `sphinx-lint
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index 5b6c3dcd45c6..df1f2ab775b0 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -714,7 +714,7 @@ to properly delineate between :term:`meta path finders <meta path finder>`
 and :term:`path entry finders <path entry finder>` by introducing
 :class:`importlib.abc.MetaPathFinder` and
 :class:`importlib.abc.PathEntryFinder`, respectively. The old ABC of
-:class:`importlib.abc.Finder` is now only provided for backwards-compatibility
+:class:`!importlib.abc.Finder` is now only provided for backwards-compatibility
 and does not enforce any method requirements.
 
 In terms of finders, :class:`importlib.machinery.FileFinder` exposes the
@@ -2390,7 +2390,7 @@ Porting Python code
   :attr:`sys.path_importer_cache` where it represents the use of implicit
   finders, but semantically it should not change anything.
 
-* :class:`importlib.abc.Finder` no longer specifies a ``find_module()`` abstract
+* :class:`!importlib.abc.Finder` no longer specifies a ``find_module()`` abstract
   method that must be implemented. If you were relying on subclasses to
   implement that method, make sure to check for the method's existence first.
   You will probably want to check for ``find_loader()`` first, though, in the
diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst
index b7bb505a8184..53f78e3621cf 100644
--- a/Doc/whatsnew/3.4.rst
+++ b/Doc/whatsnew/3.4.rst
@@ -2077,19 +2077,19 @@ Deprecations in the Python API
 ------------------------------
 
 * As mentioned in :ref:`whatsnew-pep-451`, a number of :mod:`importlib`
-  methods and functions are deprecated: :meth:`importlib.find_loader` is
+  methods and functions are deprecated: :meth:`!importlib.find_loader` is
   replaced by :func:`importlib.util.find_spec`;
-  :meth:`importlib.machinery.PathFinder.find_module` is replaced by
+  :meth:`!importlib.machinery.PathFinder.find_module` is replaced by
   :meth:`importlib.machinery.PathFinder.find_spec`;
-  :meth:`importlib.abc.MetaPathFinder.find_module` is replaced by
+  :meth:`!importlib.abc.MetaPathFinder.find_module` is replaced by
   :meth:`importlib.abc.MetaPathFinder.find_spec`;
-  :meth:`importlib.abc.PathEntryFinder.find_loader` and
-  :meth:`~importlib.abc.PathEntryFinder.find_module` are replaced by
+  :meth:`!importlib.abc.PathEntryFinder.find_loader` and
+  :meth:`!find_module` are replaced by
   :meth:`importlib.abc.PathEntryFinder.find_spec`; all of the ``xxxLoader`` ABC
-  ``load_module`` methods (:meth:`importlib.abc.Loader.load_module`,
-  :meth:`importlib.abc.InspectLoader.load_module`,
-  :meth:`importlib.abc.FileLoader.load_module`,
-  :meth:`importlib.abc.SourceLoader.load_module`) should no longer be
+  ``load_module`` methods (:meth:`!importlib.abc.Loader.load_module`,
+  :meth:`!importlib.abc.InspectLoader.load_module`,
+  :meth:`!importlib.abc.FileLoader.load_module`,
+  :meth:`!importlib.abc.SourceLoader.load_module`) should no longer be
   implemented, instead loaders should implement an
   ``exec_module`` method
   (:meth:`importlib.abc.Loader.exec_module`,
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index df3b636cb9ec..28f22836d8d0 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -2004,11 +2004,11 @@ importlib
 ---------
 
 Methods
-:meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>`
+:meth:`MetaPathFinder.find_module() <!importlib.abc.MetaPathFinder.find_module>`
 (replaced by
 :meth:`MetaPathFinder.find_spec() <importlib.abc.MetaPathFinder.find_spec>`)
 and
-:meth:`PathEntryFinder.find_loader() <importlib.abc.PathEntryFinder.find_loader>`
+:meth:`PathEntryFinder.find_loader() <!importlib.abc.PathEntryFinder.find_loader>`
 (replaced by
 :meth:`PathEntryFinder.find_spec() <importlib.abc.PathEntryFinder.find_spec>`)
 both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`.
diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py
index 21d9dee652b3..707c081cb2c5 100644
--- a/Lib/importlib/__init__.py
+++ b/Lib/importlib/__init__.py
@@ -70,40 +70,6 @@ def invalidate_caches():
             finder.invalidate_caches()
 
 
-def find_loader(name, path=None):
-    """Return the loader for the specified module.
-
-    This is a backward-compatible wrapper around find_spec().
-
-    This function is deprecated in favor of importlib.util.find_spec().
-
-    """
-    warnings.warn('Deprecated since Python 3.4 and slated for removal in '
-                  'Python 3.12; use importlib.util.find_spec() instead',
-                  DeprecationWarning, stacklevel=2)
-    try:
-        loader = sys.modules[name].__loader__
-        if loader is None:
-            raise ValueError(f'{name}.__loader__ is None')
-        else:
-            return loader
-    except KeyError:
-        pass
-    except AttributeError:
-        raise ValueError(f'{name}.__loader__ is not set') from None
-
-    spec = _bootstrap._find_spec(name, path)
-    # We won't worry about malformed specs (missing attributes).
-    if spec is None:
-        return None
-    if spec.loader is None:
-        if spec.submodule_search_locations is None:
-            raise ImportError(f'spec for {name} missing loader', name=name)
-        raise ImportError('namespace packages do not have loaders',
-                          name=name)
-    return spec.loader
-
-
 def import_module(name, package=None):
     """Import a module.
 
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index e4fcaa61e6de..c48fd506a0e4 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -892,21 +892,6 @@ def find_spec(cls, fullname, path=None, target=None):
         else:
             return None
 
-    @classmethod
-    def find_module(cls, fullname, path=None):
-        """Find the built-in module.
-
-        If 'path' is ever specified then the search is considered a failure.
-
-        This method is deprecated.  Use find_spec() instead.
-
-        """
-        _warnings.warn("BuiltinImporter.find_module() is deprecated and "
-                       "slated for removal in Python 3.12; use find_spec() instead",
-                       DeprecationWarning)
-        spec = cls.find_spec(fullname, path)
-        return spec.loader if spec is not None else None
-
     @staticmethod
     def create_module(spec):
         """Create a built-in module"""
@@ -1076,18 +1061,6 @@ def find_spec(cls, fullname, path=None, target=None):
             spec.submodule_search_locations.insert(0, pkgdir)
         return spec
 
-    @classmethod
-    def find_module(cls, fullname, path=None):
-        """Find a frozen module.
-
-        This method is deprecated.  Use find_spec() instead.
-
-        """
-        _warnings.warn("FrozenImporter.find_module() is deprecated and "
-                       "slated for removal in Python 3.12; use find_spec() instead",
-                       DeprecationWarning)
-        return cls if _imp.is_frozen(fullname) else None
-
     @staticmethod
     def create_module(spec):
         """Set __file__, if able."""
@@ -1170,16 +1143,6 @@ def _resolve_name(name, package, level):
     return f'{base}.{name}' if name else base
 
 
-def _find_spec_legacy(finder, name, path):
-    msg = (f"{_object_name(finder)}.find_spec() not found; "
-                           "falling back to find_module()")
-    _warnings.warn(msg, ImportWarning)
-    loader = finder.find_module(name, path)
-    if loader is None:
-        return None
-    return spec_from_loader(name, loader)
-
-
 def _find_spec(name, path, target=None):
     """Find a module's spec."""
     meta_path = sys.meta_path
@@ -1200,9 +1163,7 @@ def _find_spec(name, path, target=None):
             try:
                 find_spec = finder.find_spec
             except AttributeError:
-                spec = _find_spec_legacy(finder, name, path)
-                if spec is None:
-                    continue
+                continue
             else:
                 spec = find_spec(name, path, target)
         if spec is not None:
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index cb227373ca2f..7a3fdbaebdf2 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -659,26 +659,6 @@ def _wrap(new, old):
     return _check_name_wrapper
 
 
-def _find_module_shim(self, fullname):
-    """Try to find a loader for the specified module by delegating to
-    self.find_loader().
-
-    This method is deprecated in favor of finder.find_spec().
-
-    """
-    _warnings.warn("find_module() is deprecated and "
-                   "slated for removal in Python 3.12; use find_spec() instead",
-                   DeprecationWarning)
-    # Call find_loader(). If it returns a string (indicating this
-    # is a namespace package portion), generate a warning and
-    # return None.
-    loader, portions = self.find_loader(fullname)
-    if loader is None and len(portions):
-        msg = f'Not importing directory {portions[0]}: missing __init__'
-        _warnings.warn(msg, ImportWarning)
-    return loader
-
-
 def _classify_pyc(data, name, exc_details):
     """Perform basic validity checking of a pyc header and return the flags field,
     which determines how the pyc should be further validated against the source.
@@ -985,22 +965,6 @@ def find_spec(cls, fullname, path=None, target=None):
                                                    origin=filepath)
                 return spec
 
-    @classmethod
-    def find_module(cls, fullname, path=None):
-        """Find module named in the registry.
-
-        This method is deprecated.  Use find_spec() instead.
-
-        """
-        _warnings.warn("WindowsRegistryFinder.find_module() is deprecated and "
-                       "slated for removal in Python 3.12; use find_spec() instead",
-                       DeprecationWarning)
-        spec = cls.find_spec(fullname, path)
-        if spec is not None:
-            return spec.loader
-        else:
-            return None
-
 
 class _LoaderBasics:
 
@@ -1517,27 +1481,6 @@ def _path_importer_cache(cls, path):
             sys.path_importer_cache[path] = finder
         return finder
 
-    @classmethod
-    def _legacy_get_spec(cls, fullname, finder):
-        # This would be a good place for a DeprecationWarning if
-        # we ended up going that route.
-        if hasattr(finder, 'find_loader'):
-            msg = (f"{_bootstrap._object_name(finder)}.find_spec() not found; "
-                    "falling back to find_loader()")
-            _warnings.warn(msg, ImportWarning)
-            loader, portions = finder.find_loader(fullname)
-        else:
-            msg = (f"{_bootstrap._object_name(finder)}.find_spec() not found; "
-                    "falling back to find_module()")
-            _warnings.warn(msg, ImportWarning)
-            loader = finder.find_module(fullname)
-            portions = []
-        if loader is not None:
-            return _bootstrap.spec_from_loader(fullname, loader)
-        spec = _bootstrap.ModuleSpec(fullname, None)
-        spec.submodule_search_locations = portions
-        return spec
-
     @classmethod
     def _get_spec(cls, fullname, path, target=None):
         """Find the loader or namespace_path for this module/package name."""
@@ -1549,10 +1492,7 @@ def _get_spec(cls, fullname, path, target=None):
                 continue
             finder = cls._path_importer_cache(entry)
             if finder is not None:
-                if hasattr(finder, 'find_spec'):
-                    spec = finder.find_spec(fullname, target)
-                else:
-                    spec = cls._legacy_get_spec(fullname, finder)
+                spec = finder.find_spec(fullname, target)
                 if spec is None:
                     continue
                 if spec.loader is not None:
@@ -1594,22 +1534,6 @@ def find_spec(cls, fullname, path=None, target=None):
         else:
             return spec
 
-    @classmethod
-    def find_module(cls, fullname, path=None):
-        """find the module on sys.path or 'path' based on sys.path_hooks and
-        sys.path_importer_cache.
-
-        This method is deprecated.  Use find_spec() instead.
-
-        """
-        _warnings.warn("PathFinder.find_module() is deprecated and "
-                       "slated for removal in Python 3.12; use find_spec() instead",
-                       DeprecationWarning)
-        spec = cls.find_spec(fullname, path)
-        if spec is None:
-            return None
-        return spec.loader
-
     @staticmethod
     def find_distributions(*args, **kwargs):
         """
@@ -1654,23 +1578,6 @@ def invalidate_caches(self):
         """Invalidate the directory mtime."""
         self._path_mtime = -1
 
-    find_module = _find_module_shim
-
-    def find_loader(self, fullname):
-        """Try to find a loader for the specified module, or the namespace
-        package portions. Returns (loader, list-of-portions).
-
-        This method is deprecated.  Use find_spec() instead.
-
-        """
-        _warnings.warn("FileFinder.find_loader() is deprecated and "
-                       "slated for removal in Python 3.12; use find_spec() instead",
-                       DeprecationWarning)
-        spec = self.find_spec(fullname)
-        if spec is None:
-            return None, []
-        return spec.loader, spec.submodule_search_locations or []
-
     def _get_spec(self, loader_class, fullname, path, smsl, target):
         loader = loader_class(fullname, path)
         return spec_from_file_location(fullname, path, loader=loader,
diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py
index 8fa9a0f3bc1e..b56fa94eb9c1 100644
--- a/Lib/importlib/abc.py
+++ b/Lib/importlib/abc.py
@@ -19,7 +19,7 @@
 
 
 __all__ = [
-    'Loader', 'Finder', 'MetaPathFinder', 'PathEntryFinder',
+    'Loader', 'MetaPathFinder', 'PathEntryFinder',
     'ResourceLoader', 'InspectLoader', 'ExecutionLoader',
     'FileLoader', 'SourceLoader',
 ]
@@ -49,38 +49,6 @@ def _register(abstract_cls, *classes):
             abstract_cls.register(frozen_cls)
 
 
-class Finder(metaclass=abc.ABCMeta):
-
-    """Legacy abstract base class for import finders.
-
-    It may be subclassed for compatibility with legacy third party
-    reimplementations of the import system.  Otherwise, finder
-    implementations should derive from the more specific MetaPathFinder
-    or PathEntryFinder ABCs.
-
-    Deprecated since Python 3.3
-    """
-
-    def __init__(self):
-        warnings.warn("the Finder ABC is deprecated and "
-                       "slated for removal in Python 3.12; use MetaPathFinder "
-                       "or PathEntryFinder instead",
-                       DeprecationWarning)
-
-    @abc.abstractmethod
-    def find_module(self, fullname, path=None):
-        """An abstract method that should find a module.
-        The fullname is a str and the optional path is a str or None.
-        Returns a Loader object or None.
-        """
-        warnings.warn("importlib.abc.Finder along with its find_module() "
-                      "method are deprecated and "
-                       "slated for removal in Python 3.12; use "
-                       "MetaPathFinder.find_spec() or "
-                       "PathEntryFinder.find_spec() instead",
-                       DeprecationWarning)
-
-
 class MetaPathFinder(metaclass=abc.ABCMeta):
 
     """Abstract base class for import finders on sys.meta_path."""
@@ -88,27 +56,6 @@ class MetaPathFinder(metaclass=abc.ABCMeta):
     # We don't define find_spec() here since that would break
     # hasattr checks we do to support backward compatibility.
 
-    def find_module(self, fullname, path):
-        """Return a loader for the module.
-
-        If no module is found, return None.  The fullname is a str and
-        the path is a list of strings or None.
-
-        This method is deprecated since Python 3.4 in favor of
-        finder.find_spec(). If find_spec() exists then backwards-compatible
-        functionality is provided for this method.
-
-        """
-        warnings.warn("MetaPathFinder.find_module() is deprecated since Python "
-                      "3.4 in favor of MetaPathFinder.find_spec() and is "
-                      "slated for removal in Python 3.12",
-                      DeprecationWarning,
-                      stacklevel=2)
-        if not hasattr(self, 'find_spec'):
-            return None
-        found = self.find_spec(fullname, path)
-        return found.loader if found is not None else None
-
     def invalidate_caches(self):
         """An optional method for clearing the finder's cache, if any.
         This method is used by importlib.invalidate_caches().
@@ -122,43 +69,6 @@ class PathEntryFinder(metaclass=abc.ABCMeta):
 
     """Abstract base class for path entry finders used by PathFinder."""
 
-    # We don't define find_spec() here since that would break
-    # hasattr checks we do to support backward compatibility.
-
-    def find_loader(self, fullname):
-        """Return (loader, namespace portion) for the path entry.
-
-        The fullname is a str.  The namespace portion is a sequence of
-        path entries contributing to part of a namespace package. The
-        sequence may be empty.  If loader is not None, the portion will
-        be ignored.
-
-        The portion will be discarded if another path entry finder
-        locates the module as a normal module or package.
-
-        This method is deprecated since Python 3.4 in favor of
-        finder.find_spec(). If find_spec() is provided than backwards-compatible
-        functionality is provided.
-        """
-        warnings.warn("PathEntryFinder.find_loader() is deprecated since Python "
-                      "3.4 in favor of PathEntryFinder.find_spec() "
-                      "(available since 3.4)",
-                      DeprecationWarning,
-                      stacklevel=2)
-        if not hasattr(self, 'find_spec'):
-            return None, []
-        found = self.find_spec(fullname)
-        if found is not None:
-            if not found.submodule_search_locations:
-                portions = []
-            else:
-                portions = found.submodule_search_locations
-            return found.loader, portions
-        else:
-            return None, []
-
-    find_module = _bootstrap_external._find_module_shim
-
     def invalidate_caches(self):
         """An optional method for clearing the finder's cache, if any.
         This method is used by PathFinder.invalidate_caches().
diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py
index fb977eaaa057..f62eccb974d6 100644
--- a/Lib/pkgutil.py
+++ b/Lib/pkgutil.py
@@ -23,20 +23,6 @@
 ModuleInfo.__doc__ = 'A namedtuple with minimal info about a module.'
 
 
-def _get_spec(finder, name):
-    """Return the finder-specific module spec."""
-    # Works with legacy finders.
-    try:
-        find_spec = finder.find_spec
-    except AttributeError:
-        loader = finder.find_module(name)
-        if loader is None:
-            return None
-        return importlib.util.spec_from_loader(name, loader)
-    else:
-        return find_spec(name)
-
-
 def read_code(stream):
     # This helper is needed in order for the PEP 302 emulation to
     # correctly handle compiled files
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 1c3443fa8469..b10a5da99402 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -2242,7 +2242,7 @@ def run(self, callback, key=None, completer=None, onerror=None):
                 callback(None, modname, '')
             else:
                 try:
-                    spec = pkgutil._get_spec(importer, modname)
+                    spec = importer.find_spec(modname)
                 except SyntaxError:
                     # raised by tests for bad coding cookies or BOM
                     continue
diff --git a/Lib/test/test_importlib/builtin/test_finder.py b/Lib/test/test_importlib/builtin/test_finder.py
index 81dc5a3699d9..111c4af1ea7c 100644
--- a/Lib/test/test_importlib/builtin/test_finder.py
+++ b/Lib/test/test_importlib/builtin/test_finder.py
@@ -43,38 +43,5 @@ def test_failure(self):
  ) = util.test_both(FindSpecTests, machinery=machinery)
 
 
- at unittest.skipIf(util.BUILTINS.good_name is None, 'no reasonable builtin module')
-class FinderTests(abc.FinderTests):
-
-    """Test find_module() for built-in modules."""
-
-    def test_module(self):
-        # Common case.
-        with util.uncache(util.BUILTINS.good_name):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", DeprecationWarning)
-                found = self.machinery.BuiltinImporter.find_module(util.BUILTINS.good_name)
-            self.assertTrue(found)
-            self.assertTrue(hasattr(found, 'load_module'))
-
-    # Built-in modules cannot be a package.
-    test_package = test_package_in_package = test_package_over_module = None
-
-    # Built-in modules cannot be in a package.
-    test_module_in_package = None
-
-    def test_failure(self):
-        assert 'importlib' not in sys.builtin_module_names
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            loader = self.machinery.BuiltinImporter.find_module('importlib')
-        self.assertIsNone(loader)
-
-
-(Frozen_FinderTests,
- Source_FinderTests
- ) = util.test_both(FinderTests, machinery=machinery)
-
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/test/test_importlib/extension/test_path_hook.py b/Lib/test/test_importlib/extension/test_path_hook.py
index a0adc70ad1ec..ec9644dc5205 100644
--- a/Lib/test/test_importlib/extension/test_path_hook.py
+++ b/Lib/test/test_importlib/extension/test_path_hook.py
@@ -19,7 +19,7 @@ def hook(self, entry):
     def test_success(self):
         # Path hook should handle a directory where a known extension module
         # exists.
-        self.assertTrue(hasattr(self.hook(util.EXTENSIONS.path), 'find_module'))
+        self.assertTrue(hasattr(self.hook(util.EXTENSIONS.path), 'find_spec'))
 
 
 (Frozen_PathHooksTests,
diff --git a/Lib/test/test_importlib/fixtures.py b/Lib/test/test_importlib/fixtures.py
index a364a977bce7..73e5da2ba922 100644
--- a/Lib/test/test_importlib/fixtures.py
+++ b/Lib/test/test_importlib/fixtures.py
@@ -350,11 +350,6 @@ def DALS(str):
     return textwrap.dedent(str).lstrip()
 
 
-class NullFinder:
-    def find_module(self, name):
-        pass
-
-
 @requires_zlib()
 class ZipFixtures:
     root = 'test.test_importlib.data'
diff --git a/Lib/test/test_importlib/frozen/test_finder.py b/Lib/test/test_importlib/frozen/test_finder.py
index 069755606b40..469dcdbd09ea 100644
--- a/Lib/test/test_importlib/frozen/test_finder.py
+++ b/Lib/test/test_importlib/frozen/test_finder.py
@@ -182,45 +182,5 @@ def test_not_using_frozen(self):
  ) = util.test_both(FindSpecTests, machinery=machinery)
 
 
-class FinderTests(abc.FinderTests):
-
-    """Test finding frozen modules."""
-
-    def find(self, name, path=None):
-        finder = self.machinery.FrozenImporter
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            with import_helper.frozen_modules():
-                return finder.find_module(name, path)
-
-    def test_module(self):
-        name = '__hello__'
-        loader = self.find(name)
-        self.assertTrue(hasattr(loader, 'load_module'))
-
-    def test_package(self):
-        loader = self.find('__phello__')
-        self.assertTrue(hasattr(loader, 'load_module'))
-
-    def test_module_in_package(self):
-        loader = self.find('__phello__.spam', ['__phello__'])
-        self.assertTrue(hasattr(loader, 'load_module'))
-
-    # No frozen package within another package to test with.
-    test_package_in_package = None
-
-    # No easy way to test.
-    test_package_over_module = None
-
-    def test_failure(self):
-        loader = self.find('<not real>')
-        self.assertIsNone(loader)
-
-
-(Frozen_FinderTests,
- Source_FinderTests
- ) = util.test_both(FinderTests, machinery=machinery)
-
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/test/test_importlib/frozen/test_loader.py b/Lib/test/test_importlib/frozen/test_loader.py
index da1569e3d068..4f1af454b52c 100644
--- a/Lib/test/test_importlib/frozen/test_loader.py
+++ b/Lib/test/test_importlib/frozen/test_loader.py
@@ -125,88 +125,6 @@ def test_unloadable(self):
  ) = util.test_both(ExecModuleTests, machinery=machinery)
 
 
-class LoaderTests(abc.LoaderTests):
-
-    def load_module(self, name):
-        with fresh(name, oldapi=True):
-            module = self.machinery.FrozenImporter.load_module(name)
-        with captured_stdout() as stdout:
-            module.main()
-        return module, stdout
-
-    def test_module(self):
-        module, stdout = self.load_module('__hello__')
-        filename = resolve_stdlib_file('__hello__')
-        check = {'__name__': '__hello__',
-                '__package__': '',
-                '__loader__': self.machinery.FrozenImporter,
-                '__file__': filename,
-                }
-        for attr, value in check.items():
-            self.assertEqual(getattr(module, attr, None), value)
-        self.assertEqual(stdout.getvalue(), 'Hello world!\n')
-
-    def test_package(self):
-        module, stdout = self.load_module('__phello__')
-        filename = resolve_stdlib_file('__phello__', ispkg=True)
-        pkgdir = os.path.dirname(filename)
-        check = {'__name__': '__phello__',
-                 '__package__': '__phello__',
-                 '__path__': [pkgdir],
-                 '__loader__': self.machinery.FrozenImporter,
-                 '__file__': filename,
-                 }
-        for attr, value in check.items():
-            attr_value = getattr(module, attr, None)
-            self.assertEqual(attr_value, value,
-                             "for __phello__.%s, %r != %r" %
-                             (attr, attr_value, value))
-        self.assertEqual(stdout.getvalue(), 'Hello world!\n')
-
-    def test_lacking_parent(self):
-        with util.uncache('__phello__'):
-            module, stdout = self.load_module('__phello__.spam')
-        filename = resolve_stdlib_file('__phello__.spam')
-        check = {'__name__': '__phello__.spam',
-                '__package__': '__phello__',
-                '__loader__': self.machinery.FrozenImporter,
-                '__file__': filename,
-                }
-        for attr, value in check.items():
-            attr_value = getattr(module, attr)
-            self.assertEqual(attr_value, value,
-                             "for __phello__.spam.%s, %r != %r" %
-                             (attr, attr_value, value))
-        self.assertEqual(stdout.getvalue(), 'Hello world!\n')
-
-    def test_module_reuse(self):
-        with fresh('__hello__', oldapi=True):
-            module1 = self.machinery.FrozenImporter.load_module('__hello__')
-            module2 = self.machinery.FrozenImporter.load_module('__hello__')
-        with captured_stdout() as stdout:
-            module1.main()
-            module2.main()
-        self.assertIs(module1, module2)
-        self.assertEqual(stdout.getvalue(),
-                         'Hello world!\nHello world!\n')
-
-    # No way to trigger an error in a frozen module.
-    test_state_after_failure = None
-
-    def test_unloadable(self):
-        with import_helper.frozen_modules():
-            with deprecated():
-                assert self.machinery.FrozenImporter.find_module('_not_real') is None
-            with self.assertRaises(ImportError) as cm:
-                self.load_module('_not_real')
-            self.assertEqual(cm.exception.name, '_not_real')
-
-
-(Frozen_LoaderTests,
- Source_LoaderTests
- ) = util.test_both(LoaderTests, machinery=machinery)
-
-
 class InspectLoaderTests:
 
     """Tests for the InspectLoader methods for FrozenImporter."""
diff --git a/Lib/test/test_importlib/import_/test___loader__.py b/Lib/test/test_importlib/import_/test___loader__.py
index eaf665a6f5b5..a14163919af6 100644
--- a/Lib/test/test_importlib/import_/test___loader__.py
+++ b/Lib/test/test_importlib/import_/test___loader__.py
@@ -33,48 +33,5 @@ def test___loader__(self):
  ) = util.test_both(SpecLoaderAttributeTests, __import__=util.__import__)
 
 
-class LoaderMock:
-
-    def find_module(self, fullname, path=None):
-        return self
-
-    def load_module(self, fullname):
-        sys.modules[fullname] = self.module
-        return self.module
-
-
-class LoaderAttributeTests:
-
-    def test___loader___missing(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            module = types.ModuleType('blah')
-            try:
-                del module.__loader__
-            except AttributeError:
-                pass
-            loader = LoaderMock()
-            loader.module = module
-            with util.uncache('blah'), util.import_state(meta_path=[loader]):
-                module = self.__import__('blah')
-            self.assertEqual(loader, module.__loader__)
-
-    def test___loader___is_None(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            module = types.ModuleType('blah')
-            module.__loader__ = None
-            loader = LoaderMock()
-            loader.module = module
-            with util.uncache('blah'), util.import_state(meta_path=[loader]):
-                returned_module = self.__import__('blah')
-            self.assertEqual(loader, module.__loader__)
-
-
-(Frozen_Tests,
- Source_Tests
- ) = util.test_both(LoaderAttributeTests, __import__=util.__import__)
-
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/test/test_importlib/import_/test___package__.py b/Lib/test/test_importlib/import_/test___package__.py
index ab1b35ee3c1a..7130c99a6fc1 100644
--- a/Lib/test/test_importlib/import_/test___package__.py
+++ b/Lib/test/test_importlib/import_/test___package__.py
@@ -95,25 +95,6 @@ def __init__(self, parent):
         self.parent = parent
 
 
-class Using__package__PEP302(Using__package__):
-    mock_modules = util.mock_modules
-
-    def test_using___package__(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            super().test_using___package__()
-
-    def test_spec_fallback(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            super().test_spec_fallback()
-
-
-(Frozen_UsingPackagePEP302,
- Source_UsingPackagePEP302
- ) = util.test_both(Using__package__PEP302, __import__=util.__import__)
-
-
 class Using__package__PEP451(Using__package__):
     mock_modules = util.mock_spec
 
@@ -162,23 +143,6 @@ def test_submodule(self):
                 module = getattr(pkg, 'mod')
                 self.assertEqual(module.__package__, 'pkg')
 
-class Setting__package__PEP302(Setting__package__, unittest.TestCase):
-    mock_modules = util.mock_modules
-
-    def test_top_level(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            super().test_top_level()
-
-    def test_package(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            super().test_package()
-
-    def test_submodule(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            super().test_submodule()
 
 class Setting__package__PEP451(Setting__package__, unittest.TestCase):
     mock_modules = util.mock_spec
diff --git a/Lib/test/test_importlib/import_/test_api.py b/Lib/test/test_importlib/import_/test_api.py
index 0ee032b0206d..d6ad590b3d46 100644
--- a/Lib/test/test_importlib/import_/test_api.py
+++ b/Lib/test/test_importlib/import_/test_api.py
@@ -28,11 +28,6 @@ def exec_module(module):
 
 
 class BadLoaderFinder:
-    @classmethod
-    def find_module(cls, fullname, path):
-        if fullname == SUBMOD_NAME:
-            return cls
-
     @classmethod
     def load_module(cls, fullname):
         if fullname == SUBMOD_NAME:
diff --git a/Lib/test/test_importlib/import_/test_caching.py b/Lib/test/test_importlib/import_/test_caching.py
index 3ca765fb4ada..aedf0fd4f9db 100644
--- a/Lib/test/test_importlib/import_/test_caching.py
+++ b/Lib/test/test_importlib/import_/test_caching.py
@@ -52,12 +52,11 @@ class ImportlibUseCache(UseCache, unittest.TestCase):
     __import__ = util.__import__['Source']
 
     def create_mock(self, *names, return_=None):
-        mock = util.mock_modules(*names)
-        original_load = mock.load_module
-        def load_module(self, fullname):
-            original_load(fullname)
-            return return_
-        mock.load_module = MethodType(load_module, mock)
+        mock = util.mock_spec(*names)
+        original_spec = mock.find_spec
+        def find_spec(self, fullname, path, target=None):
+            return original_spec(fullname)
+        mock.find_spec = MethodType(find_spec, mock)
         return mock
 
     # __import__ inconsistent between loaders and built-in import when it comes
@@ -86,14 +85,12 @@ def test_using_cache_for_assigning_to_attribute(self):
     # See test_using_cache_after_loader() for reasoning.
     def test_using_cache_for_fromlist(self):
         # [from cache for fromlist]
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", ImportWarning)
-            with self.create_mock('pkg.__init__', 'pkg.module') as importer:
-                with util.import_state(meta_path=[importer]):
-                    module = self.__import__('pkg', fromlist=['module'])
-                    self.assertTrue(hasattr(module, 'module'))
-                    self.assertEqual(id(module.module),
-                                    id(sys.modules['pkg.module']))
+        with self.create_mock('pkg.__init__', 'pkg.module') as importer:
+            with util.import_state(meta_path=[importer]):
+                module = self.__import__('pkg', fromlist=['module'])
+                self.assertTrue(hasattr(module, 'module'))
+                self.assertEqual(id(module.module),
+                                 id(sys.modules['pkg.module']))
 
 
 if __name__ == '__main__':
diff --git a/Lib/test/test_importlib/import_/test_meta_path.py b/Lib/test/test_importlib/import_/test_meta_path.py
index c8b898ec2378..8689017ba431 100644
--- a/Lib/test/test_importlib/import_/test_meta_path.py
+++ b/Lib/test/test_importlib/import_/test_meta_path.py
@@ -113,16 +113,6 @@ def test_with_path(self):
             super().test_no_path()
 
 
-class CallSignaturePEP302(CallSignoreSuppressImportWarning):
-    mock_modules = util.mock_modules
-    finder_name = 'find_module'
-
-
-(Frozen_CallSignaturePEP302,
- Source_CallSignaturePEP302
- ) = util.test_both(CallSignaturePEP302, __import__=util.__import__)
-
-
 class CallSignaturePEP451(CallSignature):
     mock_modules = util.mock_spec
     finder_name = 'find_spec'
diff --git a/Lib/test/test_importlib/import_/test_path.py b/Lib/test/test_importlib/import_/test_path.py
index de620842bbc5..89b52fbd1e1a 100644
--- a/Lib/test/test_importlib/import_/test_path.py
+++ b/Lib/test/test_importlib/import_/test_path.py
@@ -116,46 +116,6 @@ def test_None_on_sys_path(self):
             if email is not missing:
                 sys.modules['email'] = email
 
-    def test_finder_with_find_module(self):
-        class TestFinder:
-            def find_module(self, fullname):
-                return self.to_return
-        failing_finder = TestFinder()
-        failing_finder.to_return = None
-        path = 'testing path'
-        with util.import_state(path_importer_cache={path: failing_finder}):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", ImportWarning)
-                self.assertIsNone(
-                    self.machinery.PathFinder.find_spec('whatever', [path]))
-        success_finder = TestFinder()
-        success_finder.to_return = __loader__
-        with util.import_state(path_importer_cache={path: success_finder}):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", ImportWarning)
-                spec = self.machinery.PathFinder.find_spec('whatever', [path])
-        self.assertEqual(spec.loader, __loader__)
-
-    def test_finder_with_find_loader(self):
-        class TestFinder:
-            loader = None
-            portions = []
-            def find_loader(self, fullname):
-                return self.loader, self.portions
-        path = 'testing path'
-        with util.import_state(path_importer_cache={path: TestFinder()}):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", ImportWarning)
-                self.assertIsNone(
-                    self.machinery.PathFinder.find_spec('whatever', [path]))
-        success_finder = TestFinder()
-        success_finder.loader = __loader__
-        with util.import_state(path_importer_cache={path: success_finder}):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", ImportWarning)
-                spec = self.machinery.PathFinder.find_spec('whatever', [path])
-        self.assertEqual(spec.loader, __loader__)
-
     def test_finder_with_find_spec(self):
         class TestFinder:
             spec = None
@@ -228,9 +188,9 @@ def invalidate_caches(self):
 
 class FindModuleTests(FinderTests):
     def find(self, *args, **kwargs):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            return self.machinery.PathFinder.find_module(*args, **kwargs)
+        spec = self.machinery.PathFinder.find_spec(*args, **kwargs)
+        return None if spec is None else spec.loader
+
     def check_found(self, found, importer):
         self.assertIs(found, importer)
 
@@ -255,16 +215,14 @@ def check_found(self, found, importer):
 class PathEntryFinderTests:
 
     def test_finder_with_failing_find_spec(self):
-        # PathEntryFinder with find_module() defined should work.
-        # Issue #20763.
         class Finder:
-            path_location = 'test_finder_with_find_module'
+            path_location = 'test_finder_with_find_spec'
             def __init__(self, path):
                 if path != self.path_location:
                     raise ImportError
 
             @staticmethod
-            def find_module(fullname):
+            def find_spec(fullname, target=None):
                 return None
 
 
@@ -274,27 +232,6 @@ def find_module(fullname):
                 warnings.simplefilter("ignore", ImportWarning)
                 self.machinery.PathFinder.find_spec('importlib')
 
-    def test_finder_with_failing_find_module(self):
-        # PathEntryFinder with find_module() defined should work.
-        # Issue #20763.
-        class Finder:
-            path_location = 'test_finder_with_find_module'
-            def __init__(self, path):
-                if path != self.path_location:
-                    raise ImportError
-
-            @staticmethod
-            def find_module(fullname):
-                return None
-
-
-        with util.import_state(path=[Finder.path_location]+sys.path[:],
-                               path_hooks=[Finder]):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", ImportWarning)
-                warnings.simplefilter("ignore", DeprecationWarning)
-                self.machinery.PathFinder.find_module('importlib')
-
 
 (Frozen_PEFTests,
  Source_PEFTests
diff --git a/Lib/test/test_importlib/source/test_case_sensitivity.py b/Lib/test/test_importlib/source/test_case_sensitivity.py
index 9d472707abe8..6a06313319db 100644
--- a/Lib/test/test_importlib/source/test_case_sensitivity.py
+++ b/Lib/test/test_importlib/source/test_case_sensitivity.py
@@ -63,19 +63,6 @@ def test_insensitive(self):
             self.assertIn(self.name, insensitive.get_filename(self.name))
 
 
-class CaseSensitivityTestPEP302(CaseSensitivityTest):
-    def find(self, finder):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            return finder.find_module(self.name)
-
-
-(Frozen_CaseSensitivityTestPEP302,
- Source_CaseSensitivityTestPEP302
- ) = util.test_both(CaseSensitivityTestPEP302, importlib=importlib,
-                    machinery=machinery)
-
-
 class CaseSensitivityTestPEP451(CaseSensitivityTest):
     def find(self, finder):
         found = finder.find_spec(self.name)
diff --git a/Lib/test/test_importlib/source/test_finder.py b/Lib/test/test_importlib/source/test_finder.py
index bed9d56dca84..12db7c7d352a 100644
--- a/Lib/test/test_importlib/source/test_finder.py
+++ b/Lib/test/test_importlib/source/test_finder.py
@@ -120,7 +120,7 @@ def test_package_over_module(self):
     def test_failure(self):
         with util.create_modules('blah') as mapping:
             nothing = self.import_(mapping['.root'], 'sdfsadsadf')
-            self.assertIsNone(nothing)
+            self.assertEqual(nothing, self.NOT_FOUND)
 
     def test_empty_string_for_dir(self):
         # The empty string from sys.path means to search in the cwd.
@@ -150,7 +150,7 @@ def test_dir_removal_handling(self):
             found = self._find(finder, 'mod', loader_only=True)
             self.assertIsNotNone(found)
         found = self._find(finder, 'mod', loader_only=True)
-        self.assertIsNone(found)
+        self.assertEqual(found, self.NOT_FOUND)
 
     @unittest.skipUnless(sys.platform != 'win32',
             'os.chmod() does not support the needed arguments under Windows')
@@ -196,10 +196,12 @@ class FinderTestsPEP420(FinderTests):
     NOT_FOUND = (None, [])
 
     def _find(self, finder, name, loader_only=False):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            loader_portions = finder.find_loader(name)
-            return loader_portions[0] if loader_only else loader_portions
+        spec = finder.find_spec(name)
+        if spec is None:
+            return self.NOT_FOUND
+        if loader_only:
+            return spec.loader
+        return spec.loader, spec.submodule_search_locations
 
 
 (Frozen_FinderTestsPEP420,
@@ -207,20 +209,5 @@ def _find(self, finder, name, loader_only=False):
  ) = util.test_both(FinderTestsPEP420, machinery=machinery)
 
 
-class FinderTestsPEP302(FinderTests):
-
-    NOT_FOUND = None
-
-    def _find(self, finder, name, loader_only=False):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            return finder.find_module(name)
-
-
-(Frozen_FinderTestsPEP302,
- Source_FinderTestsPEP302
- ) = util.test_both(FinderTestsPEP302, machinery=machinery)
-
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/test/test_importlib/source/test_path_hook.py b/Lib/test/test_importlib/source/test_path_hook.py
index ead62f5e945e..f274330e0b33 100644
--- a/Lib/test/test_importlib/source/test_path_hook.py
+++ b/Lib/test/test_importlib/source/test_path_hook.py
@@ -18,19 +18,10 @@ def test_success(self):
             self.assertTrue(hasattr(self.path_hook()(mapping['.root']),
                                     'find_spec'))
 
-    def test_success_legacy(self):
-        with util.create_modules('dummy') as mapping:
-            self.assertTrue(hasattr(self.path_hook()(mapping['.root']),
-                                    'find_module'))
-
     def test_empty_string(self):
         # The empty string represents the cwd.
         self.assertTrue(hasattr(self.path_hook()(''), 'find_spec'))
 
-    def test_empty_string_legacy(self):
-        # The empty string represents the cwd.
-        self.assertTrue(hasattr(self.path_hook()(''), 'find_module'))
-
 
 (Frozen_PathHookTest,
  Source_PathHooktest
diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py
index 3c9149c4e45a..603125f6d926 100644
--- a/Lib/test/test_importlib/test_abc.py
+++ b/Lib/test/test_importlib/test_abc.py
@@ -147,20 +147,13 @@ def ins(self):
 
 class MetaPathFinder:
 
-    def find_module(self, fullname, path):
-        return super().find_module(fullname, path)
+    pass
 
 
 class MetaPathFinderDefaultsTests(ABCTestHarness):
 
     SPLIT = make_abc_subclasses(MetaPathFinder)
 
-    def test_find_module(self):
-        # Default should return None.
-        with self.assertWarns(DeprecationWarning):
-            found = self.ins.find_module('something', None)
-        self.assertIsNone(found)
-
     def test_invalidate_caches(self):
         # Calling the method is a no-op.
         self.ins.invalidate_caches()
@@ -173,22 +166,13 @@ def test_invalidate_caches(self):
 
 class PathEntryFinder:
 
-    def find_loader(self, fullname):
-        return super().find_loader(fullname)
+    pass
 
 
 class PathEntryFinderDefaultsTests(ABCTestHarness):
 
     SPLIT = make_abc_subclasses(PathEntryFinder)
 
-    def test_find_loader(self):
-        with self.assertWarns(DeprecationWarning):
-            found = self.ins.find_loader('something')
-        self.assertEqual(found, (None, []))
-
-    def find_module(self):
-        self.assertEqual(None, self.ins.find_module('something'))
-
     def test_invalidate_caches(self):
         # Should be a no-op.
         self.ins.invalidate_caches()
@@ -201,8 +185,7 @@ def test_invalidate_caches(self):
 
 class Loader:
 
-    def load_module(self, fullname):
-        return super().load_module(fullname)
+    pass
 
 
 class LoaderDefaultsTests(ABCTestHarness):
@@ -333,14 +316,6 @@ def find_spec(self, fullname, path, target=None):
 
         return MetaPathSpecFinder()
 
-    def test_find_module(self):
-        finder = self.finder(None)
-        path = ['a', 'b', 'c']
-        name = 'blah'
-        with self.assertWarns(DeprecationWarning):
-            found = finder.find_module(name, path)
-        self.assertIsNone(found)
-
     def test_find_spec_with_explicit_target(self):
         loader = object()
         spec = self.util.spec_from_loader('blah', loader)
@@ -370,53 +345,6 @@ def test_spec(self):
  ) = test_util.test_both(MetaPathFinderFindModuleTests, abc=abc, util=util)
 
 
-##### PathEntryFinder concrete methods #########################################
-class PathEntryFinderFindLoaderTests:
-
-    @classmethod
-    def finder(cls, spec):
-        class PathEntrySpecFinder(cls.abc.PathEntryFinder):
-
-            def find_spec(self, fullname, target=None):
-                self.called_for = fullname
-                return spec
-
-        return PathEntrySpecFinder()
-
-    def test_no_spec(self):
-        finder = self.finder(None)
-        name = 'blah'
-        with self.assertWarns(DeprecationWarning):
-            found = finder.find_loader(name)
-        self.assertIsNone(found[0])
-        self.assertEqual([], found[1])
-        self.assertEqual(name, finder.called_for)
-
-    def test_spec_with_loader(self):
-        loader = object()
-        spec = self.util.spec_from_loader('blah', loader)
-        finder = self.finder(spec)
-        with self.assertWarns(DeprecationWarning):
-            found = finder.find_loader('blah')
-        self.assertIs(found[0], spec.loader)
-
-    def test_spec_with_portions(self):
-        spec = self.machinery.ModuleSpec('blah', None)
-        paths = ['a', 'b', 'c']
-        spec.submodule_search_locations = paths
-        finder = self.finder(spec)
-        with self.assertWarns(DeprecationWarning):
-            found = finder.find_loader('blah')
-        self.assertIsNone(found[0])
-        self.assertEqual(paths, found[1])
-
-
-(Frozen_PEFFindLoaderTests,
- Source_PEFFindLoaderTests
- ) = test_util.test_both(PathEntryFinderFindLoaderTests, abc=abc, util=util,
-                         machinery=machinery)
-
-
 ##### Loader concrete methods ##################################################
 class LoaderLoadModuleTests:
 
diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py
index b3a99dc2dd57..ecf2c47c462e 100644
--- a/Lib/test/test_importlib/test_api.py
+++ b/Lib/test/test_importlib/test_api.py
@@ -95,7 +95,8 @@ def load_b():
 
 (Frozen_ImportModuleTests,
  Source_ImportModuleTests
- ) = test_util.test_both(ImportModuleTests, init=init)
+ ) = test_util.test_both(
+     ImportModuleTests, init=init, util=util, machinery=machinery)
 
 
 class FindLoaderTests:
@@ -103,29 +104,26 @@ class FindLoaderTests:
     FakeMetaFinder = None
 
     def test_sys_modules(self):
-        # If a module with __loader__ is in sys.modules, then return it.
+        # If a module with __spec__.loader is in sys.modules, then return it.
         name = 'some_mod'
         with test_util.uncache(name):
             module = types.ModuleType(name)
             loader = 'a loader!'
-            module.__loader__ = loader
+            module.__spec__ = self.machinery.ModuleSpec(name, loader)
             sys.modules[name] = module
-            with warnings.catch_warnings():
-                warnings.simplefilter('ignore', DeprecationWarning)
-                found = self.init.find_loader(name)
-            self.assertEqual(loader, found)
+            spec = self.util.find_spec(name)
+            self.assertIsNotNone(spec)
+            self.assertEqual(spec.loader, loader)
 
     def test_sys_modules_loader_is_None(self):
-        # If sys.modules[name].__loader__ is None, raise ValueError.
+        # If sys.modules[name].__spec__.loader is None, raise ValueError.
         name = 'some_mod'
         with test_util.uncache(name):
             module = types.ModuleType(name)
             module.__loader__ = None
             sys.modules[name] = module
             with self.assertRaises(ValueError):
-                with warnings.catch_warnings():
-                    warnings.simplefilter('ignore', DeprecationWarning)
-                    self.init.find_loader(name)
+                self.util.find_spec(name)
 
     def test_sys_modules_loader_is_not_set(self):
         # Should raise ValueError
@@ -134,24 +132,20 @@ def test_sys_modules_loader_is_not_set(self):
         with test_util.uncache(name):
             module = types.ModuleType(name)
             try:
-                del module.__loader__
+                del module.__spec__.loader
             except AttributeError:
                 pass
             sys.modules[name] = module
             with self.assertRaises(ValueError):
-                with warnings.catch_warnings():
-                    warnings.simplefilter('ignore', DeprecationWarning)
-                    self.init.find_loader(name)
+                self.util.find_spec(name)
 
     def test_success(self):
         # Return the loader found on sys.meta_path.
         name = 'some_mod'
         with test_util.uncache(name):
             with test_util.import_state(meta_path=[self.FakeMetaFinder]):
-                with warnings.catch_warnings():
-                    warnings.simplefilter('ignore', DeprecationWarning)
-                    warnings.simplefilter('ignore', ImportWarning)
-                    self.assertEqual((name, None), self.init.find_loader(name))
+                spec = self.util.find_spec(name)
+                self.assertEqual((name, (name, None)), (spec.name, spec.loader))
 
     def test_success_path(self):
         # Searching on a path should work.
@@ -159,17 +153,12 @@ def test_success_path(self):
         path = 'path to some place'
         with test_util.uncache(name):
             with test_util.import_state(meta_path=[self.FakeMetaFinder]):
-                with warnings.catch_warnings():
-                    warnings.simplefilter('ignore', DeprecationWarning)
-                    warnings.simplefilter('ignore', ImportWarning)
-                    self.assertEqual((name, path),
-                                     self.init.find_loader(name, path))
+                spec = self.util.find_spec(name, path)
+                self.assertEqual(name, spec.name)
 
     def test_nothing(self):
         # None is returned upon failure to find a loader.
-        with warnings.catch_warnings():
-            warnings.simplefilter('ignore', DeprecationWarning)
-            self.assertIsNone(self.init.find_loader('nevergoingtofindthismodule'))
+        self.assertIsNone(self.util.find_spec('nevergoingtofindthismodule'))
 
 
 class FindLoaderPEP451Tests(FindLoaderTests):
@@ -182,20 +171,8 @@ def find_spec(name, path=None, target=None):
 
 (Frozen_FindLoaderPEP451Tests,
  Source_FindLoaderPEP451Tests
- ) = test_util.test_both(FindLoaderPEP451Tests, init=init)
-
-
-class FindLoaderPEP302Tests(FindLoaderTests):
-
-    class FakeMetaFinder:
-        @staticmethod
-        def find_module(name, path=None):
-            return name, path
-
-
-(Frozen_FindLoaderPEP302Tests,
- Source_FindLoaderPEP302Tests
- ) = test_util.test_both(FindLoaderPEP302Tests, init=init)
+ ) = test_util.test_both(
+     FindLoaderPEP451Tests, init=init, util=util, machinery=machinery)
 
 
 class ReloadTests:
@@ -380,7 +357,8 @@ def test_module_missing_spec(self):
 
 (Frozen_ReloadTests,
  Source_ReloadTests
- ) = test_util.test_both(ReloadTests, init=init, util=util)
+ ) = test_util.test_both(
+     ReloadTests, init=init, util=util, machinery=machinery)
 
 
 class InvalidateCacheTests:
@@ -390,8 +368,6 @@ def test_method_called(self):
         class InvalidatingNullFinder:
             def __init__(self, *ignored):
                 self.called = False
-            def find_module(self, *args):
-                return None
             def invalidate_caches(self):
                 self.called = True
 
@@ -416,7 +392,8 @@ def test_method_lacking(self):
 
 (Frozen_InvalidateCacheTests,
  Source_InvalidateCacheTests
- ) = test_util.test_both(InvalidateCacheTests, init=init)
+ ) = test_util.test_both(
+     InvalidateCacheTests, init=init, util=util, machinery=machinery)
 
 
 class FrozenImportlibTests(unittest.TestCase):
diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py
index b7dfe865a03a..40b8aa1787fe 100644
--- a/Lib/test/test_importlib/test_windows.py
+++ b/Lib/test/test_importlib/test_windows.py
@@ -92,30 +92,16 @@ class WindowsRegistryFinderTests:
 
     def test_find_spec_missing(self):
         spec = self.machinery.WindowsRegistryFinder.find_spec('spam')
-        self.assertIs(spec, None)
-
-    def test_find_module_missing(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", DeprecationWarning)
-            loader = self.machinery.WindowsRegistryFinder.find_module('spam')
-        self.assertIs(loader, None)
+        self.assertIsNone(spec)
 
     def test_module_found(self):
         with setup_module(self.machinery, self.test_module):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", DeprecationWarning)
-                loader = self.machinery.WindowsRegistryFinder.find_module(self.test_module)
             spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module)
-            self.assertIsNot(loader, None)
-            self.assertIsNot(spec, None)
+            self.assertIsNotNone(spec)
 
     def test_module_not_found(self):
         with setup_module(self.machinery, self.test_module, path="."):
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore", DeprecationWarning)
-                loader = self.machinery.WindowsRegistryFinder.find_module(self.test_module)
             spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module)
-            self.assertIsNone(loader)
             self.assertIsNone(spec)
 
 (Frozen_WindowsRegistryFinderTests,
diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py
index e348733f6ce3..c25be096e528 100644
--- a/Lib/test/test_importlib/util.py
+++ b/Lib/test/test_importlib/util.py
@@ -194,8 +194,7 @@ def import_state(**kwargs):
                 new_value = default
             setattr(sys, attr, new_value)
         if len(kwargs):
-            raise ValueError(
-                    'unrecognized arguments: {0}'.format(kwargs.keys()))
+            raise ValueError('unrecognized arguments: {}'.format(kwargs))
         yield
     finally:
         for attr, value in originals.items():
@@ -243,30 +242,6 @@ def __exit__(self, *exc_info):
         self._uncache.__exit__(None, None, None)
 
 
-class mock_modules(_ImporterMock):
-
-    """Importer mock using PEP 302 APIs."""
-
-    def find_module(self, fullname, path=None):
-        if fullname not in self.modules:
-            return None
-        else:
-            return self
-
-    def load_module(self, fullname):
-        if fullname not in self.modules:
-            raise ImportError
-        else:
-            sys.modules[fullname] = self.modules[fullname]
-            if fullname in self.module_code:
-                try:
-                    self.module_code[fullname]()
-                except Exception:
-                    del sys.modules[fullname]
-                    raise
-            return self.modules[fullname]
-
-
 class mock_spec(_ImporterMock):
 
     """Importer mock using PEP 451 APIs."""
diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py
index 4d9f5db3c6b3..902627088fc2 100644
--- a/Lib/test/test_pkgutil.py
+++ b/Lib/test/test_pkgutil.py
@@ -429,7 +429,7 @@ def test_iter_importers(self):
             importers = list(iter_importers(fullname))
             expected_importer = get_importer(pathitem)
             for finder in importers:
-                spec = pkgutil._get_spec(finder, fullname)
+                spec = finder.find_spec(fullname)
                 loader = spec.loader
                 try:
                     loader = loader.loader
@@ -441,7 +441,7 @@ def test_iter_importers(self):
                 self.assertEqual(finder, expected_importer)
                 self.assertIsInstance(loader,
                                       importlib.machinery.SourceFileLoader)
-                self.assertIsNone(pkgutil._get_spec(finder, pkgname))
+                self.assertIsNone(finder.find_spec(pkgname))
 
             with self.assertRaises(ImportError):
                 list(iter_importers('invalid.module'))
@@ -535,12 +535,6 @@ class ImportlibMigrationTests(unittest.TestCase):
     # PEP 302 emulation in this module is in the process of being
     # deprecated in favour of importlib proper
 
-    def check_deprecated(self):
-        return check_warnings(
-            ("This emulation is deprecated and slated for removal in "
-             "Python 3.12; use 'importlib' instead",
-             DeprecationWarning))
-
     def test_get_loader_avoids_emulation(self):
         with check_warnings() as w:
             self.assertIsNotNone(pkgutil.get_loader("sys"))
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
index 52d43bdead67..14c19719e260 100644
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -836,7 +836,6 @@ def _testBogusZipFile(self):
             self.assertRaises(TypeError, z.get_source, None)
 
             error = zipimport.ZipImportError
-            self.assertIsNone(z.find_module('abc'))
             self.assertIsNone(z.find_spec('abc'))
 
             with warnings.catch_warnings():
diff --git a/Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst b/Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst
new file mode 100644
index 000000000000..ac1854068441
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst
@@ -0,0 +1,2 @@
+Remove more deprecated importlib APIs: ``find_loader()``, ``find_module()``,
+``importlib.abc.Finder``, ``pkgutil.ImpImporter``, ``pkgutil.ImpLoader``.



More information about the Python-checkins mailing list