From 582f13786bb75c73d609790967fea03a5b50148a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 30 Aug 2020 18:29:53 +0100 Subject: [PATCH] bpo-39994: Fix pprint handling of dict subclasses that override __repr__ (GH-21892) Co-authored-by: Palak Kumar Jha --- Lib/pprint.py | 6 --- Lib/test/test_pprint.py | 49 ++++++++++++++++++- Misc/ACKS | 1 + .../2020-08-15-18-17-21.bpo-39994.dOgPOh.rst | 1 + 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst diff --git a/Lib/pprint.py b/Lib/pprint.py index 7c1118a484b..213998e3491 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -176,12 +176,6 @@ class PrettyPrinter: p(self, object, stream, indent, allowance, context, level + 1) del context[objid] return - elif isinstance(object, dict): - context[objid] = 1 - self._pprint_dict(object, stream, indent, allowance, - context, level + 1) - del context[objid] - return stream.write(rep) _dispatch = {} diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index cf3e4f093b1..8ee18e8fef8 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -18,6 +18,10 @@ class list3(list): 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 @@ class tuple3(tuple): 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 @@ class set3(set): 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 @@ class frozenset3(frozenset): 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 @@ class dict3(dict): 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 @@ class QueryTestCase(unittest.TestCase): "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 @@ class QueryTestCase(unittest.TestCase): .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, diff --git a/Misc/ACKS b/Misc/ACKS index 1599b09c692..a2cdeb85040 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -856,6 +856,7 @@ Per Øyvind Karlsen Anton Kasyanov Lou Kates Makoto Kato +Irit Katriel Hiroaki Kawai Dmitry Kazakov Brian Kearns diff --git a/Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst b/Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst new file mode 100644 index 00000000000..46876c15ea1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst @@ -0,0 +1 @@ +Fixed pprint's handling of dict subclasses that override __repr__.