Skip to content

Commit bedbf96

Browse files
Issue #23870: The pprint module now supports all standard collections
except named tuples.
1 parent 0c59ff6 commit bedbf96

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed

Lib/pprint.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,86 @@ def format(self, object, context, maxlevels, level):
404404
"""
405405
return _safe_repr(object, context, maxlevels, level)
406406

407+
def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
408+
if not len(object):
409+
stream.write(repr(object))
410+
return
411+
rdf = self._repr(object.default_factory, context, level)
412+
cls = object.__class__
413+
indent += len(cls.__name__) + 1
414+
stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
415+
self._pprint_dict(object, stream, indent, allowance + 1, context, level)
416+
stream.write(')')
417+
418+
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
419+
420+
def _pprint_counter(self, object, stream, indent, allowance, context, level):
421+
if not len(object):
422+
stream.write(repr(object))
423+
return
424+
cls = object.__class__
425+
stream.write(cls.__name__ + '({')
426+
if self._indent_per_level > 1:
427+
stream.write((self._indent_per_level - 1) * ' ')
428+
items = object.most_common()
429+
self._format_dict_items(items, stream,
430+
indent + len(cls.__name__) + 1, allowance + 2,
431+
context, level)
432+
stream.write('})')
433+
434+
_dispatch[_collections.Counter.__repr__] = _pprint_counter
435+
436+
def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
437+
if not len(object.maps):
438+
stream.write(repr(object))
439+
return
440+
cls = object.__class__
441+
stream.write(cls.__name__ + '(')
442+
indent += len(cls.__name__) + 1
443+
for i, m in enumerate(object.maps):
444+
if i == len(object.maps) - 1:
445+
self._format(m, stream, indent, allowance + 1, context, level)
446+
stream.write(')')
447+
else:
448+
self._format(m, stream, indent, 1, context, level)
449+
stream.write(',\n' + ' ' * indent)
450+
451+
_dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
452+
453+
def _pprint_deque(self, object, stream, indent, allowance, context, level):
454+
if not len(object):
455+
stream.write(repr(object))
456+
return
457+
cls = object.__class__
458+
stream.write(cls.__name__ + '(')
459+
indent += len(cls.__name__) + 1
460+
stream.write('[')
461+
if object.maxlen is None:
462+
self._format_items(object, stream, indent, allowance + 2,
463+
context, level)
464+
stream.write('])')
465+
else:
466+
self._format_items(object, stream, indent, 2,
467+
context, level)
468+
rml = self._repr(object.maxlen, context, level)
469+
stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
470+
471+
_dispatch[_collections.deque.__repr__] = _pprint_deque
472+
473+
def _pprint_user_dict(self, object, stream, indent, allowance, context, level):
474+
self._format(object.data, stream, indent, allowance, context, level - 1)
475+
476+
_dispatch[_collections.UserDict.__repr__] = _pprint_user_dict
477+
478+
def _pprint_user_list(self, object, stream, indent, allowance, context, level):
479+
self._format(object.data, stream, indent, allowance, context, level - 1)
480+
481+
_dispatch[_collections.UserList.__repr__] = _pprint_user_list
482+
483+
def _pprint_user_string(self, object, stream, indent, allowance, context, level):
484+
self._format(object.data, stream, indent, allowance, context, level - 1)
485+
486+
_dispatch[_collections.UserString.__repr__] = _pprint_user_string
407487

408488
# Return triple (repr_string, isreadable, isrecursive).
409489

Lib/test/test_pprint.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,154 @@ def test_bytearray_wrap(self):
843843
[[[[[bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
844844
b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')]]]]]""")
845845

846+
def test_default_dict(self):
847+
d = collections.defaultdict(int)
848+
self.assertEqual(pprint.pformat(d, width=1), "defaultdict(<class 'int'>, {})")
849+
words = 'the quick brown fox jumped over a lazy dog'.split()
850+
d = collections.defaultdict(int, zip(words, itertools.count()))
851+
self.assertEqual(pprint.pformat(d),
852+
"""\
853+
defaultdict(<class 'int'>,
854+
{'a': 6,
855+
'brown': 2,
856+
'dog': 8,
857+
'fox': 3,
858+
'jumped': 4,
859+
'lazy': 7,
860+
'over': 5,
861+
'quick': 1,
862+
'the': 0})""")
863+
864+
def test_counter(self):
865+
d = collections.Counter()
866+
self.assertEqual(pprint.pformat(d, width=1), "Counter()")
867+
d = collections.Counter('senselessness')
868+
self.assertEqual(pprint.pformat(d, width=40),
869+
"""\
870+
Counter({'s': 6,
871+
'e': 4,
872+
'n': 2,
873+
'l': 1})""")
874+
875+
def test_chainmap(self):
876+
d = collections.ChainMap()
877+
self.assertEqual(pprint.pformat(d, width=1), "ChainMap({})")
878+
words = 'the quick brown fox jumped over a lazy dog'.split()
879+
items = list(zip(words, itertools.count()))
880+
d = collections.ChainMap(dict(items))
881+
self.assertEqual(pprint.pformat(d),
882+
"""\
883+
ChainMap({'a': 6,
884+
'brown': 2,
885+
'dog': 8,
886+
'fox': 3,
887+
'jumped': 4,
888+
'lazy': 7,
889+
'over': 5,
890+
'quick': 1,
891+
'the': 0})""")
892+
d = collections.ChainMap(dict(items), collections.OrderedDict(items))
893+
self.assertEqual(pprint.pformat(d),
894+
"""\
895+
ChainMap({'a': 6,
896+
'brown': 2,
897+
'dog': 8,
898+
'fox': 3,
899+
'jumped': 4,
900+
'lazy': 7,
901+
'over': 5,
902+
'quick': 1,
903+
'the': 0},
904+
OrderedDict([('the', 0),
905+
('quick', 1),
906+
('brown', 2),
907+
('fox', 3),
908+
('jumped', 4),
909+
('over', 5),
910+
('a', 6),
911+
('lazy', 7),
912+
('dog', 8)]))""")
913+
914+
def test_deque(self):
915+
d = collections.deque()
916+
self.assertEqual(pprint.pformat(d, width=1), "deque([])")
917+
d = collections.deque(maxlen=7)
918+
self.assertEqual(pprint.pformat(d, width=1), "deque([], maxlen=7)")
919+
words = 'the quick brown fox jumped over a lazy dog'.split()
920+
d = collections.deque(zip(words, itertools.count()))
921+
self.assertEqual(pprint.pformat(d),
922+
"""\
923+
deque([('the', 0),
924+
('quick', 1),
925+
('brown', 2),
926+
('fox', 3),
927+
('jumped', 4),
928+
('over', 5),
929+
('a', 6),
930+
('lazy', 7),
931+
('dog', 8)])""")
932+
d = collections.deque(zip(words, itertools.count()), maxlen=7)
933+
self.assertEqual(pprint.pformat(d),
934+
"""\
935+
deque([('brown', 2),
936+
('fox', 3),
937+
('jumped', 4),
938+
('over', 5),
939+
('a', 6),
940+
('lazy', 7),
941+
('dog', 8)],
942+
maxlen=7)""")
943+
944+
def test_user_dict(self):
945+
d = collections.UserDict()
946+
self.assertEqual(pprint.pformat(d, width=1), "{}")
947+
words = 'the quick brown fox jumped over a lazy dog'.split()
948+
d = collections.UserDict(zip(words, itertools.count()))
949+
self.assertEqual(pprint.pformat(d),
950+
"""\
951+
{'a': 6,
952+
'brown': 2,
953+
'dog': 8,
954+
'fox': 3,
955+
'jumped': 4,
956+
'lazy': 7,
957+
'over': 5,
958+
'quick': 1,
959+
'the': 0}""")
960+
961+
def test_user_dict(self):
962+
d = collections.UserList()
963+
self.assertEqual(pprint.pformat(d, width=1), "[]")
964+
words = 'the quick brown fox jumped over a lazy dog'.split()
965+
d = collections.UserList(zip(words, itertools.count()))
966+
self.assertEqual(pprint.pformat(d),
967+
"""\
968+
[('the', 0),
969+
('quick', 1),
970+
('brown', 2),
971+
('fox', 3),
972+
('jumped', 4),
973+
('over', 5),
974+
('a', 6),
975+
('lazy', 7),
976+
('dog', 8)]""")
977+
978+
def test_user_string(self):
979+
d = collections.UserString('')
980+
self.assertEqual(pprint.pformat(d, width=1), "''")
981+
d = collections.UserString('the quick brown fox jumped over a lazy dog')
982+
self.assertEqual(pprint.pformat(d, width=20),
983+
"""\
984+
('the quick brown '
985+
'fox jumped over '
986+
'a lazy dog')""")
987+
self.assertEqual(pprint.pformat({1: d}, width=20),
988+
"""\
989+
{1: 'the quick '
990+
'brown fox '
991+
'jumped over a '
992+
'lazy dog'}""")
993+
846994

847995
class DottedPrettyPrinter(pprint.PrettyPrinter):
848996

0 commit comments

Comments
 (0)