https://github.com/python/cpython/commit/04d6dd23e2d8a3132772cf7ce928676e26313585
commit: 04d6dd23e2d8a3132772cf7ce928676e26313585
branch: main
author: George Pittock <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-10-17T16:34:37Z
summary:

gh-113570: reprlib.repr does not use builtin __repr__ for reshadowed builtins 
(GH-113577)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2023-12-30-00-21-45.gh-issue-113570._XQgsW.rst
M Lib/reprlib.py
M Lib/test/test_reprlib.py

diff --git a/Lib/reprlib.py b/Lib/reprlib.py
index 05bb1a0eb01795..19dbe3a07eb618 100644
--- a/Lib/reprlib.py
+++ b/Lib/reprlib.py
@@ -36,6 +36,17 @@ def wrapper(self):
     return decorating_function
 
 class Repr:
+    _lookup = {
+        'tuple': 'builtins',
+        'list': 'builtins',
+        'array': 'array',
+        'set': 'builtins',
+        'frozenset': 'builtins',
+        'deque': 'collections',
+        'dict': 'builtins',
+        'str': 'builtins',
+        'int': 'builtins'
+    }
 
     def __init__(
         self, *, maxlevel=6, maxtuple=6, maxlist=6, maxarray=5, maxdict=4,
@@ -60,14 +71,24 @@ def repr(self, x):
         return self.repr1(x, self.maxlevel)
 
     def repr1(self, x, level):
-        typename = type(x).__name__
+        cls = type(x)
+        typename = cls.__name__
+
         if ' ' in typename:
             parts = typename.split()
             typename = '_'.join(parts)
-        if hasattr(self, 'repr_' + typename):
-            return getattr(self, 'repr_' + typename)(x, level)
-        else:
-            return self.repr_instance(x, level)
+
+        method = getattr(self, 'repr_' + typename, None)
+        if method:
+            # not defined in this class
+            if typename not in self._lookup:
+                return method(x, level)
+            module = getattr(cls, '__module__', None)
+            # defined in this class and is the module intended
+            if module == self._lookup[typename]:
+                return method(x, level)
+
+        return self.repr_instance(x, level)
 
     def _join(self, pieces, level):
         if self.indent is None:
diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py
index 3e93b561c143d8..ffeb1fba7b80c6 100644
--- a/Lib/test/test_reprlib.py
+++ b/Lib/test/test_reprlib.py
@@ -580,6 +580,50 @@ def test_invalid_indent(self):
                 with self.assertRaisesRegex(expected_error, expected_msg):
                     r.repr(test_object)
 
+    def test_shadowed_stdlib_array(self):
+        # Issue #113570: repr() should not be fooled by an array
+        class array:
+            def __repr__(self):
+                return "not array.array"
+
+        self.assertEqual(r(array()), "not array.array")
+
+    def test_shadowed_builtin(self):
+        # Issue #113570: repr() should not be fooled
+        # by a shadowed builtin function
+        class list:
+            def __repr__(self):
+                return "not builtins.list"
+
+        self.assertEqual(r(list()), "not builtins.list")
+
+    def test_custom_repr(self):
+        class MyRepr(Repr):
+
+            def repr_TextIOWrapper(self, obj, level):
+                if obj.name in {'<stdin>', '<stdout>', '<stderr>'}:
+                    return obj.name
+                return repr(obj)
+
+        aRepr = MyRepr()
+        self.assertEqual(aRepr.repr(sys.stdin), "<stdin>")
+
+    def test_custom_repr_class_with_spaces(self):
+        class TypeWithSpaces:
+            pass
+
+        t = TypeWithSpaces()
+        type(t).__name__ = "type with spaces"
+        self.assertEqual(type(t).__name__, "type with spaces")
+
+        class MyRepr(Repr):
+            def repr_type_with_spaces(self, obj, level):
+                return "Type With Spaces"
+
+
+        aRepr = MyRepr()
+        self.assertEqual(aRepr.repr(t), "Type With Spaces")
+
 def write_file(path, text):
     with open(path, 'w', encoding='ASCII') as fp:
         fp.write(text)
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2023-12-30-00-21-45.gh-issue-113570._XQgsW.rst b/Misc/NEWS.d/next/Core 
and Builtins/2023-12-30-00-21-45.gh-issue-113570._XQgsW.rst
new file mode 100644
index 00000000000000..6e0f0afe05369b
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2023-12-30-00-21-45.gh-issue-113570._XQgsW.rst 
@@ -0,0 +1 @@
+Fixed a bug in ``reprlib.repr`` where it incorrectly called the repr method on 
shadowed Python built-in types.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to