diff options
author | Barry Warsaw <barry@python.org> | 2022-08-05 00:24:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-05 00:24:26 (GMT) |
commit | e1182bc3776ea7cfdd3f82d5ba4fdfee40ae57ee (patch) | |
tree | a83cbfa65f28dd2de5cefdabecd7daa925152f28 | |
parent | 44f1f63ad5cf00b6f50cef0cc1a62c42632138be (diff) | |
download | cpython-e1182bc3776ea7cfdd3f82d5ba4fdfee40ae57ee.zip cpython-e1182bc3776ea7cfdd3f82d5ba4fdfee40ae57ee.tar.gz cpython-e1182bc3776ea7cfdd3f82d5ba4fdfee40ae57ee.tar.bz2 |
gh-94619: Remove long deprecated methods module_repr() and load_module() (#94624)
* gh-94619: Remove long deprecated methods module_repr() and load_module()
Closes #94619
* Update Misc/NEWS.d/next/Library/2022-07-06-14-57-33.gh-issue-94619.PRqKVX.rst
Fix typo
Co-authored-by: Brett Cannon <brett@python.org>
Co-authored-by: Brett Cannon <brett@python.org>
-rw-r--r-- | Doc/library/importlib.rst | 14 | ||||
-rw-r--r-- | Doc/reference/import.rst | 20 | ||||
-rw-r--r-- | Lib/importlib/_abc.py | 14 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap.py | 6 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap_external.py | 13 | ||||
-rw-r--r-- | Lib/test/test_importlib/frozen/test_loader.py | 8 | ||||
-rw-r--r-- | Lib/test/test_importlib/source/test_file_loader.py | 1 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_abc.py | 2 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_namespace_pkgs.py | 7 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_spec.py | 95 | ||||
-rw-r--r-- | Lib/test/test_module.py | 10 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2022-07-06-14-57-33.gh-issue-94619.PRqKVX.rst | 1 |
12 files changed, 11 insertions, 180 deletions
diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index c29d69c..0fd765f 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -493,20 +493,6 @@ ABC hierarchy:: other responsibilities of :meth:`load_module` when :meth:`exec_module` is implemented. - .. method:: module_repr(module) - - A legacy method which when implemented calculates and returns the given - module's representation, as a string. The module type's default - :meth:`__repr__` will use the result of this method as appropriate. - - .. versionadded:: 3.3 - - .. versionchanged:: 3.4 - Made optional instead of an abstractmethod. - - .. deprecated:: 3.4 - The import machinery now takes care of this automatically. - .. class:: ResourceLoader diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 1e6b08f..507f2b3 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -676,22 +676,10 @@ Here are the exact rules used: * Otherwise, just use the module's ``__name__`` in the repr. -.. versionchanged:: 3.4 - Use of :meth:`loader.module_repr() <importlib.abc.Loader.module_repr>` - has been deprecated and the module spec is now used by the import - machinery to generate a module repr. - - For backward compatibility with Python 3.3, the module repr will be - generated by calling the loader's - :meth:`~importlib.abc.Loader.module_repr` method, if defined, before - trying either approach described above. However, the method is deprecated. - -.. versionchanged:: 3.10 - - Calling :meth:`~importlib.abc.Loader.module_repr` now occurs after trying to - use a module's ``__spec__`` attribute but before falling back on - ``__file__``. Use of :meth:`~importlib.abc.Loader.module_repr` is slated to - stop in Python 3.12. +.. versionchanged:: 3.12 + Use of :meth:`module_repr`, having been deprecated since Python 3.4, was + removed in Python 3.12 and is no longer called during the resolution of a + module's repr. .. _pyc-invalidation: diff --git a/Lib/importlib/_abc.py b/Lib/importlib/_abc.py index f80348f..0832056 100644 --- a/Lib/importlib/_abc.py +++ b/Lib/importlib/_abc.py @@ -38,17 +38,3 @@ class Loader(metaclass=abc.ABCMeta): raise ImportError # Warning implemented in _load_module_shim(). return _bootstrap._load_module_shim(self, fullname) - - def module_repr(self, module): - """Return a module's repr. - - Used by the module type when the method does not raise - NotImplementedError. - - This method is deprecated. - - """ - warnings.warn("importlib.abc.Loader.module_repr() is deprecated and " - "slated for removal in Python 3.12", DeprecationWarning) - # The exception will cause ModuleType.__repr__ to ignore this method. - raise NotImplementedError diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index afb95f4..67989c5 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -296,11 +296,6 @@ def _module_repr(module): loader = getattr(module, '__loader__', None) if spec := getattr(module, "__spec__", None): return _module_repr_from_spec(spec) - elif hasattr(loader, 'module_repr'): - try: - return loader.module_repr(module) - except Exception: - pass # Fall through to a catch-all which always succeeds. try: name = module.__name__ @@ -582,7 +577,6 @@ def module_from_spec(spec): def _module_repr_from_spec(spec): """Return the repr to use for the module.""" - # We mostly replicate _module_repr() using the spec attributes. name = '?' if spec.name is None else spec.name if spec.origin is None: if spec.loader is None: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index b6c6716..82d2042 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1339,22 +1339,11 @@ class _NamespacePath: # This class is actually exposed publicly in a namespace package's __loader__ # attribute, so it should be available through a non-private name. -# https://bugs.python.org/issue35673 +# https://github.com/python/cpython/issues/92054 class NamespaceLoader: def __init__(self, name, path, path_finder): self._path = _NamespacePath(name, path, path_finder) - @staticmethod - def module_repr(module): - """Return repr for the module. - - The method is deprecated. The import machinery does the job itself. - - """ - _warnings.warn("NamespaceLoader.module_repr() is deprecated and " - "slated for removal in Python 3.12", DeprecationWarning) - return '<module {!r} (namespace)>'.format(module.__name__) - def is_package(self, fullname): return True diff --git a/Lib/test/test_importlib/frozen/test_loader.py b/Lib/test/test_importlib/frozen/test_loader.py index f2df7e6..32f951c 100644 --- a/Lib/test/test_importlib/frozen/test_loader.py +++ b/Lib/test/test_importlib/frozen/test_loader.py @@ -103,14 +103,6 @@ class ExecModuleTests(abc.LoaderTests): expected=value)) self.assertEqual(output, 'Hello world!\n') - def test_module_repr(self): - name = '__hello__' - module, output = self.exec_module(name) - with deprecated(): - repr_str = self.machinery.FrozenImporter.module_repr(module) - self.assertEqual(repr_str, - "<module '__hello__' (frozen)>") - def test_module_repr_indirect(self): name = '__hello__' module, output = self.exec_module(name) diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py index 378dcbe..f35adec 100644 --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -51,7 +51,6 @@ class SimpleTest(abc.LoaderTests): def get_code(self, _): pass def get_source(self, _): pass def is_package(self, _): pass - def module_repr(self, _): pass path = 'some_path' name = 'some_name' diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py index d59b663..88bf100 100644 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -221,8 +221,6 @@ class LoaderDefaultsTests(ABCTestHarness): mod = types.ModuleType('blah') with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - with self.assertRaises(NotImplementedError): - self.ins.module_repr(mod) original_repr = repr(mod) mod.__loader__ = self.ins # Should still return a proper repr. diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index cd08498..f451f75 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -79,13 +79,6 @@ class SingleNamespacePackage(NamespacePackageTest): with self.assertRaises(ImportError): import foo.two - def test_module_repr(self): - import foo.one - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - self.assertEqual(foo.__spec__.loader.module_repr(foo), - "<module 'foo' (namespace)>") - class DynamicPathNamespacePackage(NamespacePackageTest): paths = ['portion1'] diff --git a/Lib/test/test_importlib/test_spec.py b/Lib/test/test_importlib/test_spec.py index 21e2c02..f1ab16c 100644 --- a/Lib/test/test_importlib/test_spec.py +++ b/Lib/test/test_importlib/test_spec.py @@ -407,101 +407,6 @@ class ModuleSpecMethodsTests: machinery=machinery) -class ModuleReprTests: - - @property - def bootstrap(self): - return self.init._bootstrap - - def setUp(self): - self.module = type(os)('spam') - self.spec = self.machinery.ModuleSpec('spam', TestLoader()) - - def test_module___loader___module_repr(self): - class Loader: - def module_repr(self, module): - return '<delicious {}>'.format(module.__name__) - self.module.__loader__ = Loader() - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, '<delicious spam>') - - def test_module___loader___module_repr_bad(self): - class Loader(TestLoader): - def module_repr(self, module): - raise Exception - self.module.__loader__ = Loader() - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, - '<module {!r} (<TestLoader object>)>'.format('spam')) - - def test_module___spec__(self): - origin = 'in a hole, in the ground' - self.spec.origin = origin - self.module.__spec__ = self.spec - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, '<module {!r} ({})>'.format('spam', origin)) - - def test_module___spec___location(self): - location = 'in_a_galaxy_far_far_away.py' - self.spec.origin = location - self.spec._set_fileattr = True - self.module.__spec__ = self.spec - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, - '<module {!r} from {!r}>'.format('spam', location)) - - def test_module___spec___no_origin(self): - self.spec.loader = TestLoader() - self.module.__spec__ = self.spec - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, - '<module {!r} (<TestLoader object>)>'.format('spam')) - - def test_module___spec___no_origin_no_loader(self): - self.spec.loader = None - self.module.__spec__ = self.spec - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, '<module {!r}>'.format('spam')) - - def test_module_no_name(self): - del self.module.__name__ - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, '<module {!r}>'.format('?')) - - def test_module_with_file(self): - filename = 'e/i/e/i/o/spam.py' - self.module.__file__ = filename - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, - '<module {!r} from {!r}>'.format('spam', filename)) - - def test_module_no_file(self): - self.module.__loader__ = TestLoader() - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, - '<module {!r} (<TestLoader object>)>'.format('spam')) - - def test_module_no_file_no_loader(self): - modrepr = self.bootstrap._module_repr(self.module) - - self.assertEqual(modrepr, '<module {!r}>'.format('spam')) - - -(Frozen_ModuleReprTests, - Source_ModuleReprTests - ) = test_util.test_both(ModuleReprTests, init=init, util=util, - machinery=machinery) - - class FactoryTests: def setUp(self): diff --git a/Lib/test/test_module.py b/Lib/test/test_module.py index f72177d..6c83d76 100644 --- a/Lib/test/test_module.py +++ b/Lib/test/test_module.py @@ -8,10 +8,10 @@ from test.support.script_helper import assert_python_ok import sys ModuleType = type(sys) + class FullLoader: - @classmethod - def module_repr(cls, m): - return "<module '{}' (crafted)>".format(m.__name__) + pass + class BareLoader: pass @@ -236,7 +236,7 @@ a = A(destroyed)""" # Yes, a class not an instance. m.__loader__ = FullLoader self.assertEqual( - repr(m), "<module 'foo' (crafted)>") + repr(m), "<module 'foo' (<class 'test.test_module.FullLoader'>)>") def test_module_repr_with_bare_loader_and_filename(self): # Because the loader has no module_repr(), use the file name. @@ -252,7 +252,7 @@ a = A(destroyed)""" # Yes, a class not an instance. m.__loader__ = FullLoader m.__file__ = '/tmp/foo.py' - self.assertEqual(repr(m), "<module 'foo' (crafted)>") + self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") def test_module_repr_builtin(self): self.assertEqual(repr(sys), "<module 'sys' (built-in)>") diff --git a/Misc/NEWS.d/next/Library/2022-07-06-14-57-33.gh-issue-94619.PRqKVX.rst b/Misc/NEWS.d/next/Library/2022-07-06-14-57-33.gh-issue-94619.PRqKVX.rst new file mode 100644 index 0000000..a790503 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-06-14-57-33.gh-issue-94619.PRqKVX.rst @@ -0,0 +1 @@ +Remove the long-deprecated `module_repr()` from `importlib`. |