8000 gh-90117: handle dict and mapping views in pprint by devdanzin · Pull Request #30135 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-90117: handle dict and mapping views in pprint #30135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 45 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f7835ca
Teach pprint about dict views with PrettyPrinter._pprint_dict_view an…
devdanzin Dec 16, 2021
1eda2d5
Merge branch 'main' of https://github.com/python/cpython into pprint_…
devdanzin Dec 17, 2021
9500a74
Use _private names for _dict_*_view attributes of PrettyPrinter.
devdanzin Dec 17, 2021
653cdea
Use explicit 'items' keyword when calling _pprint_dict_view from _ppr…
devdanzin Dec 18, 2021
884f224
📜🤖 Added by blurb_it.
blurb-it[bot] Dec 18, 2021
48be1e9
Properly indent code.
devdanzin Jan 19, 2022
9745491
WIP: Improve tests and make short views sortable.
devdanzin Jan 19, 2022
7edb29d
fix typo
merwok Apr 24, 2022
7d2fa0f
Merge branch 'main' into pprint_dict_view
merwok Apr 24, 2022
32773ce
Merge branch 'main' into pprint_dict_view
arhadthedev Mar 4, 2023
15dd266
Address the failing Docs check
arhadthedev Mar 4, 2023
6898bc4
Merge branch 'python:main' into pprint_dict_view
devdanzin Apr 6, 2024
67e3f14
Add tests for collections.abc.[Keys|Items|Mapping|Values]View support…
devdanzin Apr 7, 2024
65e0be2
Add support for collections.abc.[Keys|Items|Mapping|Values]View in pp…
devdanzin Apr 7, 2024
c91af09
Split _pprint_dict_view into _pprint_abc_view, so pretty-printing nor…
devdanzin Apr 7, 2024
5b2341c
Simplify redundant code.
devdanzin Apr 7, 2024
a9ff3df
Add collections.abc views to some existing pprint tests.
devdanzin Apr 7, 2024
4c67166
Remove TODO.
devdanzin Apr 7, 2024
bfa9868
Test that views from collection.UserDict are correctly formatted by p…
devdanzin Apr 7, 2024
148b469
Handle recursive dict and ABC views.
devdanzin Apr 7, 2024
34abce7
Test that subclasses of ABC views work in pprint.
devdanzin Apr 7, 2024
09839a6
Test dict views coming from collections.Counter.
devdanzin Apr 7, 2024
091c3bb
Test ABC views coming from collections.ChainMap.
devdanzin Apr 7, 2024
29655a0
Test odict views coming from collections.OrderedDict.
devdanzin Apr 7, 2024
7ecb456
Merge branch 'main' into pprint_dict_view
devdanzin Apr 8, 2024
646816a
Rename _pprint_abc_view to _pprint_mapping_abc_view.
devdanzin Apr 8, 2024
7537a52
Add pprint test for mapping ABC views where ._mapping has a custom __…
devdanzin Apr 9, 2024
7a6769d
When a mapping ABC view has a ._mapping that defines a custom __repr_…
devdanzin Apr 9, 2024
7dcb9cf
Merge branch 'python:main' into pprint_dict_view
devdanzin Apr 9, 2024
06babe4
Merge remote-tracking branch 'refs/remotes/origin/pprint_dict_view' i…
devdanzin Apr 9, 2024
58692d2
Add tests for ABC mapping views subclasses that don't replace __repr_…
devdanzin Apr 21, 2024
8e605c1
Simplify the pretty printing of ABC mapping views.
devdanzin Apr 21, 2024
7e27e02
Merge branch 'python:main' into pprint_dict_view
devdanzin Apr 21, 2024
eb66934
Merge remote-tracking branch 'refs/remotes/origin/pprint_dict_view' i…
devdanzin Apr 21, 2024
1dc4ab2
Add a test for depth handling when pretty printing dict views.
devdanzin Apr 21, 2024
f267452
Fix checking whether the view type is a subclass of an items view, ad…
devdanzin Apr 22, 2024
3867338
Move construction of the views __repr__ set out of _safe_repr.
devdanzin Apr 26, 2024
1a609d0
Merge branch 'main' into pprint_dict_view
devdanzin Apr 26, 2024
bca6f6f
Merge remote-tracking branch 'refs/remotes/origin/pprint_dict_view' i…
devdanzin Apr 26, 2024
d020f86
Merge branch 'python:main' into pprint_dict_view
devdanzin May 21, 2024
ee7b521
Merge branch 'python:main' into pprint_dict_view
devdanzin May 30, 2024
7009887
Merge branch 'python:main' into pprint_dict_view
devdanzin Jul 1, 2024
9499115
Merge branch 'main' into pprint_dict_view
devdanzin Oct 29, 2024
692c0cd
Merge branch 'main' into pprint_dict_view
AA-Turner Apr 20, 2025
90e069c
Merge branch 'main' into pprint_dict_view
gpshead May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Teach pprint about dict views with PrettyPrinter._pprint_dict_view an…
…d ._pprint_dict_items_view.
  • Loading branch information
devdanzin committed Dec 16, 2021
< 8000 batch-deferred-content class="d-inline-block" data-url="/commits/badges">
commit f7835caceaebfa97c88bb5d4b58b11370c005b60
28 changes: 28 additions & 0 deletions Lib/pprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,34 @@ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level

_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict

def _pprint_dict_view(self, object, stream, indent, allowance, context, level, items=False):
key = _safe_tuple if items else _safe_key
write = stream.write
write(object.__class__.__name__ + '([')
if self._indent_per_level > 1:
write((self._indent_per_level - 1) * ' ')
length = len(object)
if length:
if self._sort_dicts:
entries = sorted(object, key=key)
else:
entries = object
self._format_items(entries, stream, indent, allowance + 1,
context, level)
write('])')

dict_keys_view = type({}.keys())
_dispatch[dict_keys_view.__repr__] = _pprint_dict_view

dict_values_view = type({}.values())
_dispatch[dict_values_view.__repr__] = _pprint_dict_view

def _pprint_dict_items_view(self, object, stream, indent, allowance, context, level):
self._pprint_dict_view(object, stream, indent, allowance, context, level, True)

dict_items_view = type({}.items())
_dispatch[dict_items_view.__repr__] = _pprint_dict_items_view

def _pprint_list(self, object, stream, indent, allowance, context, level):
stream.write('[')
self._format_items(object, stream, indent, allowance + 1,
Expand Down
58 changes: 58 additions & 0 deletions Lib/test/test_pprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ def test_same_as_repr(self):
set(), set2(), set3(),
frozenset(), frozenset2(), frozenset3(),
{}, dict2(), dict3(),
{}.keys(), {}.values(), {}.items(),
self.assertTrue, pprint,
-6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"),
(3,), [3], {3: 6},
Expand All @@ -240,6 +241,7 @@ def test_same_as_repr(self):
set({7}), set2({7}), set3({7}),
frozenset({8}), frozenset2({8}), frozenset3({8}),
dict2({5: 6}), dict3({5: 6}),
{5: 6}.keys(), {5: 6}.values(), {5: 6}.items(),
range(10, -11, -1),
True, False, None, ...,
):
Expand Down Expand Up @@ -296,6 +298,36 @@ def test_basic_line_wrap(self):
for type in [dict, dict2]:
self.assertEqual(pprint.pformat(type(o)), exp)

o = range(100)
exp = 'dict_keys([%s])' % ',\n '.join(map(str, o))
keys = dict.fromkeys(o).keys()
self.assertEqual(pprint.pformat(keys), exp)

o = range(100)
exp = 'dict_values([%s])' % ',\n '.join(map(str, o))
values = {v: v for v in o}.values()
self.assertEqual(pprint.pformat(values), exp)

o = range(100)
exp = 'dict_items([%s])' % ',\n '.join("(%s, %s)" % (i, i) for i in o)
items = {v: v for v in o}.items()
self.assertEqual(pprint.pformat(items), exp)

o = range(100)
exp = 'odict_keys([%s])' % ',\n '.join(map(str, o))
keys = collections.OrderedDict.fromkeys(o).keys()
self.assertEqual(pprint.pformat(keys), exp)

o = range(100)
exp = 'odict_values([%s])' % ',\n '.join(map(str, o))
values = collections.OrderedDict({v: v for v in o}).values()
self.assertEqual(pprint.pformat(values), exp)

o = range(100)
exp = 'odict_items([%s])' % ',\n '.join("(%s, %s)" % (i, i) for i in o)
items = collections.OrderedDict({v: v for v in o}).items()
self.assertEqual(pprint.pformat(items), exp)

o = range(100)
exp = '[%s]' % ',\n '.join(map(str, o))
for type in [list, list2]:
Expand Down Expand Up @@ -447,6 +479,28 @@ def test_mapping_proxy(self):
('lazy', 7),
('dog', 8)]))""")

def test_dict_views(self):
for dict_class in (dict, collections.OrderedDict):
empty = dict_class()
short = dict_class(zip('abcde', 'abcde'))
long = dict_class((chr(x), chr(x)) for x in range(65, 91))
prefix = "dict" if dict_class is dict else "odict"
for d in empty, short, long:
is_short = len(d) < 6
joiner = ", " if is_short else ",\n "
k = d.keys()
v = d.values()
i = d.items()
self.assertEqual(pprint.pformat(k, sort_dicts=True),
prefix + "_keys([%s])" %
joiner.join(repr(key) for key in sorted(k)))
self.assertEqual(pprint.pformat(v, sort_dicts=True),
prefix + "_values([%s])" %
joiner.join(repr(val) for val in sorted(v)))
self.assertEqual(pprint.pformat(i, sort_dicts=True),
prefix + "_items([%s])" %
joiner.join(repr(item) for item in sorted(i)))

def test_empty_simple_namespace(self):
ns = types.SimpleNamespace()
formatted = pprint.pformat(ns)
Expand Down Expand Up @@ -860,6 +914,10 @@ def test_sort_unorderable_values(self):
'frozenset({' + ','.join(map(repr, skeys)) + '})')
self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys))),
'{' + ','.join('%r:None' % k for k in skeys) + '}')
self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys).keys())),
'dict_keys([' + ','.join('%r' % k for k in skeys) + '])')
self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys).items())),
'dict_items([' + ','.join('(%r,None)' % k for k in skeys) + '])')

# Issue 10017: TypeError on user-defined types as dict keys.
self.assertEqual(pprint.pformat({Unorderable: 0, 1: 0}),
Expand Down
0