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