Skip to content

Commit 1b78f99

Browse files
committed
support named tuples
1 parent c066b4f commit 1b78f99

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

devtools/prettier.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ def __init__(self,
4040
(dict, self._format_dict),
4141
(str, self._format_str),
4242
(bytes, self._format_bytes),
43-
((tuple, list, set, frozenset), self._format_list_like),
43+
(tuple, self._format_tuples),
44+
((list, set, frozenset), self._format_list_like),
4445
(collections.Generator, self._format_generators),
4546
]
4647

@@ -95,6 +96,22 @@ def _format_list_like(self, value: Union[list, tuple, set], value_repr: str, ind
9596
self._stream.write(',\n')
9697
self._stream.write(indent_current * self._c + close_)
9798

99+
def _format_tuples(self, value: tuple, value_repr: str, indent_current: int, indent_new: int):
100+
fields = getattr(value, '_fields', None)
101+
if fields:
102+
# named tuple
103+
self._stream.write(value.__class__.__name__ + '(\n')
104+
for field, v in zip(fields, value):
105+
self._stream.write(indent_new * self._c)
106+
self._stream.write(field)
107+
self._stream.write('=')
108+
self._format(v, indent_new, False)
109+
self._stream.write(',\n')
110+
self._stream.write(indent_current * self._c + ')')
111+
else:
112+
# normal tuples are just like other similar iterables
113+
return self._format_list_like(value, value_repr, indent_current, indent_new)
114+
98115
def _format_str(self, value: str, value_repr: str, indent_current: int, indent_new: int):
99116
if self._repr_strings:
100117
self._stream.write(value_repr)

tests/test_prettier.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import string
22
from collections import OrderedDict
3+
from typing import Any, NamedTuple
34

45
import numpy
56

@@ -82,6 +83,19 @@ def test_generator():
8283
')')
8384

8485

86+
def test_named_tuple():
87+
class TestNT(NamedTuple):
88+
foo: str
89+
bar: str
90+
spam: int
91+
v = pformat(TestNT('x', 'y', 1))
92+
assert v == ("TestNT(\n"
93+
" foo='x',\n"
94+
" bar='y',\n"
95+
" spam=1,\n"
96+
")")
97+
98+
8599
def test_generator_no_yield():
86100
pformat_ = PrettyFormat(yield_from_generators=False)
87101
v = pformat_((i for i in range(3)))
@@ -158,3 +172,47 @@ def test_frozenset():
158172
1,
159173
2,
160174
})"""
175+
176+
177+
def test_deep_objects():
178+
class TestNT(NamedTuple):
179+
foo: str
180+
bar: str
181+
spam: Any
182+
v = pformat((
183+
{
184+
'a': TestNT('x', 'y', OrderedDict([(1, 2), (3, 4), (5, 6)])),
185+
'b': frozenset(range(3)),
186+
'c': [1, 2, {1: 2, 3: 4}]
187+
},
188+
{1, 2, 3}
189+
))
190+
print(v)
191+
assert v == """\
192+
(
193+
{
194+
'a': TestNT(
195+
foo='x',
196+
bar='y',
197+
spam=OrderedDict([
198+
(1, 2),
199+
(3, 4),
200+
(5, 6),
201+
]),
202+
),
203+
'b': frozenset({
204+
0,
205+
1,
206+
2,
207+
}),
208+
'c': [
209+
1,
210+
2,
211+
{
212+
1: 2,
213+
3: 4,
214+
},
215+
],
216+
},
217+
{1, 2, 3},
218+
)"""

0 commit comments

Comments
 (0)