From b7de6dfed08238104025de26e77eaaab1dc8614a Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 21 Oct 2022 16:24:33 +0300 Subject: [PATCH 1/9] gh-97850: Deprecate `find_module` and `get_module` in `pkgutil` --- Doc/whatsnew/3.12.rst | 4 ++ Lib/pkgutil.py | 8 ++++ Lib/test/test_pkgutil.py | 37 ++++++++++++------- ...2-10-21-16-23-31.gh-issue-97850.N46coo.rst | 1 + 4 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 525efc405c8520..50d368fe69db92 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -251,6 +251,10 @@ Deprecated :exc:`ImportWarning`). (Contributed by Brett Cannon in :gh:`65961`.) +* :func:`pkgutil.find_module` and :func:`pkgutil.get_module` + now raise :exc:`DeprecationWarning`, + use :func:`importlib.util.find_spec` instead. + Pending Removal in Python 3.13 ------------------------------ diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index bdebfd2fc8ac32..314c6f5cb9443d 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -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) if module_or_name in sys.modules: module_or_name = sys.modules[module_or_name] if module_or_name is None: @@ -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) if fullname.startswith('.'): msg = "Relative module name {!r} not supported".format(fullname) raise ImportError(msg) diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 0cc99e0cc22763..c75e2d9736732c 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -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 @@ -549,12 +550,16 @@ 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, + )): + 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): @@ -562,9 +567,9 @@ def test_get_loader_handles_missing_loader_attribute(self): this_loader = __loader__ del __loader__ try: - with check_warnings() as w: + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) self.assertIsNotNone(pkgutil.get_loader(__name__)) - self.assertEqual(len(w.warnings), 0) finally: __loader__ = this_loader @@ -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, + )): + 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 diff --git a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst new file mode 100644 index 00000000000000..77d525e1a4a549 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst @@ -0,0 +1 @@ +Deprecate :func:`pkgutil.find_module` and :func:`pkgutil.get_module`. From b1e6d4d8b33e2090c84d9691c76d9efb63d7f817 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 9 Nov 2022 16:22:09 +0300 Subject: [PATCH 2/9] Address review --- Doc/whatsnew/3.12.rst | 3 ++- Lib/pkgutil.py | 16 +++++++------- Lib/test/test_pkgutil.py | 48 ++++++++++++++++++---------------------- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 50d368fe69db92..0b88828d285fe4 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -252,8 +252,9 @@ Deprecated (Contributed by Brett Cannon in :gh:`65961`.) * :func:`pkgutil.find_module` and :func:`pkgutil.get_module` - now raise :exc:`DeprecationWarning`, + now raise :exc:`DeprecationWarning`; use :func:`importlib.util.find_spec` instead. + (Contributed by Nikita Sobolev in :gh:`97850`.) Pending Removal in Python 3.13 diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index 314c6f5cb9443d..3e13e2df0d903e 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -465,10 +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) + 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: @@ -493,10 +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) + 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) diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index c75e2d9736732c..8f44edad786fe6 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -1,6 +1,6 @@ from pathlib import Path from test.support.import_helper import unload, CleanImport -from test.support.warnings_helper import check_warnings +from test.support.warnings_helper import check_warnings, ignore_warnings import unittest import sys import importlib @@ -10,7 +10,6 @@ import os.path import tempfile import shutil -import warnings import zipfile # Note: pkgutil.walk_packages is currently tested in test_runpy. This is @@ -550,29 +549,18 @@ def test_loader_deprecated(self): with self.check_deprecated(): pkgutil.ImpLoader("", "", "", "") - 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, - )): - res = pkgutil.get_loader(module) - self.assertIsNotNone(res) - @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: - with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - self.assertIsNotNone(pkgutil.get_loader(__name__)) + 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) @@ -582,6 +570,7 @@ def test_get_loader_handles_missing_spec_attribute(self): 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) @@ -591,6 +580,7 @@ def test_get_loader_handles_spec_attribute_none(self): 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 @@ -600,22 +590,28 @@ def test_get_loader_None_in_sys_modules(self): del sys.modules[name] self.assertIsNone(loader) - def test_find_loader_missing_module(self): - name = 'totally bogus' - loader = pkgutil.find_loader(name) - self.assertIsNone(loader) + def test_get_loader_is_deprecated(self): + for module in ["sys", "os", "test.support"]: + with check_warnings( + (r".*\bpkgutil.get_loader\b.*", DeprecationWarning), + ): + res = pkgutil.get_loader(module) + self.assertIsNotNone(res) 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, - )): + with check_warnings( + (r".*\bpkgutil.find_loader\b.*", DeprecationWarning), + ): res = pkgutil.find_loader(module) 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: From d55a9b7dd3b1a4775875c014510b2ea8401fa44d Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 9 Nov 2022 16:22:33 +0300 Subject: [PATCH 3/9] Update Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst Co-authored-by: C.A.M. Gerlach --- .../next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst index 77d525e1a4a549..f91435485c4bd8 100644 --- a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst +++ b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst @@ -1 +1,2 @@ -Deprecate :func:`pkgutil.find_module` and :func:`pkgutil.get_module`. +Deprecate :func:`pkgutil.find_module` and :func:`pkgutil.get_module` +in favor of :func:`importlib.util.find_spec`. From e282911c118b38765de605a8eb5719bcf9df50e6 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 26 Nov 2022 13:13:38 +0300 Subject: [PATCH 4/9] Use just one module --- Lib/test/test_pkgutil.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 8f44edad786fe6..46117cd2e7e5c5 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -591,20 +591,18 @@ def test_get_loader_None_in_sys_modules(self): self.assertIsNone(loader) def test_get_loader_is_deprecated(self): - for module in ["sys", "os", "test.support"]: - with check_warnings( - (r".*\bpkgutil.get_loader\b.*", DeprecationWarning), - ): - res = pkgutil.get_loader(module) - self.assertIsNotNone(res) + with check_warnings( + (r".*\bpkgutil.get_loader\b.*", DeprecationWarning), + ): + res = pkgutil.get_loader("sys") + self.assertIsNotNone(res) def test_find_loader_is_deprecated(self): - for module in ["sys", "os", "test.support"]: - with check_warnings( - (r".*\bpkgutil.find_loader\b.*", DeprecationWarning), - ): - res = pkgutil.find_loader(module) - self.assertIsNotNone(res) + 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): From 817f2dacef8d279fe9ffd590c9e58260234851fb Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 5 Feb 2023 14:45:33 +0300 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Brett Cannon --- Doc/whatsnew/3.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index eeb1ac81a60cc7..bc5794133c6c41 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -408,7 +408,7 @@ Deprecated :exc:`ImportWarning`). (Contributed by Brett Cannon in :gh:`65961`.) -* :func:`pkgutil.find_module` and :func:`pkgutil.get_module` +* :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`.) From 8b116d932a8873e9c39b7e4a06d5c008d23a354b Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 5 Feb 2023 14:59:53 +0300 Subject: [PATCH 6/9] Update Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst Co-authored-by: Brett Cannon --- .../next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst index f91435485c4bd8..e3297d164fff6d 100644 --- a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst +++ b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst @@ -1,2 +1,2 @@ -Deprecate :func:`pkgutil.find_module` and :func:`pkgutil.get_module` +Deprecate :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` in favor of :func:`importlib.util.find_spec`. From e073fac9576069662eb9f97fd06c114cfabeec60 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 19 Apr 2023 12:26:28 +0300 Subject: [PATCH 7/9] Mention deprecation in `pkgutil` docs --- Doc/library/pkgutil.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst index 788a02dcb8922f..28e5b4101ea9da 100644 --- a/Doc/library/pkgutil.rst +++ b/Doc/library/pkgutil.rst @@ -91,6 +91,10 @@ support. .. versionchanged:: 3.4 Updated to be based on :pep:`451` + .. deprecated:: 3.12 + Use :func:`importlib.util.find_spec` instead. + + .. function:: get_importer(path_item) Retrieve a :term:`finder` for the given *path_item*. @@ -123,6 +127,9 @@ support. .. versionchanged:: 3.4 Updated to be based on :pep:`451` + .. deprecated:: 3.12 + Use :func:`importlib.util.find_spec` instead. + .. function:: iter_importers(fullname='') From 1e26981c5c7795aab510abf7b2c2c2f23e054886 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 19 Apr 2023 15:57:33 +0300 Subject: [PATCH 8/9] Address review --- Doc/library/pkgutil.rst | 4 ++-- Doc/whatsnew/3.12.rst | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst index 28e5b4101ea9da..5ec33cd97b2583 100644 --- a/Doc/library/pkgutil.rst +++ b/Doc/library/pkgutil.rst @@ -91,7 +91,7 @@ support. .. versionchanged:: 3.4 Updated to be based on :pep:`451` - .. deprecated:: 3.12 + .. deprecated-removed:: 3.12 3.14 Use :func:`importlib.util.find_spec` instead. @@ -127,7 +127,7 @@ support. .. versionchanged:: 3.4 Updated to be based on :pep:`451` - .. deprecated:: 3.12 + .. deprecated-removed:: 3.12 3.14 Use :func:`importlib.util.find_spec` instead. diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 529df03e88dad3..afbc18f27b5afb 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -572,11 +572,6 @@ Deprecated :exc:`ImportWarning`). (Contributed by Brett Cannon in :gh:`65961`.) -* :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`.) - * The :meth:`~asyncio.get_event_loop` method of the default event loop policy now emits a :exc:`DeprecationWarning` if there is no current event loop set and it decides to create one. @@ -695,6 +690,11 @@ Pending Removal in Python 3.14 * The *onerror* argument of :func:`shutil.rmtree` is deprecated in 3.12, and will be removed in 3.14. +* :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`.) + Pending Removal in Future Versions ---------------------------------- From 619c4dcd09985fab0aa2cabe53163b8b4b20b349 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 3 May 2023 12:52:10 -0700 Subject: [PATCH 9/9] Apply suggestions from code review --- Lib/pkgutil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index bb98d7ad24deb2..95bd2db7bdea50 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -286,7 +286,7 @@ def get_loader(module_or_name): """ warnings._deprecated("pkgutil.get_loader", f"{warnings._DEPRECATED_MSG}; " - "use importlib.util.find_spec instead", + "use importlib.util.find_spec() instead", remove=(3, 14)) if module_or_name in sys.modules: module_or_name = sys.modules[module_or_name] @@ -314,7 +314,7 @@ def find_loader(fullname): """ warnings._deprecated("pkgutil.find_loader", f"{warnings._DEPRECATED_MSG}; " - "use importlib.util.find_spec instead", + "use importlib.util.find_spec() instead", remove=(3, 14)) if fullname.startswith('.'): msg = "Relative module name {!r} not supported".format(fullname)