summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2022-08-05 00:24:26 (GMT)
committerGitHub <noreply@github.com>2022-08-05 00:24:26 (GMT)
commite1182bc3776ea7cfdd3f82d5ba4fdfee40ae57ee (patch)
treea83cbfa65f28dd2de5cefdabecd7daa925152f28
parent44f1f63ad5cf00b6f50cef0cc1a62c42632138be (diff)
downloadcpython-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.rst14
-rw-r--r--Doc/reference/import.rst20
-rw-r--r--Lib/importlib/_abc.py14
-rw-r--r--Lib/importlib/_bootstrap.py6
-rw-r--r--Lib/importlib/_bootstrap_external.py13
-rw-r--r--Lib/test/test_importlib/frozen/test_loader.py8
-rw-r--r--Lib/test/test_importlib/source/test_file_loader.py1
-rw-r--r--Lib/test/test_importlib/test_abc.py2
-rw-r--r--Lib/test/test_importlib/test_namespace_pkgs.py7
-rw-r--r--Lib/test/test_importlib/test_spec.py95
-rw-r--r--Lib/test/test_module.py10
-rw-r--r--Misc/NEWS.d/next/Library/2022-07-06-14-57-33.gh-issue-94619.PRqKVX.rst1
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`.