1 # -*- coding: utf-8 -*-
2
3 import collections
4 import contextlib
5 import dataclasses
6 import io
7 import itertools
8 import pprint
9 import random
10 import test.support
11 import test.test_set
12 import types
13 import unittest
14
15 # list, tuple and dict subclasses that do or don't overwrite __repr__
16 class ESC[4;38;5;81mlist2(ESC[4;38;5;149mlist):
17 pass
18
19 class ESC[4;38;5;81mlist3(ESC[4;38;5;149mlist):
20 def __repr__(self):
21 return list.__repr__(self)
22
23 class ESC[4;38;5;81mlist_custom_repr(ESC[4;38;5;149mlist):
24 def __repr__(self):
25 return '*'*len(list.__repr__(self))
26
27 class ESC[4;38;5;81mtuple2(ESC[4;38;5;149mtuple):
28 pass
29
30 class ESC[4;38;5;81mtuple3(ESC[4;38;5;149mtuple):
31 def __repr__(self):
32 return tuple.__repr__(self)
33
34 class ESC[4;38;5;81mtuple_custom_repr(ESC[4;38;5;149mtuple):
35 def __repr__(self):
36 return '*'*len(tuple.__repr__(self))
37
38 class ESC[4;38;5;81mset2(ESC[4;38;5;149mset):
39 pass
40
41 class ESC[4;38;5;81mset3(ESC[4;38;5;149mset):
42 def __repr__(self):
43 return set.__repr__(self)
44
45 class ESC[4;38;5;81mset_custom_repr(ESC[4;38;5;149mset):
46 def __repr__(self):
47 return '*'*len(set.__repr__(self))
48
49 class ESC[4;38;5;81mfrozenset2(ESC[4;38;5;149mfrozenset):
50 pass
51
52 class ESC[4;38;5;81mfrozenset3(ESC[4;38;5;149mfrozenset):
53 def __repr__(self):
54 return frozenset.__repr__(self)
55
56 class ESC[4;38;5;81mfrozenset_custom_repr(ESC[4;38;5;149mfrozenset):
57 def __repr__(self):
58 return '*'*len(frozenset.__repr__(self))
59
60 class ESC[4;38;5;81mdict2(ESC[4;38;5;149mdict):
61 pass
62
63 class ESC[4;38;5;81mdict3(ESC[4;38;5;149mdict):
64 def __repr__(self):
65 return dict.__repr__(self)
66
67 class ESC[4;38;5;81mdict_custom_repr(ESC[4;38;5;149mdict):
68 def __repr__(self):
69 return '*'*len(dict.__repr__(self))
70
71 @dataclasses.dataclass
72 class ESC[4;38;5;81mdataclass1:
73 field1: str
74 field2: int
75 field3: bool = False
76 field4: int = dataclasses.field(default=1, repr=False)
77
78 @dataclasses.dataclass
79 class ESC[4;38;5;81mdataclass2:
80 a: int = 1
81 def __repr__(self):
82 return "custom repr that doesn't fit within pprint width"
83
84 @dataclasses.dataclass(repr=False)
85 class ESC[4;38;5;81mdataclass3:
86 a: int = 1
87
88 @dataclasses.dataclass
89 class ESC[4;38;5;81mdataclass4:
90 a: "dataclass4"
91 b: int = 1
92
93 @dataclasses.dataclass
94 class ESC[4;38;5;81mdataclass5:
95 a: "dataclass6"
96 b: int = 1
97
98 @dataclasses.dataclass
99 class ESC[4;38;5;81mdataclass6:
100 c: "dataclass5"
101 d: int = 1
102
103 class ESC[4;38;5;81mUnorderable:
104 def __repr__(self):
105 return str(id(self))
106
107 # Class Orderable is orderable with any type
108 class ESC[4;38;5;81mOrderable:
109 def __init__(self, hash):
110 self._hash = hash
111 def __lt__(self, other):
112 return False
113 def __gt__(self, other):
114 return self != other
115 def __le__(self, other):
116 return self == other
117 def __ge__(self, other):
118 return True
119 def __eq__(self, other):
120 return self is other
121 def __ne__(self, other):
122 return self is not other
123 def __hash__(self):
124 return self._hash
125
126 class ESC[4;38;5;81mQueryTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
127
128 def setUp(self):
129 self.a = list(range(100))
130 self.b = list(range(200))
131 self.a[-12] = self.b
132
133 def test_init(self):
134 pp = pprint.PrettyPrinter()
135 pp = pprint.PrettyPrinter(indent=4, width=40, depth=5,
136 stream=io.StringIO(), compact=True)
137 pp = pprint.PrettyPrinter(4, 40, 5, io.StringIO())
138 pp = pprint.PrettyPrinter(sort_dicts=False)
139 with self.assertRaises(TypeError):
140 pp = pprint.PrettyPrinter(4, 40, 5, io.StringIO(), True)
141 self.assertRaises(ValueError, pprint.PrettyPrinter, indent=-1)
142 self.assertRaises(ValueError, pprint.PrettyPrinter, depth=0)
143 self.assertRaises(ValueError, pprint.PrettyPrinter, depth=-1)
144 self.assertRaises(ValueError, pprint.PrettyPrinter, width=0)
145
146 def test_basic(self):
147 # Verify .isrecursive() and .isreadable() w/o recursion
148 pp = pprint.PrettyPrinter()
149 for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def",
150 bytearray(b"ghi"), True, False, None, ...,
151 self.a, self.b):
152 # module-level convenience functions
153 self.assertFalse(pprint.isrecursive(safe),
154 "expected not isrecursive for %r" % (safe,))
155 self.assertTrue(pprint.isreadable(safe),
156 "expected isreadable for %r" % (safe,))
157 # PrettyPrinter methods
158 self.assertFalse(pp.isrecursive(safe),
159 "expected not isrecursive for %r" % (safe,))
160 self.assertTrue(pp.isreadable(safe),
161 "expected isreadable for %r" % (safe,))
162
163 def test_stdout_is_None(self):
164 with contextlib.redirect_stdout(None):
165 # smoke test - there is no output to check
166 value = 'this should not fail'
167 pprint.pprint(value)
168 pprint.PrettyPrinter().pprint(value)
169
170 def test_knotted(self):
171 # Verify .isrecursive() and .isreadable() w/ recursion
172 # Tie a knot.
173 self.b[67] = self.a
174 # Messy dict.
175 self.d = {}
176 self.d[0] = self.d[1] = self.d[2] = self.d
177
178 pp = pprint.PrettyPrinter()
179
180 for icky in self.a, self.b, self.d, (self.d, self.d):
181 self.assertTrue(pprint.isrecursive(icky), "expected isrecursive")
182 self.assertFalse(pprint.isreadable(icky), "expected not isreadable")
183 self.assertTrue(pp.isrecursive(icky), "expected isrecursive")
184 self.assertFalse(pp.isreadable(icky), "expected not isreadable")
185
186 # Break the cycles.
187 self.d.clear()
188 del self.a[:]
189 del self.b[:]
190
191 for safe in self.a, self.b, self.d, (self.d, self.d):
192 # module-level convenience functions
193 self.assertFalse(pprint.isrecursive(safe),
194 "expected not isrecursive for %r" % (safe,))
195 self.assertTrue(pprint.isreadable(safe),
196 "expected isreadable for %r" % (safe,))
197 # PrettyPrinter methods
198 self.assertFalse(pp.isrecursive(safe),
199 "expected not isrecursive for %r" % (safe,))
200 self.assertTrue(pp.isreadable(safe),
201 "expected isreadable for %r" % (safe,))
202
203 def test_unreadable(self):
204 # Not recursive but not readable anyway
205 pp = pprint.PrettyPrinter()
206 for unreadable in object(), int, pprint, pprint.isrecursive:
207 # module-level convenience functions
208 self.assertFalse(pprint.isrecursive(unreadable),
209 "expected not isrecursive for %r" % (unreadable,))
210 self.assertFalse(pprint.isreadable(unreadable),
211 "expected not isreadable for %r" % (unreadable,))
212 # PrettyPrinter methods
213 self.assertFalse(pp.isrecursive(unreadable),
214 "expected not isrecursive for %r" % (unreadable,))
215 self.assertFalse(pp.isreadable(unreadable),
216 "expected not isreadable for %r" % (unreadable,))
217
218 def test_same_as_repr(self):
219 # Simple objects, small containers and classes that override __repr__
220 # to directly call super's __repr__.
221 # For those the result should be the same as repr().
222 # Ahem. The docs don't say anything about that -- this appears to
223 # be testing an implementation quirk. Starting in Python 2.5, it's
224 # not true for dicts: pprint always sorts dicts by key now; before,
225 # it sorted a dict display if and only if the display required
226 # multiple lines. For that reason, dicts with more than one element
227 # aren't tested here.
228 for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(),
229 (), tuple2(), tuple3(),
230 [], list2(), list3(),
231 set(), set2(), set3(),
232 frozenset(), frozenset2(), frozenset3(),
233 {}, dict2(), dict3(),
234 self.assertTrue, pprint,
235 -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"),
236 (3,), [3], {3: 6},
237 (1,2), [3,4], {5: 6},
238 tuple2((1,2)), tuple3((1,2)), tuple3(range(100)),
239 [3,4], list2([3,4]), list3([3,4]), list3(range(100)),
240 set({7}), set2({7}), set3({7}),
241 frozenset({8}), frozenset2({8}), frozenset3({8}),
242 dict2({5: 6}), dict3({5: 6}),
243 range(10, -11, -1),
244 True, False, None, ...,
245 ):
246 native = repr(simple)
247 self.assertEqual(pprint.pformat(simple), native)
248 self.assertEqual(pprint.pformat(simple, width=1, indent=0)
249 .replace('\n', ' '), native)
250 self.assertEqual(pprint.pformat(simple, underscore_numbers=True), native)
251 self.assertEqual(pprint.saferepr(simple), native)
252
253 def test_container_repr_override_called(self):
254 N = 1000
255 # Ensure that __repr__ override is called for subclasses of containers
256
257 for cont in (list_custom_repr(),
258 list_custom_repr([1,2,3]),
259 list_custom_repr(range(N)),
260 tuple_custom_repr(),
261 tuple_custom_repr([1,2,3]),
262 tuple_custom_repr(range(N)),
263 set_custom_repr(),
264 set_custom_repr([1,2,3]),
265 set_custom_repr(range(N)),
266 frozenset_custom_repr(),
267 frozenset_custom_repr([1,2,3]),
268 frozenset_custom_repr(range(N)),
269 dict_custom_repr(),
270 dict_custom_repr({5: 6}),
271 dict_custom_repr(zip(range(N),range(N))),
272 ):
273 native = repr(cont)
274 expected = '*' * len(native)
275 self.assertEqual(pprint.pformat(cont), expected)
276 self.assertEqual(pprint.pformat(cont, width=1, indent=0), expected)
277 self.assertEqual(pprint.saferepr(cont), expected)
278
279 def test_basic_line_wrap(self):
280 # verify basic line-wrapping operation
281 o = {'RPM_cal': 0,
282 'RPM_cal2': 48059,
283 'Speed_cal': 0,
284 'controldesk_runtime_us': 0,
285 'main_code_runtime_us': 0,
286 'read_io_runtime_us': 0,
287 'write_io_runtime_us': 43690}
288 exp = """\
289 {'RPM_cal': 0,
290 'RPM_cal2': 48059,
291 'Speed_cal': 0,
292 'controldesk_runtime_us': 0,
293 'main_code_runtime_us': 0,
294 'read_io_runtime_us': 0,
295 'write_io_runtime_us': 43690}"""
296 for type in [dict, dict2]:
297 self.assertEqual(pprint.pformat(type(o)), exp)
298
299 o = range(100)
300 exp = '[%s]' % ',\n '.join(map(str, o))
301 for type in [list, list2]:
302 self.assertEqual(pprint.pformat(type(o)), exp)
303
304 o = tuple(range(100))
305 exp = '(%s)' % ',\n '.join(map(str, o))
306 for type in [tuple, tuple2]:
307 self.assertEqual(pprint.pformat(type(o)), exp)
308
309 # indent parameter
310 o = range(100)
311 exp = '[ %s]' % ',\n '.join(map(str, o))
312 for type in [list, list2]:
313 self.assertEqual(pprint.pformat(type(o), indent=4), exp)
314
315 def test_nested_indentations(self):
316 o1 = list(range(10))
317 o2 = dict(first=1, second=2, third=3)
318 o = [o1, o2]
319 expected = """\
320 [ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
321 {'first': 1, 'second': 2, 'third': 3}]"""
322 self.assertEqual(pprint.pformat(o, indent=4, width=42), expected)
323 expected = """\
324 [ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
325 { 'first': 1,
326 'second': 2,
327 'third': 3}]"""
328 self.assertEqual(pprint.pformat(o, indent=4, width=41), expected)
329
330 def test_width(self):
331 expected = """\
332 [[[[[[1, 2, 3],
333 '1 2']]]],
334 {1: [1, 2, 3],
335 2: [12, 34]},
336 'abc def ghi',
337 ('ab cd ef',),
338 set2({1, 23}),
339 [[[[[1, 2, 3],
340 '1 2']]]]]"""
341 o = eval(expected)
342 self.assertEqual(pprint.pformat(o, width=15), expected)
343 self.assertEqual(pprint.pformat(o, width=16), expected)
344 self.assertEqual(pprint.pformat(o, width=25), expected)
345 self.assertEqual(pprint.pformat(o, width=14), """\
346 [[[[[[1,
347 2,
348 3],
349 '1 '
350 '2']]]],
351 {1: [1,
352 2,
353 3],
354 2: [12,
355 34]},
356 'abc def '
357 'ghi',
358 ('ab cd '
359 'ef',),
360 set2({1,
361 23}),
362 [[[[[1,
363 2,
364 3],
365 '1 '
366 '2']]]]]""")
367
368 def test_integer(self):
369 self.assertEqual(pprint.pformat(1234567), '1234567')
370 self.assertEqual(pprint.pformat(1234567, underscore_numbers=True), '1_234_567')
371
372 class ESC[4;38;5;81mTemperature(ESC[4;38;5;149mint):
373 def __new__(cls, celsius_degrees):
374 return super().__new__(Temperature, celsius_degrees)
375 def __repr__(self):
376 kelvin_degrees = self + 273.15
377 return f"{kelvin_degrees}°K"
378 self.assertEqual(pprint.pformat(Temperature(1000)), '1273.15°K')
379
380 def test_sorted_dict(self):
381 # Starting in Python 2.5, pprint sorts dict displays by key regardless
382 # of how small the dictionary may be.
383 # Before the change, on 32-bit Windows pformat() gave order
384 # 'a', 'c', 'b' here, so this test failed.
385 d = {'a': 1, 'b': 1, 'c': 1}
386 self.assertEqual(pprint.pformat(d), "{'a': 1, 'b': 1, 'c': 1}")
387 self.assertEqual(pprint.pformat([d, d]),
388 "[{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 1, 'c': 1}]")
389
390 # The next one is kind of goofy. The sorted order depends on the
391 # alphabetic order of type names: "int" < "str" < "tuple". Before
392 # Python 2.5, this was in the test_same_as_repr() test. It's worth
393 # keeping around for now because it's one of few tests of pprint
394 # against a crazy mix of types.
395 self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}),
396 r"{5: [[]], 'xy\tab\n': (3,), (): {}}")
397
398 def test_sort_dict(self):
399 d = dict.fromkeys('cba')
400 self.assertEqual(pprint.pformat(d, sort_dicts=False), "{'c': None, 'b': None, 'a': None}")
401 self.assertEqual(pprint.pformat([d, d], sort_dicts=False),
402 "[{'c': None, 'b': None, 'a': None}, {'c': None, 'b': None, 'a': None}]")
403
404 def test_ordered_dict(self):
405 d = collections.OrderedDict()
406 self.assertEqual(pprint.pformat(d, width=1), 'OrderedDict()')
407 d = collections.OrderedDict([])
408 self.assertEqual(pprint.pformat(d, width=1), 'OrderedDict()')
409 words = 'the quick brown fox jumped over a lazy dog'.split()
410 d = collections.OrderedDict(zip(words, itertools.count()))
411 self.assertEqual(pprint.pformat(d),
412 """\
413 OrderedDict([('the', 0),
414 ('quick', 1),
415 ('brown', 2),
416 ('fox', 3),
417 ('jumped', 4),
418 ('over', 5),
419 ('a', 6),
420 ('lazy', 7),
421 ('dog', 8)])""")
422
423 def test_mapping_proxy(self):
424 words = 'the quick brown fox jumped over a lazy dog'.split()
425 d = dict(zip(words, itertools.count()))
426 m = types.MappingProxyType(d)
427 self.assertEqual(pprint.pformat(m), """\
428 mappingproxy({'a': 6,
429 'brown': 2,
430 'dog': 8,
431 'fox': 3,
432 'jumped': 4,
433 'lazy': 7,
434 'over': 5,
435 'quick': 1,
436 'the': 0})""")
437 d = collections.OrderedDict(zip(words, itertools.count()))
438 m = types.MappingProxyType(d)
439 self.assertEqual(pprint.pformat(m), """\
440 mappingproxy(OrderedDict([('the', 0),
441 ('quick', 1),
442 ('brown', 2),
443 ('fox', 3),
444 ('jumped', 4),
445 ('over', 5),
446 ('a', 6),
447 ('lazy', 7),
448 ('dog', 8)]))""")
449
450 def test_empty_simple_namespace(self):
451 ns = types.SimpleNamespace()
452 formatted = pprint.pformat(ns)
453 self.assertEqual(formatted, "namespace()")
454
455 def test_small_simple_namespace(self):
456 ns = types.SimpleNamespace(a=1, b=2)
457 formatted = pprint.pformat(ns)
458 self.assertEqual(formatted, "namespace(a=1, b=2)")
459
460 def test_simple_namespace(self):
461 ns = types.SimpleNamespace(
462 the=0,
463 quick=1,
464 brown=2,
465 fox=3,
466 jumped=4,
467 over=5,
468 a=6,
469 lazy=7,
470 dog=8,
471 )
472 formatted = pprint.pformat(ns, width=60, indent=4)
473 self.assertEqual(formatted, """\
474 namespace(the=0,
475 quick=1,
476 brown=2,
477 fox=3,
478 jumped=4,
479 over=5,
480 a=6,
481 lazy=7,
482 dog=8)""")
483
484 def test_simple_namespace_subclass(self):
485 class ESC[4;38;5;81mAdvancedNamespace(ESC[4;38;5;149mtypesESC[4;38;5;149m.ESC[4;38;5;149mSimpleNamespace): pass
486 ns = AdvancedNamespace(
487 the=0,
488 quick=1,
489 brown=2,
490 fox=3,
491 jumped=4,
492 over=5,
493 a=6,
494 lazy=7,
495 dog=8,
496 )
497 formatted = pprint.pformat(ns, width=60)
498 self.assertEqual(formatted, """\
499 AdvancedNamespace(the=0,
500 quick=1,
501 brown=2,
502 fox=3,
503 jumped=4,
504 over=5,
505 a=6,
506 lazy=7,
507 dog=8)""")
508
509 def test_empty_dataclass(self):
510 dc = dataclasses.make_dataclass("MyDataclass", ())()
511 formatted = pprint.pformat(dc)
512 self.assertEqual(formatted, "MyDataclass()")
513
514 def test_small_dataclass(self):
515 dc = dataclass1("text", 123)
516 formatted = pprint.pformat(dc)
517 self.assertEqual(formatted, "dataclass1(field1='text', field2=123, field3=False)")
518
519 def test_larger_dataclass(self):
520 dc = dataclass1("some fairly long text", int(1e10), True)
521 formatted = pprint.pformat([dc, dc], width=60, indent=4)
522 self.assertEqual(formatted, """\
523 [ dataclass1(field1='some fairly long text',
524 field2=10000000000,
525 field3=True),
526 dataclass1(field1='some fairly long text',
527 field2=10000000000,
528 field3=True)]""")
529
530 def test_dataclass_with_repr(self):
531 dc = dataclass2()
532 formatted = pprint.pformat(dc, width=20)
533 self.assertEqual(formatted, "custom repr that doesn't fit within pprint width")
534
535 def test_dataclass_no_repr(self):
536 dc = dataclass3()
537 formatted = pprint.pformat(dc, width=10)
538 self.assertRegex(formatted, r"<test.test_pprint.dataclass3 object at \w+>")
539
540 def test_recursive_dataclass(self):
541 dc = dataclass4(None)
542 dc.a = dc
543 formatted = pprint.pformat(dc, width=10)
544 self.assertEqual(formatted, """\
545 dataclass4(a=...,
546 b=1)""")
547
548 def test_cyclic_dataclass(self):
549 dc5 = dataclass5(None)
550 dc6 = dataclass6(None)
551 dc5.a = dc6
552 dc6.c = dc5
553 formatted = pprint.pformat(dc5, width=10)
554 self.assertEqual(formatted, """\
555 dataclass5(a=dataclass6(c=...,
556 d=1),
557 b=1)""")
558
559 def test_subclassing(self):
560 # length(repr(obj)) > width
561 o = {'names with spaces': 'should be presented using repr()',
562 'others.should.not.be': 'like.this'}
563 exp = """\
564 {'names with spaces': 'should be presented using repr()',
565 others.should.not.be: like.this}"""
566
567 dotted_printer = DottedPrettyPrinter()
568 self.assertEqual(dotted_printer.pformat(o), exp)
569
570 # length(repr(obj)) < width
571 o1 = ['with space']
572 exp1 = "['with space']"
573 self.assertEqual(dotted_printer.pformat(o1), exp1)
574 o2 = ['without.space']
575 exp2 = "[without.space]"
576 self.assertEqual(dotted_printer.pformat(o2), exp2)
577
578 def test_set_reprs(self):
579 self.assertEqual(pprint.pformat(set()), 'set()')
580 self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}')
581 self.assertEqual(pprint.pformat(set(range(7)), width=20), '''\
582 {0,
583 1,
584 2,
585 3,
586 4,
587 5,
588 6}''')
589 self.assertEqual(pprint.pformat(set2(range(7)), width=20), '''\
590 set2({0,
591 1,
592 2,
593 3,
594 4,
595 5,
596 6})''')
597 self.assertEqual(pprint.pformat(set3(range(7)), width=20),
598 'set3({0, 1, 2, 3, 4, 5, 6})')
599
600 self.assertEqual(pprint.pformat(frozenset()), 'frozenset()')
601 self.assertEqual(pprint.pformat(frozenset(range(3))),
602 'frozenset({0, 1, 2})')
603 self.assertEqual(pprint.pformat(frozenset(range(7)), width=20), '''\
604 frozenset({0,
605 1,
606 2,
607 3,
608 4,
609 5,
610 6})''')
611 self.assertEqual(pprint.pformat(frozenset2(range(7)), width=20), '''\
612 frozenset2({0,
613 1,
614 2,
615 3,
616 4,
617 5,
618 6})''')
619 self.assertEqual(pprint.pformat(frozenset3(range(7)), width=20),
620 'frozenset3({0, 1, 2, 3, 4, 5, 6})')
621
622 @unittest.expectedFailure
623 #See http://bugs.python.org/issue13907
624 @test.support.cpython_only
625 def test_set_of_sets_reprs(self):
626 # This test creates a complex arrangement of frozensets and
627 # compares the pretty-printed repr against a string hard-coded in
628 # the test. The hard-coded repr depends on the sort order of
629 # frozensets.
630 #
631 # However, as the docs point out: "Since sets only define
632 # partial ordering (subset relationships), the output of the
633 # list.sort() method is undefined for lists of sets."
634 #
635 # In a nutshell, the test assumes frozenset({0}) will always
636 # sort before frozenset({1}), but:
637 #
638 # >>> frozenset({0}) < frozenset({1})
639 # False
640 # >>> frozenset({1}) < frozenset({0})
641 # False
642 #
643 # Consequently, this test is fragile and
644 # implementation-dependent. Small changes to Python's sort
645 # algorithm cause the test to fail when it should pass.
646 # XXX Or changes to the dictionary implementation...
647
648 cube_repr_tgt = """\
649 {frozenset(): frozenset({frozenset({2}), frozenset({0}), frozenset({1})}),
650 frozenset({0}): frozenset({frozenset(),
651 frozenset({0, 2}),
652 frozenset({0, 1})}),
653 frozenset({1}): frozenset({frozenset(),
654 frozenset({1, 2}),
655 frozenset({0, 1})}),
656 frozenset({2}): frozenset({frozenset(),
657 frozenset({1, 2}),
658 frozenset({0, 2})}),
659 frozenset({1, 2}): frozenset({frozenset({2}),
660 frozenset({1}),
661 frozenset({0, 1, 2})}),
662 frozenset({0, 2}): frozenset({frozenset({2}),
663 frozenset({0}),
664 frozenset({0, 1, 2})}),
665 frozenset({0, 1}): frozenset({frozenset({0}),
666 frozenset({1}),
667 frozenset({0, 1, 2})}),
668 frozenset({0, 1, 2}): frozenset({frozenset({1, 2}),
669 frozenset({0, 2}),
670 frozenset({0, 1})})}"""
671 cube = test.test_set.cube(3)
672 self.assertEqual(pprint.pformat(cube), cube_repr_tgt)
673 cubo_repr_tgt = """\
674 {frozenset({frozenset({0, 2}), frozenset({0})}): frozenset({frozenset({frozenset({0,
675 2}),
676 frozenset({0,
677 1,
678 2})}),
679 frozenset({frozenset({0}),
680 frozenset({0,
681 1})}),
682 frozenset({frozenset(),
683 frozenset({0})}),
684 frozenset({frozenset({2}),
685 frozenset({0,
686 2})})}),
687 frozenset({frozenset({0, 1}), frozenset({1})}): frozenset({frozenset({frozenset({0,
688 1}),
689 frozenset({0,
690 1,
691 2})}),
692 frozenset({frozenset({0}),
693 frozenset({0,
694 1})}),
695 frozenset({frozenset({1}),
696 frozenset({1,
697 2})}),
698 frozenset({frozenset(),
699 frozenset({1})})}),
700 frozenset({frozenset({1, 2}), frozenset({1})}): frozenset({frozenset({frozenset({1,
701 2}),
702 frozenset({0,
703 1,
704 2})}),
705 frozenset({frozenset({2}),
706 frozenset({1,
707 2})}),
708 frozenset({frozenset(),
709 frozenset({1})}),
710 frozenset({frozenset({1}),
711 frozenset({0,
712 1})})}),
713 frozenset({frozenset({1, 2}), frozenset({2})}): frozenset({frozenset({frozenset({1,
714 2}),
715 frozenset({0,
716 1,
717 2})}),
718 frozenset({frozenset({1}),
719 frozenset({1,
720 2})}),
721 frozenset({frozenset({2}),
722 frozenset({0,
723 2})}),
724 frozenset({frozenset(),
725 frozenset({2})})}),
726 frozenset({frozenset(), frozenset({0})}): frozenset({frozenset({frozenset({0}),
727 frozenset({0,
728 1})}),
729 frozenset({frozenset({0}),
730 frozenset({0,
731 2})}),
732 frozenset({frozenset(),
733 frozenset({1})}),
734 frozenset({frozenset(),
735 frozenset({2})})}),
736 frozenset({frozenset(), frozenset({1})}): frozenset({frozenset({frozenset(),
737 frozenset({0})}),
738 frozenset({frozenset({1}),
739 frozenset({1,
740 2})}),
741 frozenset({frozenset(),
742 frozenset({2})}),
743 frozenset({frozenset({1}),
744 frozenset({0,
745 1})})}),
746 frozenset({frozenset({2}), frozenset()}): frozenset({frozenset({frozenset({2}),
747 frozenset({1,
748 2})}),
749 frozenset({frozenset(),
750 frozenset({0})}),
751 frozenset({frozenset(),
752 frozenset({1})}),
753 frozenset({frozenset({2}),
754 frozenset({0,
755 2})})}),
756 frozenset({frozenset({0, 1, 2}), frozenset({0, 1})}): frozenset({frozenset({frozenset({1,
757 2}),
758 frozenset({0,
759 1,
760 2})}),
761 frozenset({frozenset({0,
762 2}),
763 frozenset({0,
764 1,
765 2})}),
766 frozenset({frozenset({0}),
767 frozenset({0,
768 1})}),
769 frozenset({frozenset({1}),
770 frozenset({0,
771 1})})}),
772 frozenset({frozenset({0}), frozenset({0, 1})}): frozenset({frozenset({frozenset(),
773 frozenset({0})}),
774 frozenset({frozenset({0,
775 1}),
776 frozenset({0,
777 1,
778 2})}),
779 frozenset({frozenset({0}),
780 frozenset({0,
781 2})}),
782 frozenset({frozenset({1}),
783 frozenset({0,
784 1})})}),
785 frozenset({frozenset({2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({0,
786 2}),
787 frozenset({0,
788 1,
789 2})}),
790 frozenset({frozenset({2}),
791 frozenset({1,
792 2})}),
793 frozenset({frozenset({0}),
794 frozenset({0,
795 2})}),
796 frozenset({frozenset(),
797 frozenset({2})})}),
798 frozenset({frozenset({0, 1, 2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({1,
799 2}),
800 frozenset({0,
801 1,
802 2})}),
803 frozenset({frozenset({0,
804 1}),
805 frozenset({0,
806 1,
807 2})}),
808 frozenset({frozenset({0}),
809 frozenset({0,
810 2})}),
811 frozenset({frozenset({2}),
812 frozenset({0,
813 2})})}),
814 frozenset({frozenset({1, 2}), frozenset({0, 1, 2})}): frozenset({frozenset({frozenset({0,
815 2}),
816 frozenset({0,
817 1,
818 2})}),
819 frozenset({frozenset({0,
820 1}),
821 frozenset({0,
822 1,
823 2})}),
824 frozenset({frozenset({2}),
825 frozenset({1,
826 2})}),
827 frozenset({frozenset({1}),
828 frozenset({1,
829 2})})})}"""
830
831 cubo = test.test_set.linegraph(cube)
832 self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt)
833
834 def test_depth(self):
835 nested_tuple = (1, (2, (3, (4, (5, 6)))))
836 nested_dict = {1: {2: {3: {4: {5: {6: 6}}}}}}
837 nested_list = [1, [2, [3, [4, [5, [6, []]]]]]]
838 self.assertEqual(pprint.pformat(nested_tuple), repr(nested_tuple))
839 self.assertEqual(pprint.pformat(nested_dict), repr(nested_dict))
840 self.assertEqual(pprint.pformat(nested_list), repr(nested_list))
841
842 lv1_tuple = '(1, (...))'
843 lv1_dict = '{1: {...}}'
844 lv1_list = '[1, [...]]'
845 self.assertEqual(pprint.pformat(nested_tuple, depth=1), lv1_tuple)
846 self.assertEqual(pprint.pformat(nested_dict, depth=1), lv1_dict)
847 self.assertEqual(pprint.pformat(nested_list, depth=1), lv1_list)
848
849 def test_sort_unorderable_values(self):
850 # Issue 3976: sorted pprints fail for unorderable values.
851 n = 20
852 keys = [Unorderable() for i in range(n)]
853 random.shuffle(keys)
854 skeys = sorted(keys, key=id)
855 clean = lambda s: s.replace(' ', '').replace('\n','')
856
857 self.assertEqual(clean(pprint.pformat(set(keys))),
858 '{' + ','.join(map(repr, skeys)) + '}')
859 self.assertEqual(clean(pprint.pformat(frozenset(keys))),
860 'frozenset({' + ','.join(map(repr, skeys)) + '})')
861 self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys))),
862 '{' + ','.join('%r:None' % k for k in skeys) + '}')
863
864 # Issue 10017: TypeError on user-defined types as dict keys.
865 self.assertEqual(pprint.pformat({Unorderable: 0, 1: 0}),
866 '{1: 0, ' + repr(Unorderable) +': 0}')
867
868 # Issue 14998: TypeError on tuples with NoneTypes as dict keys.
869 keys = [(1,), (None,)]
870 self.assertEqual(pprint.pformat(dict.fromkeys(keys, 0)),
871 '{%r: 0, %r: 0}' % tuple(sorted(keys, key=id)))
872
873 def test_sort_orderable_and_unorderable_values(self):
874 # Issue 22721: sorted pprints is not stable
875 a = Unorderable()
876 b = Orderable(hash(a)) # should have the same hash value
877 # self-test
878 self.assertLess(a, b)
879 self.assertLess(str(type(b)), str(type(a)))
880 self.assertEqual(sorted([b, a]), [a, b])
881 self.assertEqual(sorted([a, b]), [a, b])
882 # set
883 self.assertEqual(pprint.pformat(set([b, a]), width=1),
884 '{%r,\n %r}' % (a, b))
885 self.assertEqual(pprint.pformat(set([a, b]), width=1),
886 '{%r,\n %r}' % (a, b))
887 # dict
888 self.assertEqual(pprint.pformat(dict.fromkeys([b, a]), width=1),
889 '{%r: None,\n %r: None}' % (a, b))
890 self.assertEqual(pprint.pformat(dict.fromkeys([a, b]), width=1),
891 '{%r: None,\n %r: None}' % (a, b))
892
893 def test_str_wrap(self):
894 # pprint tries to wrap strings intelligently
895 fox = 'the quick brown fox jumped over a lazy dog'
896 self.assertEqual(pprint.pformat(fox, width=19), """\
897 ('the quick brown '
898 'fox jumped over '
899 'a lazy dog')""")
900 self.assertEqual(pprint.pformat({'a': 1, 'b': fox, 'c': 2},
901 width=25), """\
902 {'a': 1,
903 'b': 'the quick brown '
904 'fox jumped over '
905 'a lazy dog',
906 'c': 2}""")
907 # With some special characters
908 # - \n always triggers a new line in the pprint
909 # - \t and \n are escaped
910 # - non-ASCII is allowed
911 # - an apostrophe doesn't disrupt the pprint
912 special = "Portons dix bons \"whiskys\"\nà l'avocat goujat\t qui fumait au zoo"
913 self.assertEqual(pprint.pformat(special, width=68), repr(special))
914 self.assertEqual(pprint.pformat(special, width=31), """\
915 ('Portons dix bons "whiskys"\\n'
916 "Ã l'avocat goujat\\t qui "
917 'fumait au zoo')""")
918 self.assertEqual(pprint.pformat(special, width=20), """\
919 ('Portons dix bons '
920 '"whiskys"\\n'
921 "Ã l'avocat "
922 'goujat\\t qui '
923 'fumait au zoo')""")
924 self.assertEqual(pprint.pformat([[[[[special]]]]], width=35), """\
925 [[[[['Portons dix bons "whiskys"\\n'
926 "Ã l'avocat goujat\\t qui "
927 'fumait au zoo']]]]]""")
928 self.assertEqual(pprint.pformat([[[[[special]]]]], width=25), """\
929 [[[[['Portons dix bons '
930 '"whiskys"\\n'
931 "Ã l'avocat "
932 'goujat\\t qui '
933 'fumait au zoo']]]]]""")
934 self.assertEqual(pprint.pformat([[[[[special]]]]], width=23), """\
935 [[[[['Portons dix '
936 'bons "whiskys"\\n'
937 "Ã l'avocat "
938 'goujat\\t qui '
939 'fumait au '
940 'zoo']]]]]""")
941 # An unwrappable string is formatted as its repr
942 unwrappable = "x" * 100
943 self.assertEqual(pprint.pformat(unwrappable, width=80), repr(unwrappable))
944 self.assertEqual(pprint.pformat(''), "''")
945 # Check that the pprint is a usable repr
946 special *= 10
947 for width in range(3, 40):
948 formatted = pprint.pformat(special, width=width)
949 self.assertEqual(eval(formatted), special)
950 formatted = pprint.pformat([special] * 2, width=width)
951 self.assertEqual(eval(formatted), [special] * 2)
952
953 def test_compact(self):
954 o = ([list(range(i * i)) for i in range(5)] +
955 [list(range(i)) for i in range(6)])
956 expected = """\
957 [[], [0], [0, 1, 2, 3],
958 [0, 1, 2, 3, 4, 5, 6, 7, 8],
959 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
960 14, 15],
961 [], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3],
962 [0, 1, 2, 3, 4]]"""
963 self.assertEqual(pprint.pformat(o, width=47, compact=True), expected)
964
965 def test_compact_width(self):
966 levels = 20
967 number = 10
968 o = [0] * number
969 for i in range(levels - 1):
970 o = [o]
971 for w in range(levels * 2 + 1, levels + 3 * number - 1):
972 lines = pprint.pformat(o, width=w, compact=True).splitlines()
973 maxwidth = max(map(len, lines))
974 self.assertLessEqual(maxwidth, w)
975 self.assertGreater(maxwidth, w - 3)
976
977 def test_bytes_wrap(self):
978 self.assertEqual(pprint.pformat(b'', width=1), "b''")
979 self.assertEqual(pprint.pformat(b'abcd', width=1), "b'abcd'")
980 letters = b'abcdefghijklmnopqrstuvwxyz'
981 self.assertEqual(pprint.pformat(letters, width=29), repr(letters))
982 self.assertEqual(pprint.pformat(letters, width=19), """\
983 (b'abcdefghijkl'
984 b'mnopqrstuvwxyz')""")
985 self.assertEqual(pprint.pformat(letters, width=18), """\
986 (b'abcdefghijkl'
987 b'mnopqrstuvwx'
988 b'yz')""")
989 self.assertEqual(pprint.pformat(letters, width=16), """\
990 (b'abcdefghijkl'
991 b'mnopqrstuvwx'
992 b'yz')""")
993 special = bytes(range(16))
994 self.assertEqual(pprint.pformat(special, width=61), repr(special))
995 self.assertEqual(pprint.pformat(special, width=48), """\
996 (b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
997 b'\\x0c\\r\\x0e\\x0f')""")
998 self.assertEqual(pprint.pformat(special, width=32), """\
999 (b'\\x00\\x01\\x02\\x03'
1000 b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
1001 b'\\x0c\\r\\x0e\\x0f')""")
1002 self.assertEqual(pprint.pformat(special, width=1), """\
1003 (b'\\x00\\x01\\x02\\x03'
1004 b'\\x04\\x05\\x06\\x07'
1005 b'\\x08\\t\\n\\x0b'
1006 b'\\x0c\\r\\x0e\\x0f')""")
1007 self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
1008 width=21), """\
1009 {'a': 1,
1010 'b': b'abcdefghijkl'
1011 b'mnopqrstuvwx'
1012 b'yz',
1013 'c': 2}""")
1014 self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
1015 width=20), """\
1016 {'a': 1,
1017 'b': b'abcdefgh'
1018 b'ijklmnop'
1019 b'qrstuvwxyz',
1020 'c': 2}""")
1021 self.assertEqual(pprint.pformat([[[[[[letters]]]]]], width=25), """\
1022 [[[[[[b'abcdefghijklmnop'
1023 b'qrstuvwxyz']]]]]]""")
1024 self.assertEqual(pprint.pformat([[[[[[special]]]]]], width=41), """\
1025 [[[[[[b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
1026 b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f']]]]]]""")
1027 # Check that the pprint is a usable repr
1028 for width in range(1, 64):
1029 formatted = pprint.pformat(special, width=width)
1030 self.assertEqual(eval(formatted), special)
1031 formatted = pprint.pformat([special] * 2, width=width)
1032 self.assertEqual(eval(formatted), [special] * 2)
1033
1034 def test_bytearray_wrap(self):
1035 self.assertEqual(pprint.pformat(bytearray(), width=1), "bytearray(b'')")
1036 letters = bytearray(b'abcdefghijklmnopqrstuvwxyz')
1037 self.assertEqual(pprint.pformat(letters, width=40), repr(letters))
1038 self.assertEqual(pprint.pformat(letters, width=28), """\
1039 bytearray(b'abcdefghijkl'
1040 b'mnopqrstuvwxyz')""")
1041 self.assertEqual(pprint.pformat(letters, width=27), """\
1042 bytearray(b'abcdefghijkl'
1043 b'mnopqrstuvwx'
1044 b'yz')""")
1045 self.assertEqual(pprint.pformat(letters, width=25), """\
1046 bytearray(b'abcdefghijkl'
1047 b'mnopqrstuvwx'
1048 b'yz')""")
1049 special = bytearray(range(16))
1050 self.assertEqual(pprint.pformat(special, width=72), repr(special))
1051 self.assertEqual(pprint.pformat(special, width=57), """\
1052 bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
1053 b'\\x0c\\r\\x0e\\x0f')""")
1054 self.assertEqual(pprint.pformat(special, width=41), """\
1055 bytearray(b'\\x00\\x01\\x02\\x03'
1056 b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
1057 b'\\x0c\\r\\x0e\\x0f')""")
1058 self.assertEqual(pprint.pformat(special, width=1), """\
1059 bytearray(b'\\x00\\x01\\x02\\x03'
1060 b'\\x04\\x05\\x06\\x07'
1061 b'\\x08\\t\\n\\x0b'
1062 b'\\x0c\\r\\x0e\\x0f')""")
1063 self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
1064 width=31), """\
1065 {'a': 1,
1066 'b': bytearray(b'abcdefghijkl'
1067 b'mnopqrstuvwx'
1068 b'yz'),
1069 'c': 2}""")
1070 self.assertEqual(pprint.pformat([[[[[letters]]]]], width=37), """\
1071 [[[[[bytearray(b'abcdefghijklmnop'
1072 b'qrstuvwxyz')]]]]]""")
1073 self.assertEqual(pprint.pformat([[[[[special]]]]], width=50), """\
1074 [[[[[bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
1075 b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')]]]]]""")
1076
1077 def test_default_dict(self):
1078 d = collections.defaultdict(int)
1079 self.assertEqual(pprint.pformat(d, width=1), "defaultdict(<class 'int'>, {})")
1080 words = 'the quick brown fox jumped over a lazy dog'.split()
1081 d = collections.defaultdict(int, zip(words, itertools.count()))
1082 self.assertEqual(pprint.pformat(d),
1083 """\
1084 defaultdict(<class 'int'>,
1085 {'a': 6,
1086 'brown': 2,
1087 'dog': 8,
1088 'fox': 3,
1089 'jumped': 4,
1090 'lazy': 7,
1091 'over': 5,
1092 'quick': 1,
1093 'the': 0})""")
1094
1095 def test_counter(self):
1096 d = collections.Counter()
1097 self.assertEqual(pprint.pformat(d, width=1), "Counter()")
1098 d = collections.Counter('senselessness')
1099 self.assertEqual(pprint.pformat(d, width=40),
1100 """\
1101 Counter({'s': 6,
1102 'e': 4,
1103 'n': 2,
1104 'l': 1})""")
1105
1106 def test_chainmap(self):
1107 d = collections.ChainMap()
1108 self.assertEqual(pprint.pformat(d, width=1), "ChainMap({})")
1109 words = 'the quick brown fox jumped over a lazy dog'.split()
1110 items = list(zip(words, itertools.count()))
1111 d = collections.ChainMap(dict(items))
1112 self.assertEqual(pprint.pformat(d),
1113 """\
1114 ChainMap({'a': 6,
1115 'brown': 2,
1116 'dog': 8,
1117 'fox': 3,
1118 'jumped': 4,
1119 'lazy': 7,
1120 'over': 5,
1121 'quick': 1,
1122 'the': 0})""")
1123 d = collections.ChainMap(dict(items), collections.OrderedDict(items))
1124 self.assertEqual(pprint.pformat(d),
1125 """\
1126 ChainMap({'a': 6,
1127 'brown': 2,
1128 'dog': 8,
1129 'fox': 3,
1130 'jumped': 4,
1131 'lazy': 7,
1132 'over': 5,
1133 'quick': 1,
1134 'the': 0},
1135 OrderedDict([('the', 0),
1136 ('quick', 1),
1137 ('brown', 2),
1138 ('fox', 3),
1139 ('jumped', 4),
1140 ('over', 5),
1141 ('a', 6),
1142 ('lazy', 7),
1143 ('dog', 8)]))""")
1144
1145 def test_deque(self):
1146 d = collections.deque()
1147 self.assertEqual(pprint.pformat(d, width=1), "deque([])")
1148 d = collections.deque(maxlen=7)
1149 self.assertEqual(pprint.pformat(d, width=1), "deque([], maxlen=7)")
1150 words = 'the quick brown fox jumped over a lazy dog'.split()
1151 d = collections.deque(zip(words, itertools.count()))
1152 self.assertEqual(pprint.pformat(d),
1153 """\
1154 deque([('the', 0),
1155 ('quick', 1),
1156 ('brown', 2),
1157 ('fox', 3),
1158 ('jumped', 4),
1159 ('over', 5),
1160 ('a', 6),
1161 ('lazy', 7),
1162 ('dog', 8)])""")
1163 d = collections.deque(zip(words, itertools.count()), maxlen=7)
1164 self.assertEqual(pprint.pformat(d),
1165 """\
1166 deque([('brown', 2),
1167 ('fox', 3),
1168 ('jumped', 4),
1169 ('over', 5),
1170 ('a', 6),
1171 ('lazy', 7),
1172 ('dog', 8)],
1173 maxlen=7)""")
1174
1175 def test_user_dict(self):
1176 d = collections.UserDict()
1177 self.assertEqual(pprint.pformat(d, width=1), "{}")
1178 words = 'the quick brown fox jumped over a lazy dog'.split()
1179 d = collections.UserDict(zip(words, itertools.count()))
1180 self.assertEqual(pprint.pformat(d),
1181 """\
1182 {'a': 6,
1183 'brown': 2,
1184 'dog': 8,
1185 'fox': 3,
1186 'jumped': 4,
1187 'lazy': 7,
1188 'over': 5,
1189 'quick': 1,
1190 'the': 0}""")
1191
1192 def test_user_list(self):
1193 d = collections.UserList()
1194 self.assertEqual(pprint.pformat(d, width=1), "[]")
1195 words = 'the quick brown fox jumped over a lazy dog'.split()
1196 d = collections.UserList(zip(words, itertools.count()))
1197 self.assertEqual(pprint.pformat(d),
1198 """\
1199 [('the', 0),
1200 ('quick', 1),
1201 ('brown', 2),
1202 ('fox', 3),
1203 ('jumped', 4),
1204 ('over', 5),
1205 ('a', 6),
1206 ('lazy', 7),
1207 ('dog', 8)]""")
1208
1209 def test_user_string(self):
1210 d = collections.UserString('')
1211 self.assertEqual(pprint.pformat(d, width=1), "''")
1212 d = collections.UserString('the quick brown fox jumped over a lazy dog')
1213 self.assertEqual(pprint.pformat(d, width=20),
1214 """\
1215 ('the quick brown '
1216 'fox jumped over '
1217 'a lazy dog')""")
1218 self.assertEqual(pprint.pformat({1: d}, width=20),
1219 """\
1220 {1: 'the quick '
1221 'brown fox '
1222 'jumped over a '
1223 'lazy dog'}""")
1224
1225
1226 class ESC[4;38;5;81mDottedPrettyPrinter(ESC[4;38;5;149mpprintESC[4;38;5;149m.ESC[4;38;5;149mPrettyPrinter):
1227
1228 def format(self, object, context, maxlevels, level):
1229 if isinstance(object, str):
1230 if ' ' in object:
1231 return repr(object), 1, 0
1232 else:
1233 return object, 0, 0
1234 else:
1235 return pprint.PrettyPrinter.format(
1236 self, object, context, maxlevels, level)
1237
1238
1239 if __name__ == "__main__":
1240 unittest.main()