]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-112414: Fix `AttributeError` when calling `repr()` on a namespace package...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 27 Nov 2023 08:53:57 +0000 (09:53 +0100)
committerGitHub <noreply@github.com>
Mon, 27 Nov 2023 08:53:57 +0000 (08:53 +0000)
gh-112414: Fix `AttributeError` when calling `repr()` on a namespace package imported with a custom loader (GH-112425)
(cherry picked from commit 0622839cfedacbb48eba27180fd0f0586fe97771)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Lib/importlib/_bootstrap.py
Lib/test/test_importlib/import_/test___loader__.py
Lib/test/test_importlib/test_namespace_pkgs.py
Misc/NEWS.d/next/Library/2023-11-26-13-44-19.gh-issue-112414.kx2E7S.rst [new file with mode: 0644]

index ec2e56f6ea9ca185f0af2daa7980ac08b0f73a00..d942045f3de666fab79ffcfe20dbe838828f0441 100644 (file)
@@ -824,10 +824,16 @@ def _module_repr_from_spec(spec):
     """Return the repr to use for the module."""
     name = '?' if spec.name is None else spec.name
     if spec.origin is None:
-        if spec.loader is None:
+        loader = spec.loader
+        if loader is None:
             return f'<module {name!r}>'
+        elif (
+            _bootstrap_external is not None
+            and isinstance(loader, _bootstrap_external.NamespaceLoader)
+        ):
+            return f'<module {name!r} (namespace) from {list(loader._path)}>'
         else:
-            return f'<module {name!r} (namespace) from {list(spec.loader._path)}>'
+            return f'<module {name!r} ({loader!r})>'
     else:
         if spec.has_location:
             return f'<module {name!r} from {spec.origin!r}>'
index a14163919af677ad8d27f346ac5c05ae67ee25d4..cb9a03229965f129cc6828cdb4721e4a5c344c6a 100644 (file)
@@ -26,6 +26,10 @@ class SpecLoaderAttributeTests:
         with util.uncache('blah'), util.import_state(meta_path=[loader]):
             module = self.__import__('blah')
         self.assertEqual(loader, module.__loader__)
+        expected_repr_pattern = (
+            r"<module 'blah' \(<test\.test_importlib\..*SpecLoaderMock object at .+>\)>"
+        )
+        self.assertRegex(repr(module), expected_repr_pattern)
 
 
 (Frozen_SpecTests,
index 65428c3d3ead9bfa876a0e50c31dd673b9e0407e..cdbdecc94fede396656cb63872ead1fbe06ed843 100644 (file)
@@ -81,7 +81,7 @@ class SingleNamespacePackage(NamespacePackageTest):
 
     def test_simple_repr(self):
         import foo.one
-        assert repr(foo).startswith("<module 'foo' (namespace) from [")
+        self.assertTrue(repr(foo).startswith("<module 'foo' (namespace) from ["))
 
 
 class DynamicPathNamespacePackage(NamespacePackageTest):
diff --git a/Misc/NEWS.d/next/Library/2023-11-26-13-44-19.gh-issue-112414.kx2E7S.rst b/Misc/NEWS.d/next/Library/2023-11-26-13-44-19.gh-issue-112414.kx2E7S.rst
new file mode 100644 (file)
index 0000000..058e5a3
--- /dev/null
@@ -0,0 +1,3 @@
+Fix regression in Python 3.12 where calling :func:`repr` on a module that
+had been imported using a custom :term:`loader` could fail with
+:exc:`AttributeError`. Patch by Alex Waygood.