gh-97850: remove `find_loader and get_loader from pkgutil` (#119656)

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Brett Cannon <brett@python.org>
This commit is contained in:
Bénédikt Tran 2024-11-01 17:35:22 +01:00 committed by GitHub
parent 38a604fd90
commit 464a7a91d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 12 additions and 183 deletions

View File

@ -85,7 +85,7 @@ Pending removal in Python 3.14
:meth:`~pathlib.PurePath.relative_to`: passing additional arguments is
deprecated.
* :mod:`pkgutil`: :func:`~pkgutil.find_loader` and :func:`~pkgutil.get_loader`
* :mod:`pkgutil`: :func:`!pkgutil.find_loader` and :func:!pkgutil.get_loader`
now raise :exc:`DeprecationWarning`;
use :func:`importlib.util.find_spec` instead.
(Contributed by Nikita Sobolev in :gh:`97850`.)

View File

@ -49,25 +49,6 @@ support.
this function to raise an exception (in line with :func:`os.path.isdir`
behavior).
.. function:: find_loader(fullname)
Retrieve a module :term:`loader` for the given *fullname*.
This is a backwards compatibility wrapper around
:func:`importlib.util.find_spec` that converts most failures to
:exc:`ImportError` and only returns the loader rather than the full
:class:`importlib.machinery.ModuleSpec`.
.. versionchanged:: 3.3
Updated to be based directly on :mod:`importlib` rather than relying
on the package internal :pep:`302` import emulation.
.. versionchanged:: 3.4
Updated to be based on :pep:`451`
.. deprecated-removed:: 3.12 3.14
Use :func:`importlib.util.find_spec` instead.
.. function:: get_importer(path_item)
@ -84,27 +65,6 @@ support.
on the package internal :pep:`302` import emulation.
.. function:: get_loader(module_or_name)
Get a :term:`loader` object for *module_or_name*.
If the module or package is accessible via the normal import mechanism, a
wrapper around the relevant part of that machinery is returned. Returns
``None`` if the module cannot be found or imported. If the named module is
not already imported, its containing package (if any) is imported, in order
to establish the package ``__path__``.
.. versionchanged:: 3.3
Updated to be based directly on :mod:`importlib` rather than relying
on the package internal :pep:`302` import emulation.
.. versionchanged:: 3.4
Updated to be based on :pep:`451`
.. deprecated-removed:: 3.12 3.14
Use :func:`importlib.util.find_spec` instead.
.. function:: iter_importers(fullname='')
Yield :term:`finder` objects for the given module name.

View File

@ -1229,7 +1229,7 @@ Deprecated
your code *requires* ``'fork'``. See :ref:`contexts and start methods
<multiprocessing-start-methods>`.
* :mod:`pkgutil`: :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader`
* :mod:`pkgutil`: :func:`!pkgutil.find_loader` and :func:`!pkgutil.get_loader`
are deprecated and will be removed in Python 3.14;
use :func:`importlib.util.find_spec` instead.
(Contributed by Nikita Sobolev in :gh:`97850`.)

View File

@ -621,6 +621,13 @@ pathlib
:meth:`~pathlib.PurePath.is_relative_to`. In previous versions, any such
arguments are joined onto *other*.
pkgutil
-------
* Remove deprecated :func:`!pkgutil.get_loader` and :func:`!pkgutil.find_loader`.
These had previously raised a :exc:`DeprecationWarning` since Python 3.12.
(Contributed by Bénédikt Tran in :gh:`97850`.)
pty
---

View File

@ -12,7 +12,7 @@ from types import ModuleType
import warnings
__all__ = [
'get_importer', 'iter_importers', 'get_loader', 'find_loader',
'get_importer', 'iter_importers',
'walk_packages', 'iter_modules', 'get_data',
'read_code', 'extend_path',
'ModuleInfo',
@ -263,59 +263,6 @@ def iter_importers(fullname=""):
yield get_importer(item)
def get_loader(module_or_name):
"""Get a "loader" object for module_or_name
Returns None if the module cannot be found or imported.
If the named module is not already imported, its containing package
(if any) is imported, in order to establish the package __path__.
"""
warnings._deprecated("pkgutil.get_loader",
f"{warnings._DEPRECATED_MSG}; "
"use importlib.util.find_spec() instead",
remove=(3, 14))
if module_or_name in sys.modules:
module_or_name = sys.modules[module_or_name]
if module_or_name is None:
return None
if isinstance(module_or_name, ModuleType):
module = module_or_name
loader = getattr(module, '__loader__', None)
if loader is not None:
return loader
if getattr(module, '__spec__', None) is None:
return None
fullname = module.__name__
else:
fullname = module_or_name
return find_loader(fullname)
def find_loader(fullname):
"""Find a "loader" object for fullname
This is a backwards compatibility wrapper around
importlib.util.find_spec that converts most failures to ImportError
and only returns the loader rather than the full spec
"""
warnings._deprecated("pkgutil.find_loader",
f"{warnings._DEPRECATED_MSG}; "
"use importlib.util.find_spec() instead",
remove=(3, 14))
if fullname.startswith('.'):
msg = "Relative module name {!r} not supported".format(fullname)
raise ImportError(msg)
try:
spec = importlib.util.find_spec(fullname)
except (ImportError, AttributeError, TypeError, ValueError) as ex:
# This hack fixes an impedance mismatch between pkgutil and
# importlib, where the latter raises other errors for cases where
# pkgutil previously raised ImportError
msg = "Error while finding loader for {!r} ({}: {})"
raise ImportError(msg.format(fullname, type(ex), ex)) from ex
return spec.loader if spec is not None else None
def extend_path(path, name):
"""Extend a package's path.

View File

@ -2410,25 +2410,6 @@ def test_DocFileSuite():
>>> suite.run(unittest.TestResult())
<unittest.result.TestResult run=3 errors=0 failures=2>
Support for using a package's __loader__.get_data() is also
provided.
>>> import unittest, pkgutil, test
>>> added_loader = False
>>> if not hasattr(test, '__loader__'):
... test.__loader__ = pkgutil.get_loader(test)
... added_loader = True
>>> try:
... suite = doctest.DocFileSuite('test_doctest.txt',
... 'test_doctest2.txt',
... 'test_doctest4.txt',
... package='test.test_doctest')
... suite.run(unittest.TestResult())
... finally:
... if added_loader:
... del test.__loader__
<unittest.result.TestResult run=3 errors=0 failures=2>
'/' should be used as a path separator. It will be converted
to a native separator at run time:

View File

@ -607,73 +607,6 @@ class ImportlibMigrationTests(unittest.TestCase):
# PEP 302 emulation in this module is in the process of being
# deprecated in favour of importlib proper
@unittest.skipIf(__name__ == '__main__', 'not compatible with __main__')
@ignore_warnings(category=DeprecationWarning)
def test_get_loader_handles_missing_loader_attribute(self):
global __loader__
this_loader = __loader__
del __loader__
try:
self.assertIsNotNone(pkgutil.get_loader(__name__))
finally:
__loader__ = this_loader
@ignore_warnings(category=DeprecationWarning)
def test_get_loader_handles_missing_spec_attribute(self):
name = 'spam'
mod = type(sys)(name)
del mod.__spec__
with CleanImport(name):
try:
sys.modules[name] = mod
loader = pkgutil.get_loader(name)
finally:
sys.modules.pop(name, None)
self.assertIsNone(loader)
@ignore_warnings(category=DeprecationWarning)
def test_get_loader_handles_spec_attribute_none(self):
name = 'spam'
mod = type(sys)(name)
mod.__spec__ = None
with CleanImport(name):
try:
sys.modules[name] = mod
loader = pkgutil.get_loader(name)
finally:
sys.modules.pop(name, None)
self.assertIsNone(loader)
@ignore_warnings(category=DeprecationWarning)
def test_get_loader_None_in_sys_modules(self):
name = 'totally bogus'
sys.modules[name] = None
try:
loader = pkgutil.get_loader(name)
finally:
del sys.modules[name]
self.assertIsNone(loader)
def test_get_loader_is_deprecated(self):
with check_warnings(
(r".*\bpkgutil.get_loader\b.*", DeprecationWarning),
):
res = pkgutil.get_loader("sys")
self.assertIsNotNone(res)
def test_find_loader_is_deprecated(self):
with check_warnings(
(r".*\bpkgutil.find_loader\b.*", DeprecationWarning),
):
res = pkgutil.find_loader("sys")
self.assertIsNotNone(res)
@ignore_warnings(category=DeprecationWarning)
def test_find_loader_missing_module(self):
name = 'totally bogus'
loader = pkgutil.find_loader(name)
self.assertIsNone(loader)
def test_get_importer_avoids_emulation(self):
# We use an illegal path so *none* of the path hooks should fire
with check_warnings() as w:

View File

@ -1750,7 +1750,7 @@ Remove the long-deprecated ``imp`` module.
.. nonce: N46coo
.. section: Library
Deprecate :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` in
Deprecate :func:`!pkgutil.find_loader` and :func:`!pkgutil.get_loader` in
favor of :func:`importlib.util.find_spec`.
..

View File

@ -0,0 +1 @@
Remove deprecated :func:`!pkgutil.get_loader` and :func:`!pkgutil.find_loader`.