1# -*- coding: utf-8 -*- 2 3import collections 4import contextlib 5import dataclasses 6import io 7import itertools 8import pprint 9import random 10import re 11import test.support 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 object(), int, pprint, pprint.isrecursive: 207 # module-level convenience functions 208 self.assertFalse(pprint.isrecursive(unreadable), 209 "expected not isrecursive for %r" % (unreadable,)) 210 self.assertFalse(pprint.isreadable(unreadable), 211 "expected not isreadable for %r" % (unreadable,)) 212 # PrettyPrinter methods 213 self.assertFalse(pp.isrecursive(unreadable), 214 "expected not isrecursive for %r" % (unreadable,)) 215 self.assertFalse(pp.isreadable(unreadable), 216 "expected not isreadable for %r" % (unreadable,)) 217 218 def test_same_as_repr(self): 219 # Simple objects, small containers and classes that override __repr__ 220 # to directly call super's __repr__. 221 # For those the result should be the same as repr(). 222 # Ahem. The docs don't say anything about that -- this appears to 223 # be testing an implementation quirk. Starting in Python 2.5, it's 224 # not true for dicts: pprint always sorts dicts by key now; before, 225 # it sorted a dict display if and only if the display required 226 # multiple lines. For that reason, dicts with more than one element 227 # aren't tested here. 228 for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), 229 (), tuple2(), tuple3(), 230 [], list2(), list3(), 231 set(), set2(), set3(), 232 frozenset(), frozenset2(), frozenset3(), 233 {}, dict2(), dict3(), 234 self.assertTrue, pprint, 235 -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), 236 (3,), [3], {3: 6}, 237 (1,2), [3,4], {5: 6}, 238 tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), 239 [3,4], list2([3,4]), list3([3,4]), list3(range(100)), 240 set({7}), set2({7}), set3({7}), 241 frozenset({8}), frozenset2({8}), frozenset3({8}), 242 dict2({5: 6}), dict3({5: 6}), 243 range(10, -11, -1), 244 True, False, None, ..., 245 ): 246 native = repr(simple) 247 self.assertEqual(pprint.pformat(simple), native) 248 self.assertEqual(pprint.pformat(simple, width=1, indent=0) 249 .replace('\n', ' '), native) 250 self.assertEqual(pprint.pformat(simple, underscore_numbers=True), native) 251 self.assertEqual(pprint.saferepr(simple), native) 252 253 def test_container_repr_override_called(self): 254 N = 1000 255 # Ensure that __repr__ override is called for subclasses of containers 256 257 for cont in (list_custom_repr(), 258 list_custom_repr([1,2,3]), 259 list_custom_repr(range(N)), 260 tuple_custom_repr(), 261 tuple_custom_repr([1,2,3]), 262 tuple_custom_repr(range(N)), 263 set_custom_repr(), 264 set_custom_repr([1,2,3]), 265 set_custom_repr(range(N)), 266 frozenset_custom_repr(), 267 frozenset_custom_repr([1,2,3]), 268 frozenset_custom_repr(range(N)), 269 dict_custom_repr(), 270 dict_custom_repr({5: 6}), 271 dict_custom_repr(zip(range(N),range(N))), 272 ): 273 native = repr(cont) 274 expected = '*' * len(native) 275 self.assertEqual(pprint.pformat(cont), expected) 276 self.assertEqual(pprint.pformat(cont, width=1, indent=0), expected) 277 self.assertEqual(pprint.saferepr(cont), expected) 278 279 def test_basic_line_wrap(self): 280 # verify basic line-wrapping operation 281 o = {'RPM_cal': 0, 282 'RPM_cal2': 48059, 283 'Speed_cal': 0, 284 'controldesk_runtime_us': 0, 285 'main_code_runtime_us': 0, 286 'read_io_runtime_us': 0, 287 'write_io_runtime_us': 43690} 288 exp = """\ 289{'RPM_cal': 0, 290 'RPM_cal2': 48059, 291 'Speed_cal': 0, 292 'controldesk_runtime_us': 0, 293 'main_code_runtime_us': 0, 294 'read_io_runtime_us': 0, 295 'write_io_runtime_us': 43690}""" 296 for type in [dict, dict2]: 297 self.assertEqual(pprint.pformat(type(o)), exp) 298 299 o = range(100) 300 exp = '[%s]' % ',\n '.join(map(str, o)) 301 for type in [list, list2]: 302 self.assertEqual(pprint.pformat(type(o)), exp) 303 304 o = tuple(range(100)) 305 exp = '(%s)' % ',\n '.join(map(str, o)) 306 for type in [tuple, tuple2]: 307 self.assertEqual(pprint.pformat(type(o)), exp) 308 309 # indent parameter 310 o = range(100) 311 exp = '[ %s]' % ',\n '.join(map(str, o)) 312 for type in [list, list2]: 313 self.assertEqual(pprint.pformat(type(o), indent=4), exp) 314 315 def test_nested_indentations(self): 316 o1 = list(range(10)) 317 o2 = dict(first=1, second=2, third=3) 318 o = [o1, o2] 319 expected = """\ 320[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 321 {'first': 1, 'second': 2, 'third': 3}]""" 322 self.assertEqual(pprint.pformat(o, indent=4, width=42), expected) 323 expected = """\ 324[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 325 { 'first': 1, 326 'second': 2, 327 'third': 3}]""" 328 self.assertEqual(pprint.pformat(o, indent=4, width=41), expected) 329 330 def test_width(self): 331 expected = """\ 332[[[[[[1, 2, 3], 333 '1 2']]]], 334 {1: [1, 2, 3], 335 2: [12, 34]}, 336 'abc def ghi', 337 ('ab cd ef',), 338 set2({1, 23}), 339 [[[[[1, 2, 3], 340 '1 2']]]]]""" 341 o = eval(expected) 342 self.assertEqual(pprint.pformat(o, width=15), expected) 343 self.assertEqual(pprint.pformat(o, width=16), expected) 344 self.assertEqual(pprint.pformat(o, width=25), expected) 345 self.assertEqual(pprint.pformat(o, width=14), """\ 346[[[[[[1, 347 2, 348 3], 349 '1 ' 350 '2']]]], 351 {1: [1, 352 2, 353 3], 354 2: [12, 355 34]}, 356 'abc def ' 357 'ghi', 358 ('ab cd ' 359 'ef',), 360 set2({1, 361 23}), 362 [[[[[1, 363 2, 364 3], 365 '1 ' 366 '2']]]]]""") 367 368 def test_integer(self): 369 self.assertEqual(pprint.pformat(1234567), '1234567') 370 self.assertEqual(pprint.pformat(1234567, underscore_numbers=True), '1_234_567') 371 372 class 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( 539 formatted, 540 fr"<{re.escape(__name__)}.dataclass3 object at \w+>", 541 ) 542 543 def test_recursive_dataclass(self): 544 dc = dataclass4(None) 545 dc.a = dc 546 formatted = pprint.pformat(dc, width=10) 547 self.assertEqual(formatted, """\ 548dataclass4(a=..., 549 b=1)""") 550 551 def test_cyclic_dataclass(self): 552 dc5 = dataclass5(None) 553 dc6 = dataclass6(None) 554 dc5.a = dc6 555 dc6.c = dc5 556 formatted = pprint.pformat(dc5, width=10) 557 self.assertEqual(formatted, """\ 558dataclass5(a=dataclass6(c=..., 559 d=1), 560 b=1)""") 561 562 def test_subclassing(self): 563 # length(repr(obj)) > width 564 o = {'names with spaces': 'should be presented using repr()', 565 'others.should.not.be': 'like.this'} 566 exp = """\ 567{'names with spaces': 'should be presented using repr()', 568 others.should.not.be: like.this}""" 569 570 dotted_printer = DottedPrettyPrinter() 571 self.assertEqual(dotted_printer.pformat(o), exp) 572 573 # length(repr(obj)) < width 574 o1 = ['with space'] 575 exp1 = "['with space']" 576 self.assertEqual(dotted_printer.pformat(o1), exp1) 577 o2 = ['without.space'] 578 exp2 = "[without.space]" 579 self.assertEqual(dotted_printer.pformat(o2), exp2) 580 581 def test_set_reprs(self): 582 self.assertEqual(pprint.pformat(set()), 'set()') 583 self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}') 584 self.assertEqual(pprint.pformat(set(range(7)), width=20), '''\ 585{0, 586 1, 587 2, 588 3, 589 4, 590 5, 591 6}''') 592 self.assertEqual(pprint.pformat(set2(range(7)), width=20), '''\ 593set2({0, 594 1, 595 2, 596 3, 597 4, 598 5, 599 6})''') 600 self.assertEqual(pprint.pformat(set3(range(7)), width=20), 601 'set3({0, 1, 2, 3, 4, 5, 6})') 602 603 self.assertEqual(pprint.pformat(frozenset()), 'frozenset()') 604 self.assertEqual(pprint.pformat(frozenset(range(3))), 605 'frozenset({0, 1, 2})') 606 self.assertEqual(pprint.pformat(frozenset(range(7)), width=20), '''\ 607frozenset({0, 608 1, 609 2, 610 3, 611 4, 612 5, 613 6})''') 614 self.assertEqual(pprint.pformat(frozenset2(range(7)), width=20), '''\ 615frozenset2({0, 616 1, 617 2, 618 3, 619 4, 620 5, 621 6})''') 622 self.assertEqual(pprint.pformat(frozenset3(range(7)), width=20), 623 'frozenset3({0, 1, 2, 3, 4, 5, 6})') 624 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 # >>> frozenset({0}) < frozenset({1}) 636 # False 637 # >>> frozenset({1}) < frozenset({0}) 638 # False 639 # 640 # In this test we list all possible invariants of the result 641 # for unordered frozensets. 642 # 643 # This test has a long history, see: 644 # - https://github.com/python/cpython/commit/969fe57baa0eb80332990f9cda936a33e13fabef 645 # - https://github.com/python/cpython/issues/58115 646 # - https://github.com/python/cpython/issues/111147 647 648 import textwrap 649 650 # Single-line, always ordered: 651 fs0 = frozenset() 652 fs1 = frozenset(('abc', 'xyz')) 653 data = frozenset((fs0, fs1)) 654 self.assertEqual(pprint.pformat(data), 655 'frozenset({%r, %r})' % (fs0, fs1)) 656 self.assertEqual(pprint.pformat(data), repr(data)) 657 658 fs2 = frozenset(('one', 'two')) 659 data = {fs2: frozenset((fs0, fs1))} 660 self.assertEqual(pprint.pformat(data), 661 "{%r: frozenset({%r, %r})}" % (fs2, fs0, fs1)) 662 self.assertEqual(pprint.pformat(data), repr(data)) 663 664 # Single-line, unordered: 665 fs1 = frozenset(("xyz", "qwerty")) 666 fs2 = frozenset(("abcd", "spam")) 667 fs = frozenset((fs1, fs2)) 668 self.assertEqual(pprint.pformat(fs), repr(fs)) 669 670 # Multiline, unordered: 671 def check(res, invariants): 672 self.assertIn(res, [textwrap.dedent(i).strip() for i in invariants]) 673 674 # Inner-most frozensets are singleline, result is multiline, unordered: 675 fs1 = frozenset(('regular string', 'other string')) 676 fs2 = frozenset(('third string', 'one more string')) 677 check( 678 pprint.pformat(frozenset((fs1, fs2))), 679 [ 680 """ 681 frozenset({%r, 682 %r}) 683 """ % (fs1, fs2), 684 """ 685 frozenset({%r, 686 %r}) 687 """ % (fs2, fs1), 688 ], 689 ) 690 691 # Everything is multiline, unordered: 692 check( 693 pprint.pformat( 694 frozenset(( 695 frozenset(( 696 "xyz very-very long string", 697 "qwerty is also absurdly long", 698 )), 699 frozenset(( 700 "abcd is even longer that before", 701 "spam is not so long", 702 )), 703 )), 704 ), 705 [ 706 """ 707 frozenset({frozenset({'abcd is even longer that before', 708 'spam is not so long'}), 709 frozenset({'qwerty is also absurdly long', 710 'xyz very-very long string'})}) 711 """, 712 713 """ 714 frozenset({frozenset({'abcd is even longer that before', 715 'spam is not so long'}), 716 frozenset({'xyz very-very long string', 717 'qwerty is also absurdly long'})}) 718 """, 719 720 """ 721 frozenset({frozenset({'qwerty is also absurdly long', 722 'xyz very-very long string'}), 723 frozenset({'abcd is even longer that before', 724 'spam is not so long'})}) 725 """, 726 727 """ 728 frozenset({frozenset({'qwerty is also absurdly long', 729 'xyz very-very long string'}), 730 frozenset({'spam is not so long', 731 'abcd is even longer that before'})}) 732 """, 733 ], 734 ) 735 736 def test_depth(self): 737 nested_tuple = (1, (2, (3, (4, (5, 6))))) 738 nested_dict = {1: {2: {3: {4: {5: {6: 6}}}}}} 739 nested_list = [1, [2, [3, [4, [5, [6, []]]]]]] 740 self.assertEqual(pprint.pformat(nested_tuple), repr(nested_tuple)) 741 self.assertEqual(pprint.pformat(nested_dict), repr(nested_dict)) 742 self.assertEqual(pprint.pformat(nested_list), repr(nested_list)) 743 744 lv1_tuple = '(1, (...))' 745 lv1_dict = '{1: {...}}' 746 lv1_list = '[1, [...]]' 747 self.assertEqual(pprint.pformat(nested_tuple, depth=1), lv1_tuple) 748 self.assertEqual(pprint.pformat(nested_dict, depth=1), lv1_dict) 749 self.assertEqual(pprint.pformat(nested_list, depth=1), lv1_list) 750 751 def test_sort_unorderable_values(self): 752 # Issue 3976: sorted pprints fail for unorderable values. 753 n = 20 754 keys = [Unorderable() for i in range(n)] 755 random.shuffle(keys) 756 skeys = sorted(keys, key=id) 757 clean = lambda s: s.replace(' ', '').replace('\n','') 758 759 self.assertEqual(clean(pprint.pformat(set(keys))), 760 '{' + ','.join(map(repr, skeys)) + '}') 761 self.assertEqual(clean(pprint.pformat(frozenset(keys))), 762 'frozenset({' + ','.join(map(repr, skeys)) + '})') 763 self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys))), 764 '{' + ','.join('%r:None' % k for k in skeys) + '}') 765 766 # Issue 10017: TypeError on user-defined types as dict keys. 767 self.assertEqual(pprint.pformat({Unorderable: 0, 1: 0}), 768 '{1: 0, ' + repr(Unorderable) +': 0}') 769 770 # Issue 14998: TypeError on tuples with NoneTypes as dict keys. 771 keys = [(1,), (None,)] 772 self.assertEqual(pprint.pformat(dict.fromkeys(keys, 0)), 773 '{%r: 0, %r: 0}' % tuple(sorted(keys, key=id))) 774 775 def test_sort_orderable_and_unorderable_values(self): 776 # Issue 22721: sorted pprints is not stable 777 a = Unorderable() 778 b = Orderable(hash(a)) # should have the same hash value 779 # self-test 780 self.assertLess(a, b) 781 self.assertLess(str(type(b)), str(type(a))) 782 self.assertEqual(sorted([b, a]), [a, b]) 783 self.assertEqual(sorted([a, b]), [a, b]) 784 # set 785 self.assertEqual(pprint.pformat(set([b, a]), width=1), 786 '{%r,\n %r}' % (a, b)) 787 self.assertEqual(pprint.pformat(set([a, b]), width=1), 788 '{%r,\n %r}' % (a, b)) 789 # dict 790 self.assertEqual(pprint.pformat(dict.fromkeys([b, a]), width=1), 791 '{%r: None,\n %r: None}' % (a, b)) 792 self.assertEqual(pprint.pformat(dict.fromkeys([a, b]), width=1), 793 '{%r: None,\n %r: None}' % (a, b)) 794 795 def test_str_wrap(self): 796 # pprint tries to wrap strings intelligently 797 fox = 'the quick brown fox jumped over a lazy dog' 798 self.assertEqual(pprint.pformat(fox, width=19), """\ 799('the quick brown ' 800 'fox jumped over ' 801 'a lazy dog')""") 802 self.assertEqual(pprint.pformat({'a': 1, 'b': fox, 'c': 2}, 803 width=25), """\ 804{'a': 1, 805 'b': 'the quick brown ' 806 'fox jumped over ' 807 'a lazy dog', 808 'c': 2}""") 809 # With some special characters 810 # - \n always triggers a new line in the pprint 811 # - \t and \n are escaped 812 # - non-ASCII is allowed 813 # - an apostrophe doesn't disrupt the pprint 814 special = "Portons dix bons \"whiskys\"\nà l'avocat goujat\t qui fumait au zoo" 815 self.assertEqual(pprint.pformat(special, width=68), repr(special)) 816 self.assertEqual(pprint.pformat(special, width=31), """\ 817('Portons dix bons "whiskys"\\n' 818 "à l'avocat goujat\\t qui " 819 'fumait au zoo')""") 820 self.assertEqual(pprint.pformat(special, width=20), """\ 821('Portons dix bons ' 822 '"whiskys"\\n' 823 "à l'avocat " 824 'goujat\\t qui ' 825 'fumait au zoo')""") 826 self.assertEqual(pprint.pformat([[[[[special]]]]], width=35), """\ 827[[[[['Portons dix bons "whiskys"\\n' 828 "à l'avocat goujat\\t qui " 829 'fumait au zoo']]]]]""") 830 self.assertEqual(pprint.pformat([[[[[special]]]]], width=25), """\ 831[[[[['Portons dix bons ' 832 '"whiskys"\\n' 833 "à l'avocat " 834 'goujat\\t qui ' 835 'fumait au zoo']]]]]""") 836 self.assertEqual(pprint.pformat([[[[[special]]]]], width=23), """\ 837[[[[['Portons dix ' 838 'bons "whiskys"\\n' 839 "à l'avocat " 840 'goujat\\t qui ' 841 'fumait au ' 842 'zoo']]]]]""") 843 # An unwrappable string is formatted as its repr 844 unwrappable = "x" * 100 845 self.assertEqual(pprint.pformat(unwrappable, width=80), repr(unwrappable)) 846 self.assertEqual(pprint.pformat(''), "''") 847 # Check that the pprint is a usable repr 848 special *= 10 849 for width in range(3, 40): 850 formatted = pprint.pformat(special, width=width) 851 self.assertEqual(eval(formatted), special) 852 formatted = pprint.pformat([special] * 2, width=width) 853 self.assertEqual(eval(formatted), [special] * 2) 854 855 def test_compact(self): 856 o = ([list(range(i * i)) for i in range(5)] + 857 [list(range(i)) for i in range(6)]) 858 expected = """\ 859[[], [0], [0, 1, 2, 3], 860 [0, 1, 2, 3, 4, 5, 6, 7, 8], 861 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 862 14, 15], 863 [], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], 864 [0, 1, 2, 3, 4]]""" 865 self.assertEqual(pprint.pformat(o, width=47, compact=True), expected) 866 867 def test_compact_width(self): 868 levels = 20 869 number = 10 870 o = [0] * number 871 for i in range(levels - 1): 872 o = [o] 873 for w in range(levels * 2 + 1, levels + 3 * number - 1): 874 lines = pprint.pformat(o, width=w, compact=True).splitlines() 875 maxwidth = max(map(len, lines)) 876 self.assertLessEqual(maxwidth, w) 877 self.assertGreater(maxwidth, w - 3) 878 879 def test_bytes_wrap(self): 880 self.assertEqual(pprint.pformat(b'', width=1), "b''") 881 self.assertEqual(pprint.pformat(b'abcd', width=1), "b'abcd'") 882 letters = b'abcdefghijklmnopqrstuvwxyz' 883 self.assertEqual(pprint.pformat(letters, width=29), repr(letters)) 884 self.assertEqual(pprint.pformat(letters, width=19), """\ 885(b'abcdefghijkl' 886 b'mnopqrstuvwxyz')""") 887 self.assertEqual(pprint.pformat(letters, width=18), """\ 888(b'abcdefghijkl' 889 b'mnopqrstuvwx' 890 b'yz')""") 891 self.assertEqual(pprint.pformat(letters, width=16), """\ 892(b'abcdefghijkl' 893 b'mnopqrstuvwx' 894 b'yz')""") 895 special = bytes(range(16)) 896 self.assertEqual(pprint.pformat(special, width=61), repr(special)) 897 self.assertEqual(pprint.pformat(special, width=48), """\ 898(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b' 899 b'\\x0c\\r\\x0e\\x0f')""") 900 self.assertEqual(pprint.pformat(special, width=32), """\ 901(b'\\x00\\x01\\x02\\x03' 902 b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b' 903 b'\\x0c\\r\\x0e\\x0f')""") 904 self.assertEqual(pprint.pformat(special, width=1), """\ 905(b'\\x00\\x01\\x02\\x03' 906 b'\\x04\\x05\\x06\\x07' 907 b'\\x08\\t\\n\\x0b' 908 b'\\x0c\\r\\x0e\\x0f')""") 909 self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2}, 910 width=21), """\ 911{'a': 1, 912 'b': b'abcdefghijkl' 913 b'mnopqrstuvwx' 914 b'yz', 915 'c': 2}""") 916 self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2}, 917 width=20), """\ 918{'a': 1, 919 'b': b'abcdefgh' 920 b'ijklmnop' 921 b'qrstuvwxyz', 922 'c': 2}""") 923 self.assertEqual(pprint.pformat([[[[[[letters]]]]]], width=25), """\ 924[[[[[[b'abcdefghijklmnop' 925 b'qrstuvwxyz']]]]]]""") 926 self.assertEqual(pprint.pformat([[[[[[special]]]]]], width=41), """\ 927[[[[[[b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07' 928 b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f']]]]]]""") 929 # Check that the pprint is a usable repr 930 for width in range(1, 64): 931 formatted = pprint.pformat(special, width=width) 932 self.assertEqual(eval(formatted), special) 933 formatted = pprint.pformat([special] * 2, width=width) 934 self.assertEqual(eval(formatted), [special] * 2) 935 936 def test_bytearray_wrap(self): 937 self.assertEqual(pprint.pformat(bytearray(), width=1), "bytearray(b'')") 938 letters = bytearray(b'abcdefghijklmnopqrstuvwxyz') 939 self.assertEqual(pprint.pformat(letters, width=40), repr(letters)) 940 self.assertEqual(pprint.pformat(letters, width=28), """\ 941bytearray(b'abcdefghijkl' 942 b'mnopqrstuvwxyz')""") 943 self.assertEqual(pprint.pformat(letters, width=27), """\ 944bytearray(b'abcdefghijkl' 945 b'mnopqrstuvwx' 946 b'yz')""") 947 self.assertEqual(pprint.pformat(letters, width=25), """\ 948bytearray(b'abcdefghijkl' 949 b'mnopqrstuvwx' 950 b'yz')""") 951 special = bytearray(range(16)) 952 self.assertEqual(pprint.pformat(special, width=72), repr(special)) 953 self.assertEqual(pprint.pformat(special, width=57), """\ 954bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b' 955 b'\\x0c\\r\\x0e\\x0f')""") 956 self.assertEqual(pprint.pformat(special, width=41), """\ 957bytearray(b'\\x00\\x01\\x02\\x03' 958 b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b' 959 b'\\x0c\\r\\x0e\\x0f')""") 960 self.assertEqual(pprint.pformat(special, width=1), """\ 961bytearray(b'\\x00\\x01\\x02\\x03' 962 b'\\x04\\x05\\x06\\x07' 963 b'\\x08\\t\\n\\x0b' 964 b'\\x0c\\r\\x0e\\x0f')""") 965 self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2}, 966 width=31), """\ 967{'a': 1, 968 'b': bytearray(b'abcdefghijkl' 969 b'mnopqrstuvwx' 970 b'yz'), 971 'c': 2}""") 972 self.assertEqual(pprint.pformat([[[[[letters]]]]], width=37), """\ 973[[[[[bytearray(b'abcdefghijklmnop' 974 b'qrstuvwxyz')]]]]]""") 975 self.assertEqual(pprint.pformat([[[[[special]]]]], width=50), """\ 976[[[[[bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07' 977 b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')]]]]]""") 978 979 def test_default_dict(self): 980 d = collections.defaultdict(int) 981 self.assertEqual(pprint.pformat(d, width=1), "defaultdict(<class 'int'>, {})") 982 words = 'the quick brown fox jumped over a lazy dog'.split() 983 d = collections.defaultdict(int, zip(words, itertools.count())) 984 self.assertEqual(pprint.pformat(d), 985"""\ 986defaultdict(<class 'int'>, 987 {'a': 6, 988 'brown': 2, 989 'dog': 8, 990 'fox': 3, 991 'jumped': 4, 992 'lazy': 7, 993 'over': 5, 994 'quick': 1, 995 'the': 0})""") 996 997 def test_counter(self): 998 d = collections.Counter() 999 self.assertEqual(pprint.pformat(d, width=1), "Counter()") 1000 d = collections.Counter('senselessness') 1001 self.assertEqual(pprint.pformat(d, width=40), 1002"""\ 1003Counter({'s': 6, 1004 'e': 4, 1005 'n': 2, 1006 'l': 1})""") 1007 1008 def test_chainmap(self): 1009 d = collections.ChainMap() 1010 self.assertEqual(pprint.pformat(d, width=1), "ChainMap({})") 1011 words = 'the quick brown fox jumped over a lazy dog'.split() 1012 items = list(zip(words, itertools.count())) 1013 d = collections.ChainMap(dict(items)) 1014 self.assertEqual(pprint.pformat(d), 1015"""\ 1016ChainMap({'a': 6, 1017 'brown': 2, 1018 'dog': 8, 1019 'fox': 3, 1020 'jumped': 4, 1021 'lazy': 7, 1022 'over': 5, 1023 'quick': 1, 1024 'the': 0})""") 1025 d = collections.ChainMap(dict(items), collections.OrderedDict(items)) 1026 self.assertEqual(pprint.pformat(d), 1027"""\ 1028ChainMap({'a': 6, 1029 'brown': 2, 1030 'dog': 8, 1031 'fox': 3, 1032 'jumped': 4, 1033 'lazy': 7, 1034 'over': 5, 1035 'quick': 1, 1036 'the': 0}, 1037 OrderedDict([('the', 0), 1038 ('quick', 1), 1039 ('brown', 2), 1040 ('fox', 3), 1041 ('jumped', 4), 1042 ('over', 5), 1043 ('a', 6), 1044 ('lazy', 7), 1045 ('dog', 8)]))""") 1046 1047 def test_deque(self): 1048 d = collections.deque() 1049 self.assertEqual(pprint.pformat(d, width=1), "deque([])") 1050 d = collections.deque(maxlen=7) 1051 self.assertEqual(pprint.pformat(d, width=1), "deque([], maxlen=7)") 1052 words = 'the quick brown fox jumped over a lazy dog'.split() 1053 d = collections.deque(zip(words, itertools.count())) 1054 self.assertEqual(pprint.pformat(d), 1055"""\ 1056deque([('the', 0), 1057 ('quick', 1), 1058 ('brown', 2), 1059 ('fox', 3), 1060 ('jumped', 4), 1061 ('over', 5), 1062 ('a', 6), 1063 ('lazy', 7), 1064 ('dog', 8)])""") 1065 d = collections.deque(zip(words, itertools.count()), maxlen=7) 1066 self.assertEqual(pprint.pformat(d), 1067"""\ 1068deque([('brown', 2), 1069 ('fox', 3), 1070 ('jumped', 4), 1071 ('over', 5), 1072 ('a', 6), 1073 ('lazy', 7), 1074 ('dog', 8)], 1075 maxlen=7)""") 1076 1077 def test_user_dict(self): 1078 d = collections.UserDict() 1079 self.assertEqual(pprint.pformat(d, width=1), "{}") 1080 words = 'the quick brown fox jumped over a lazy dog'.split() 1081 d = collections.UserDict(zip(words, itertools.count())) 1082 self.assertEqual(pprint.pformat(d), 1083"""\ 1084{'a': 6, 1085 'brown': 2, 1086 'dog': 8, 1087 'fox': 3, 1088 'jumped': 4, 1089 'lazy': 7, 1090 'over': 5, 1091 'quick': 1, 1092 'the': 0}""") 1093 1094 def test_user_list(self): 1095 d = collections.UserList() 1096 self.assertEqual(pprint.pformat(d, width=1), "[]") 1097 words = 'the quick brown fox jumped over a lazy dog'.split() 1098 d = collections.UserList(zip(words, itertools.count())) 1099 self.assertEqual(pprint.pformat(d), 1100"""\ 1101[('the', 0), 1102 ('quick', 1), 1103 ('brown', 2), 1104 ('fox', 3), 1105 ('jumped', 4), 1106 ('over', 5), 1107 ('a', 6), 1108 ('lazy', 7), 1109 ('dog', 8)]""") 1110 1111 def test_user_string(self): 1112 d = collections.UserString('') 1113 self.assertEqual(pprint.pformat(d, width=1), "''") 1114 d = collections.UserString('the quick brown fox jumped over a lazy dog') 1115 self.assertEqual(pprint.pformat(d, width=20), 1116"""\ 1117('the quick brown ' 1118 'fox jumped over ' 1119 'a lazy dog')""") 1120 self.assertEqual(pprint.pformat({1: d}, width=20), 1121"""\ 1122{1: 'the quick ' 1123 'brown fox ' 1124 'jumped over a ' 1125 'lazy dog'}""") 1126 1127 1128class DottedPrettyPrinter(pprint.PrettyPrinter): 1129 1130 def format(self, object, context, maxlevels, level): 1131 if isinstance(object, str): 1132 if ' ' in object: 1133 return repr(object), 1, 0 1134 else: 1135 return object, 0, 0 1136 else: 1137 return pprint.PrettyPrinter.format( 1138 self, object, context, maxlevels, level) 1139 1140 1141if __name__ == "__main__": 1142 unittest.main() 1143