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