1# -*- coding: utf-8 -*- 2 3import collections 4import contextlib 5import dataclasses 6import io 7import itertools 8import pprint 9import random 10import test.support 11import test.test_set 12import types 13import unittest 14 15# list, tuple and dict subclasses that do or don't overwrite __repr__ 16class list2(list): 17 pass 18 19class list3(list): 20 def __repr__(self): 21 return list.__repr__(self) 22 23class list_custom_repr(list): 24 def __repr__(self): 25 return '*'*len(list.__repr__(self)) 26 27class tuple2(tuple): 28 pass 29 30class tuple3(tuple): 31 def __repr__(self): 32 return tuple.__repr__(self) 33 34class tuple_custom_repr(tuple): 35 def __repr__(self): 36 return '*'*len(tuple.__repr__(self)) 37 38class set2(set): 39 pass 40 41class set3(set): 42 def __repr__(self): 43 return set.__repr__(self) 44 45class set_custom_repr(set): 46 def __repr__(self): 47 return '*'*len(set.__repr__(self)) 48 49class frozenset2(frozenset): 50 pass 51 52class frozenset3(frozenset): 53 def __repr__(self): 54 return frozenset.__repr__(self) 55 56class frozenset_custom_repr(frozenset): 57 def __repr__(self): 58 return '*'*len(frozenset.__repr__(self)) 59 60class dict2(dict): 61 pass 62 63class dict3(dict): 64 def __repr__(self): 65 return dict.__repr__(self) 66 67class dict_custom_repr(dict): 68 def __repr__(self): 69 return '*'*len(dict.__repr__(self)) 70 71@dataclasses.dataclass 72class dataclass1: 73 field1: str 74 field2: int 75 field3: bool = False 76 field4: int = dataclasses.field(default=1, repr=False) 77 78@dataclasses.dataclass 79class dataclass2: 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) 85class dataclass3: 86 a: int = 1 87 88@dataclasses.dataclass 89class dataclass4: 90 a: "dataclass4" 91 b: int = 1 92 93@dataclasses.dataclass 94class dataclass5: 95 a: "dataclass6" 96 b: int = 1 97 98@dataclasses.dataclass 99class dataclass6: 100 c: "dataclass5" 101 d: int = 1 102 103class Unorderable: 104 def __repr__(self): 105 return str(id(self)) 106 107# Class Orderable is orderable with any type 108class Orderable: 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 126class QueryTestCase(unittest.TestCase): 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 type(3), 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 Temperature(int): 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"""\ 413OrderedDict([('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), """\ 428mappingproxy({'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), """\ 440mappingproxy(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, """\ 474namespace(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 AdvancedNamespace(types.SimpleNamespace): 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, """\ 499AdvancedNamespace(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, """\ 545dataclass4(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, """\ 555dataclass5(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), '''\ 590set2({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), '''\ 604frozenset({0, 605 1, 606 2, 607 3, 608 4, 609 5, 610 6})''') 611 self.assertEqual(pprint.pformat(frozenset2(range(7)), width=20), '''\ 612frozenset2({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), """\ 1039bytearray(b'abcdefghijkl' 1040 b'mnopqrstuvwxyz')""") 1041 self.assertEqual(pprint.pformat(letters, width=27), """\ 1042bytearray(b'abcdefghijkl' 1043 b'mnopqrstuvwx' 1044 b'yz')""") 1045 self.assertEqual(pprint.pformat(letters, width=25), """\ 1046bytearray(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), """\ 1052bytearray(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), """\ 1055bytearray(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), """\ 1059bytearray(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"""\ 1084defaultdict(<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"""\ 1101Counter({'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"""\ 1114ChainMap({'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"""\ 1126ChainMap({'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"""\ 1154deque([('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"""\ 1166deque([('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 1226class DottedPrettyPrinter(pprint.PrettyPrinter): 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 1239if __name__ == "__main__": 1240 unittest.main() 1241