Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 17 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions Doc/library/pkgutil.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,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)

Expand All @@ -83,27 +64,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.
Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ pathlib
:meth:`~pathlib.PurePath.is_relative_to`. In previous versions, any such
arguments are joined onto *other*.

pkgutil
-------

* Remove :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
___

Expand Down
55 changes: 1 addition & 54 deletions Lib/pkgutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
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',
Expand Down Expand Up @@ -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.

Expand Down
5 changes: 3 additions & 2 deletions Lib/test/test_doctest/test_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2407,10 +2407,11 @@ def test_DocFileSuite():
Support for using a package's __loader__.get_data() is also
provided.

>>> import unittest, pkgutil, test
>>> import importlib.util, unittest, test
picnixz marked this conversation as resolved.
Show resolved Hide resolved
>>> added_loader = False
>>> if not hasattr(test, '__loader__'):
... test.__loader__ = pkgutil.get_loader(test)
... spec = importlib.util.find_spec(test.__name__)
... test.__loader__ = spec.loader
... added_loader = True
>>> try:
... suite = doctest.DocFileSuite('test_doctest.txt',
Expand Down
61 changes: 0 additions & 61 deletions Lib/test/test_pkgutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,67 +571,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):
sys.modules[name] = mod
loader = pkgutil.get_loader(name)
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):
sys.modules[name] = mod
loader = pkgutil.get_loader(name)
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:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove :func:`!pkgutil.get_loader` and :func:`!pkgutil.find_loader`.
picnixz marked this conversation as resolved.
Show resolved Hide resolved
Loading