Skip to content

Commit 582f137

Browse files
authored
bpo-39994: Fix pprint handling of dict subclasses that override __repr__ (pythonGH-21892)
Co-authored-by: Palak Kumar Jha
1 parent 92c3816 commit 582f137

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

Lib/pprint.py

-6
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,6 @@ def _format(self, object, stream, indent, allowance, context, level):
176176
p(self, object, stream, indent, allowance, context, level + 1)
177177
del context[objid]
178178
return
179-
elif isinstance(object, dict):
180-
context[objid] = 1
181-
self._pprint_dict(object, stream, indent, allowance,
182-
context, level + 1)
183-
del context[objid]
184-
return
185179
stream.write(rep)
186180

187181
_dispatch = {}

Lib/test/test_pprint.py

+48-1
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,54 @@ class list3(list):
1818
def __repr__(self):
1919
return list.__repr__(self)
2020

21+
class list_custom_repr(list):
22+
def __repr__(self):
23+
return '*'*len(list.__repr__(self))
24+
2125
class tuple2(tuple):
2226
pass
2327

2428
class tuple3(tuple):
2529
def __repr__(self):
2630
return tuple.__repr__(self)
2731

32+
class tuple_custom_repr(tuple):
33+
def __repr__(self):
34+
return '*'*len(tuple.__repr__(self))
35+
2836
class set2(set):
2937
pass
3038

3139
class set3(set):
3240
def __repr__(self):
3341
return set.__repr__(self)
3442

43+
class set_custom_repr(set):
44+
def __repr__(self):
45+
return '*'*len(set.__repr__(self))
46+
3547
class frozenset2(frozenset):
3648
pass
3749

3850
class frozenset3(frozenset):
3951
def __repr__(self):
4052
return frozenset.__repr__(self)
4153

54+
class frozenset_custom_repr(frozenset):
55+
def __repr__(self):
56+
return '*'*len(frozenset.__repr__(self))
57+
4258
class dict2(dict):
4359
pass
4460

4561
class dict3(dict):
4662
def __repr__(self):
4763
return dict.__repr__(self)
4864

65+
class dict_custom_repr(dict):
66+
def __repr__(self):
67+
return '*'*len(dict.__repr__(self))
68+
4969
class Unorderable:
5070
def __repr__(self):
5171
return str(id(self))
@@ -155,7 +175,8 @@ def test_unreadable(self):
155175
"expected not isreadable for %r" % (unreadable,))
156176

157177
def test_same_as_repr(self):
158-
# Simple objects, small containers and classes that overwrite __repr__
178+
# Simple objects, small containers and classes that override __repr__
179+
# to directly call super's __repr__.
159180
# For those the result should be the same as repr().
160181
# Ahem. The docs don't say anything about that -- this appears to
161182
# be testing an implementation quirk. Starting in Python 2.5, it's
@@ -187,6 +208,32 @@ def test_same_as_repr(self):
187208
.replace('\n', ' '), native)
188209
self.assertEqual(pprint.saferepr(simple), native)
189210

211+
def test_container_repr_override_called(self):
212+
N = 1000
213+
# Ensure that __repr__ override is called for subclasses of containers
214+
215+
for cont in (list_custom_repr(),
216+
list_custom_repr([1,2,3]),
217+
list_custom_repr(range(N)),
218+
tuple_custom_repr(),
219+
tuple_custom_repr([1,2,3]),
220+
tuple_custom_repr(range(N)),
221+
set_custom_repr(),
222+
set_custom_repr([1,2,3]),
223+
set_custom_repr(range(N)),
224+
frozenset_custom_repr(),
225+
frozenset_custom_repr([1,2,3]),
226+
frozenset_custom_repr(range(N)),
227+
dict_custom_repr(),
228+
dict_custom_repr({5: 6}),
229+
dict_custom_repr(zip(range(N),range(N))),
230+
):
231+
native = repr(cont)
232+
expected = '*' * len(native)
233+
self.assertEqual(pprint.pformat(cont), expected)
234+
self.assertEqual(pprint.pformat(cont, width=1, indent=0), expected)
235+
self.assertEqual(pprint.saferepr(cont), expected)
236+
190237
def test_basic_line_wrap(self):
191238
# verify basic line-wrapping operation
192239
o = {'RPM_cal': 0,

Misc/ACKS

+1
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,7 @@ Per Øyvind Karlsen
856856
Anton Kasyanov
857857
Lou Kates
858858
Makoto Kato
859+
Irit Katriel
859860
Hiroaki Kawai
860861
Dmitry Kazakov
861862
Brian Kearns
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed pprint's handling of dict subclasses that override __repr__.

0 commit comments

Comments
 (0)