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: Deprecate find_loader and get_loader in pkgutil #98520

Merged
merged 14 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ Deprecated
:exc:`ImportWarning`).
(Contributed by Brett Cannon in :gh:`65961`.)

* :func:`pkgutil.find_module` and :func:`pkgutil.get_module`
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
now raise :exc:`DeprecationWarning`,
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
use :func:`importlib.util.find_spec` instead.
sobolevn marked this conversation as resolved.
Show resolved Hide resolved


Pending Removal in Python 3.13
------------------------------
Expand Down
8 changes: 8 additions & 0 deletions Lib/pkgutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,10 @@ def get_loader(module_or_name):
If the named module is not already imported, its containing package
(if any) is imported, in order to establish the package __path__.
"""
warnings.warn("`pkgutil.get_loader` is deprecated since Python 3.12; "
"this function is slated for removal in Python 3.14, "
"use `importlib.util.find_spec` instead",
DeprecationWarning)
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
if module_or_name in sys.modules:
module_or_name = sys.modules[module_or_name]
if module_or_name is None:
Expand All @@ -489,6 +493,10 @@ def find_loader(fullname):
importlib.util.find_spec that converts most failures to ImportError
and only returns the loader rather than the full spec
"""
warnings.warn("`pkgutil.find_loader` is deprecated since Python 3.12; "
"this function is slated for removal in Python 3.14, "
"use `importlib.util.find_spec` instead",
DeprecationWarning)
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
if fullname.startswith('.'):
msg = "Relative module name {!r} not supported".format(fullname)
raise ImportError(msg)
Expand Down
37 changes: 23 additions & 14 deletions Lib/test/test_pkgutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os.path
import tempfile
import shutil
import warnings
import zipfile

# Note: pkgutil.walk_packages is currently tested in test_runpy. This is
Expand Down Expand Up @@ -549,22 +550,26 @@ def test_loader_deprecated(self):
with self.check_deprecated():
pkgutil.ImpLoader("", "", "", "")

def test_get_loader_avoids_emulation(self):
with check_warnings() as w:
self.assertIsNotNone(pkgutil.get_loader("sys"))
self.assertIsNotNone(pkgutil.get_loader("os"))
self.assertIsNotNone(pkgutil.get_loader("test.support"))
self.assertEqual(len(w.warnings), 0)
def test_get_loader_is_deprecated(self):
for module in ["sys", "os", "test.support"]:
with check_warnings((
"`pkgutil.get_loader` is deprecated since Python 3.12; "
"this function is slated for removal in Python 3.14, "
"use `importlib.util.find_spec` instead",
DeprecationWarning,
)):
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
res = pkgutil.get_loader(module)
self.assertIsNotNone(res)

@unittest.skipIf(__name__ == '__main__', 'not compatible with __main__')
def test_get_loader_handles_missing_loader_attribute(self):
global __loader__
this_loader = __loader__
del __loader__
try:
with check_warnings() as w:
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
self.assertIsNotNone(pkgutil.get_loader(__name__))
self.assertEqual(len(w.warnings), 0)
finally:
__loader__ = this_loader

Expand Down Expand Up @@ -600,12 +605,16 @@ def test_find_loader_missing_module(self):
loader = pkgutil.find_loader(name)
self.assertIsNone(loader)

def test_find_loader_avoids_emulation(self):
with check_warnings() as w:
self.assertIsNotNone(pkgutil.find_loader("sys"))
self.assertIsNotNone(pkgutil.find_loader("os"))
self.assertIsNotNone(pkgutil.find_loader("test.support"))
self.assertEqual(len(w.warnings), 0)
def test_find_loader_is_deprecated(self):
for module in ["sys", "os", "test.support"]:
with check_warnings((
"`pkgutil.find_loader` is deprecated since Python 3.12; "
"this function is slated for removal in Python 3.14, "
"use `importlib.util.find_spec` instead",
DeprecationWarning,
sobolevn marked this conversation as resolved.
Show resolved Hide resolved
)):
res = pkgutil.find_loader(module)
self.assertIsNotNone(res)

def test_get_importer_avoids_emulation(self):
# We use an illegal path so *none* of the path hooks should fire
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecate :func:`pkgutil.find_module` and :func:`pkgutil.get_module`.
sobolevn marked this conversation as resolved.
Show resolved Hide resolved