bpo-39994: Fix pprint handling of dict subclasses that override __repr__ (GH-21892)
Co-authored-by: Palak Kumar Jha
diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py
index cf3e4f0..8ee18e8 100644
--- a/Lib/test/test_pprint.py
+++ b/Lib/test/test_pprint.py
@@ -18,6 +18,10 @@
def __repr__(self):
return list.__repr__(self)
+class list_custom_repr(list):
+ def __repr__(self):
+ return '*'*len(list.__repr__(self))
+
class tuple2(tuple):
pass
@@ -25,6 +29,10 @@
def __repr__(self):
return tuple.__repr__(self)
+class tuple_custom_repr(tuple):
+ def __repr__(self):
+ return '*'*len(tuple.__repr__(self))
+
class set2(set):
pass
@@ -32,6 +40,10 @@
def __repr__(self):
return set.__repr__(self)
+class set_custom_repr(set):
+ def __repr__(self):
+ return '*'*len(set.__repr__(self))
+
class frozenset2(frozenset):
pass
@@ -39,6 +51,10 @@
def __repr__(self):
return frozenset.__repr__(self)
+class frozenset_custom_repr(frozenset):
+ def __repr__(self):
+ return '*'*len(frozenset.__repr__(self))
+
class dict2(dict):
pass
@@ -46,6 +62,10 @@
def __repr__(self):
return dict.__repr__(self)
+class dict_custom_repr(dict):
+ def __repr__(self):
+ return '*'*len(dict.__repr__(self))
+
class Unorderable:
def __repr__(self):
return str(id(self))
@@ -155,7 +175,8 @@
"expected not isreadable for %r" % (unreadable,))
def test_same_as_repr(self):
- # Simple objects, small containers and classes that overwrite __repr__
+ # Simple objects, small containers and classes that override __repr__
+ # to directly call super's __repr__.
# For those the result should be the same as repr().
# Ahem. The docs don't say anything about that -- this appears to
# be testing an implementation quirk. Starting in Python 2.5, it's
@@ -187,6 +208,32 @@
.replace('\n', ' '), native)
self.assertEqual(pprint.saferepr(simple), native)
+ def test_container_repr_override_called(self):
+ N = 1000
+ # Ensure that __repr__ override is called for subclasses of containers
+
+ for cont in (list_custom_repr(),
+ list_custom_repr([1,2,3]),
+ list_custom_repr(range(N)),
+ tuple_custom_repr(),
+ tuple_custom_repr([1,2,3]),
+ tuple_custom_repr(range(N)),
+ set_custom_repr(),
+ set_custom_repr([1,2,3]),
+ set_custom_repr(range(N)),
+ frozenset_custom_repr(),
+ frozenset_custom_repr([1,2,3]),
+ frozenset_custom_repr(range(N)),
+ dict_custom_repr(),
+ dict_custom_repr({5: 6}),
+ dict_custom_repr(zip(range(N),range(N))),
+ ):
+ native = repr(cont)
+ expected = '*' * len(native)
+ self.assertEqual(pprint.pformat(cont), expected)
+ self.assertEqual(pprint.pformat(cont, width=1, indent=0), expected)
+ self.assertEqual(pprint.saferepr(cont), expected)
+
def test_basic_line_wrap(self):
# verify basic line-wrapping operation
o = {'RPM_cal': 0,