1import pprint 2import test.support 3import unittest 4import test.test_set 5import random 6import collections 7import itertools 8 9from typing import List, Any, Dict, Tuple, cast, Callable 10 11# list, tuple and dict subclasses that do or don't overwrite __repr__ 12class list2(list): 13 pass 14 15class list3(list): 16 def __repr__(self) -> str: 17 return list.__repr__(self) 18 19class tuple2(tuple): 20 pass 21 22class tuple3(tuple): 23 def __repr__(self) -> str: 24 return tuple.__repr__(self) 25 26class dict2(dict): 27 pass 28 29class dict3(dict): 30 def __repr__(self) -> str: 31 return dict.__repr__(self) 32 33class Unorderable: 34 def __repr__(self) -> str: 35 return str(id(self)) 36 37class QueryTestCase(unittest.TestCase): 38 39 def setUp(self) -> None: 40 self.a = list(range(100)) # type: List[Any] 41 self.b = list(range(200)) # type: List[Any] 42 self.a[-12] = self.b 43 44 def test_basic(self) -> None: 45 # Verify .isrecursive() and .isreadable() w/o recursion 46 pp = pprint.PrettyPrinter() 47 for safe in (2, 2.0, complex(0.0, 2.0), "abc", [3], (2,2), {3: 3}, "yaddayadda", 48 self.a, self.b): 49 # module-level convenience functions 50 self.assertFalse(pprint.isrecursive(safe), 51 "expected not isrecursive for %r" % (safe,)) 52 self.assertTrue(pprint.isreadable(safe), 53 "expected isreadable for %r" % (safe,)) 54 # PrettyPrinter methods 55 self.assertFalse(pp.isrecursive(safe), 56 "expected not isrecursive for %r" % (safe,)) 57 self.assertTrue(pp.isreadable(safe), 58 "expected isreadable for %r" % (safe,)) 59 60 def test_knotted(self) -> None: 61 # Verify .isrecursive() and .isreadable() w/ recursion 62 # Tie a knot. 63 self.b[67] = self.a 64 # Messy dict. 65 self.d = {} # type: Dict[int, dict] 66 self.d[0] = self.d[1] = self.d[2] = self.d 67 68 pp = pprint.PrettyPrinter() 69 70 for icky in self.a, self.b, self.d, (self.d, self.d): 71 self.assertTrue(pprint.isrecursive(icky), "expected isrecursive") 72 self.assertFalse(pprint.isreadable(icky), "expected not isreadable") 73 self.assertTrue(pp.isrecursive(icky), "expected isrecursive") 74 self.assertFalse(pp.isreadable(icky), "expected not isreadable") 75 76 # Break the cycles. 77 self.d.clear() 78 del self.a[:] 79 del self.b[:] 80 81 for safe in self.a, self.b, self.d, (self.d, self.d): 82 # module-level convenience functions 83 self.assertFalse(pprint.isrecursive(safe), 84 "expected not isrecursive for %r" % (safe,)) 85 self.assertTrue(pprint.isreadable(safe), 86 "expected isreadable for %r" % (safe,)) 87 # PrettyPrinter methods 88 self.assertFalse(pp.isrecursive(safe), 89 "expected not isrecursive for %r" % (safe,)) 90 self.assertTrue(pp.isreadable(safe), 91 "expected isreadable for %r" % (safe,)) 92 93 def test_unreadable(self) -> None: 94 # Not recursive but not readable anyway 95 pp = pprint.PrettyPrinter() 96 for unreadable in type(3), pprint, pprint.isrecursive: 97 # module-level convenience functions 98 self.assertFalse(pprint.isrecursive(unreadable), 99 "expected not isrecursive for %r" % (unreadable,)) 100 self.assertFalse(pprint.isreadable(unreadable), 101 "expected not isreadable for %r" % (unreadable,)) 102 # PrettyPrinter methods 103 self.assertFalse(pp.isrecursive(unreadable), 104 "expected not isrecursive for %r" % (unreadable,)) 105 self.assertFalse(pp.isreadable(unreadable), 106 "expected not isreadable for %r" % (unreadable,)) 107 108 def test_same_as_repr(self) -> None: 109 # Simple objects, small containers and classes that overwrite __repr__ 110 # For those the result should be the same as repr(). 111 # Ahem. The docs don't say anything about that -- this appears to 112 # be testing an implementation quirk. Starting in Python 2.5, it's 113 # not true for dicts: pprint always sorts dicts by key now; before, 114 # it sorted a dict display if and only if the display required 115 # multiple lines. For that reason, dicts with more than one element 116 # aren't tested here. 117 for simple in (0, 0, complex(0.0), 0.0, "", b"", 118 (), tuple2(), tuple3(), 119 [], list2(), list3(), 120 {}, dict2(), dict3(), 121 self.assertTrue, pprint, 122 -6, -6, complex(-6.,-6.), -1.5, "x", b"x", (3,), [3], {3: 6}, 123 (1,2), [3,4], {5: 6}, 124 tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), # type: ignore 125 [3,4], list2(cast(Any, [3,4])), list3(cast(Any, [3,4])), 126 list3(cast(Any, range(100))), dict2(cast(Any, {5: 6})), 127 dict3(cast(Any, {5: 6})), # JLe: work around mypy issue #233 128 range(10, -11, -1) 129 ): 130 native = repr(simple) 131 for function in "pformat", "saferepr": 132 f = getattr(pprint, function) 133 got = f(simple) 134 self.assertEqual(native, got, 135 "expected %s got %s from pprint.%s" % 136 (native, got, function)) 137 138 def test_basic_line_wrap(self) -> None: 139 # verify basic line-wrapping operation 140 o = {'RPM_cal': 0, 141 'RPM_cal2': 48059, 142 'Speed_cal': 0, 143 'controldesk_runtime_us': 0, 144 'main_code_runtime_us': 0, 145 'read_io_runtime_us': 0, 146 'write_io_runtime_us': 43690} 147 exp = """\ 148{'RPM_cal': 0, 149 'RPM_cal2': 48059, 150 'Speed_cal': 0, 151 'controldesk_runtime_us': 0, 152 'main_code_runtime_us': 0, 153 'read_io_runtime_us': 0, 154 'write_io_runtime_us': 43690}""" 155 # JLe: work around mypy issue #232 156 for type in cast(List[Any], [dict, dict2]): 157 self.assertEqual(pprint.pformat(type(o)), exp) 158 159 o2 = range(100) 160 exp = '[%s]' % ',\n '.join(map(str, o2)) 161 for type in cast(List[Any], [list, list2]): 162 self.assertEqual(pprint.pformat(type(o2)), exp) 163 164 o3 = tuple(range(100)) 165 exp = '(%s)' % ',\n '.join(map(str, o3)) 166 for type in cast(List[Any], [tuple, tuple2]): 167 self.assertEqual(pprint.pformat(type(o3)), exp) 168 169 # indent parameter 170 o4 = range(100) 171 exp = '[ %s]' % ',\n '.join(map(str, o4)) 172 for type in cast(List[Any], [list, list2]): 173 self.assertEqual(pprint.pformat(type(o4), indent=4), exp) 174 175 def test_nested_indentations(self) -> None: 176 o1 = list(range(10)) 177 o2 = {'first':1, 'second':2, 'third':3} 178 o = [o1, o2] 179 expected = """\ 180[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 181 { 'first': 1, 182 'second': 2, 183 'third': 3}]""" 184 self.assertEqual(pprint.pformat(o, indent=4, width=42), expected) 185 186 def test_sorted_dict(self) -> None: 187 # Starting in Python 2.5, pprint sorts dict displays by key regardless 188 # of how small the dictionary may be. 189 # Before the change, on 32-bit Windows pformat() gave order 190 # 'a', 'c', 'b' here, so this test failed. 191 d = {'a': 1, 'b': 1, 'c': 1} 192 self.assertEqual(pprint.pformat(d), "{'a': 1, 'b': 1, 'c': 1}") 193 self.assertEqual(pprint.pformat([d, d]), 194 "[{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 1, 'c': 1}]") 195 196 # The next one is kind of goofy. The sorted order depends on the 197 # alphabetic order of type names: "int" < "str" < "tuple". Before 198 # Python 2.5, this was in the test_same_as_repr() test. It's worth 199 # keeping around for now because it's one of few tests of pprint 200 # against a crazy mix of types. 201 self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}), 202 r"{5: [[]], 'xy\tab\n': (3,), (): {}}") 203 204 def test_ordered_dict(self) -> None: 205 words = 'the quick brown fox jumped over a lazy dog'.split() 206 d = collections.OrderedDict(zip(words, itertools.count())) 207 self.assertEqual(pprint.pformat(d), 208"""\ 209{'the': 0, 210 'quick': 1, 211 'brown': 2, 212 'fox': 3, 213 'jumped': 4, 214 'over': 5, 215 'a': 6, 216 'lazy': 7, 217 'dog': 8}""") 218 def test_subclassing(self) -> None: 219 o = {'names with spaces': 'should be presented using repr()', 220 'others.should.not.be': 'like.this'} 221 exp = """\ 222{'names with spaces': 'should be presented using repr()', 223 others.should.not.be: like.this}""" 224 self.assertEqual(DottedPrettyPrinter().pformat(o), exp) 225 226 @test.support.cpython_only 227 def test_set_reprs(self) -> None: 228 # This test creates a complex arrangement of frozensets and 229 # compares the pretty-printed repr against a string hard-coded in 230 # the test. The hard-coded repr depends on the sort order of 231 # frozensets. 232 # 233 # However, as the docs point out: "Since sets only define 234 # partial ordering (subset relationships), the output of the 235 # list.sort() method is undefined for lists of sets." 236 # 237 # In a nutshell, the test assumes frozenset({0}) will always 238 # sort before frozenset({1}), but: 239 # 240 # >>> frozenset({0}) < frozenset({1}) 241 # False 242 # >>> frozenset({1}) < frozenset({0}) 243 # False 244 # 245 # Consequently, this test is fragile and 246 # implementation-dependent. Small changes to Python's sort 247 # algorithm cause the test to fail when it should pass. 248 249 self.assertEqual(pprint.pformat(set()), 'set()') 250 self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}') 251 self.assertEqual(pprint.pformat(frozenset()), 'frozenset()') 252 self.assertEqual(pprint.pformat(frozenset(range(3))), 'frozenset({0, 1, 2})') 253 cube_repr_tgt = """\ 254{frozenset(): frozenset({frozenset({2}), frozenset({0}), frozenset({1})}), 255 frozenset({0}): frozenset({frozenset(), 256 frozenset({0, 2}), 257 frozenset({0, 1})}), 258 frozenset({1}): frozenset({frozenset(), 259 frozenset({1, 2}), 260 frozenset({0, 1})}), 261 frozenset({2}): frozenset({frozenset(), 262 frozenset({1, 2}), 263 frozenset({0, 2})}), 264 frozenset({1, 2}): frozenset({frozenset({2}), 265 frozenset({1}), 266 frozenset({0, 1, 2})}), 267 frozenset({0, 2}): frozenset({frozenset({2}), 268 frozenset({0}), 269 frozenset({0, 1, 2})}), 270 frozenset({0, 1}): frozenset({frozenset({0}), 271 frozenset({1}), 272 frozenset({0, 1, 2})}), 273 frozenset({0, 1, 2}): frozenset({frozenset({1, 2}), 274 frozenset({0, 2}), 275 frozenset({0, 1})})}""" 276 cube = test.test_set.cube(3) 277 self.assertEqual(pprint.pformat(cube), cube_repr_tgt) 278 cubo_repr_tgt = """\ 279{frozenset({frozenset({0, 2}), frozenset({0})}): frozenset({frozenset({frozenset({0, 280 2}), 281 frozenset({0, 282 1, 283 2})}), 284 frozenset({frozenset({0}), 285 frozenset({0, 286 1})}), 287 frozenset({frozenset(), 288 frozenset({0})}), 289 frozenset({frozenset({2}), 290 frozenset({0, 291 2})})}), 292 frozenset({frozenset({0, 1}), frozenset({1})}): frozenset({frozenset({frozenset({0, 293 1}), 294 frozenset({0, 295 1, 296 2})}), 297 frozenset({frozenset({0}), 298 frozenset({0, 299 1})}), 300 frozenset({frozenset({1}), 301 frozenset({1, 302 2})}), 303 frozenset({frozenset(), 304 frozenset({1})})}), 305 frozenset({frozenset({1, 2}), frozenset({1})}): frozenset({frozenset({frozenset({1, 306 2}), 307 frozenset({0, 308 1, 309 2})}), 310 frozenset({frozenset({2}), 311 frozenset({1, 312 2})}), 313 frozenset({frozenset(), 314 frozenset({1})}), 315 frozenset({frozenset({1}), 316 frozenset({0, 317 1})})}), 318 frozenset({frozenset({1, 2}), frozenset({2})}): frozenset({frozenset({frozenset({1, 319 2}), 320 frozenset({0, 321 1, 322 2})}), 323 frozenset({frozenset({1}), 324 frozenset({1, 325 2})}), 326 frozenset({frozenset({2}), 327 frozenset({0, 328 2})}), 329 frozenset({frozenset(), 330 frozenset({2})})}), 331 frozenset({frozenset(), frozenset({0})}): frozenset({frozenset({frozenset({0}), 332 frozenset({0, 333 1})}), 334 frozenset({frozenset({0}), 335 frozenset({0, 336 2})}), 337 frozenset({frozenset(), 338 frozenset({1})}), 339 frozenset({frozenset(), 340 frozenset({2})})}), 341 frozenset({frozenset(), frozenset({1})}): frozenset({frozenset({frozenset(), 342 frozenset({0})}), 343 frozenset({frozenset({1}), 344 frozenset({1, 345 2})}), 346 frozenset({frozenset(), 347 frozenset({2})}), 348 frozenset({frozenset({1}), 349 frozenset({0, 350 1})})}), 351 frozenset({frozenset({2}), frozenset()}): frozenset({frozenset({frozenset({2}), 352 frozenset({1, 353 2})}), 354 frozenset({frozenset(), 355 frozenset({0})}), 356 frozenset({frozenset(), 357 frozenset({1})}), 358 frozenset({frozenset({2}), 359 frozenset({0, 360 2})})}), 361 frozenset({frozenset({0, 1, 2}), frozenset({0, 1})}): frozenset({frozenset({frozenset({1, 362 2}), 363 frozenset({0, 364 1, 365 2})}), 366 frozenset({frozenset({0, 367 2}), 368 frozenset({0, 369 1, 370 2})}), 371 frozenset({frozenset({0}), 372 frozenset({0, 373 1})}), 374 frozenset({frozenset({1}), 375 frozenset({0, 376 1})})}), 377 frozenset({frozenset({0}), frozenset({0, 1})}): frozenset({frozenset({frozenset(), 378 frozenset({0})}), 379 frozenset({frozenset({0, 380 1}), 381 frozenset({0, 382 1, 383 2})}), 384 frozenset({frozenset({0}), 385 frozenset({0, 386 2})}), 387 frozenset({frozenset({1}), 388 frozenset({0, 389 1})})}), 390 frozenset({frozenset({2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({0, 391 2}), 392 frozenset({0, 393 1, 394 2})}), 395 frozenset({frozenset({2}), 396 frozenset({1, 397 2})}), 398 frozenset({frozenset({0}), 399 frozenset({0, 400 2})}), 401 frozenset({frozenset(), 402 frozenset({2})})}), 403 frozenset({frozenset({0, 1, 2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({1, 404 2}), 405 frozenset({0, 406 1, 407 2})}), 408 frozenset({frozenset({0, 409 1}), 410 frozenset({0, 411 1, 412 2})}), 413 frozenset({frozenset({0}), 414 frozenset({0, 415 2})}), 416 frozenset({frozenset({2}), 417 frozenset({0, 418 2})})}), 419 frozenset({frozenset({1, 2}), frozenset({0, 1, 2})}): frozenset({frozenset({frozenset({0, 420 2}), 421 frozenset({0, 422 1, 423 2})}), 424 frozenset({frozenset({0, 425 1}), 426 frozenset({0, 427 1, 428 2})}), 429 frozenset({frozenset({2}), 430 frozenset({1, 431 2})}), 432 frozenset({frozenset({1}), 433 frozenset({1, 434 2})})})}""" 435 436 cubo = test.test_set.linegraph(cube) 437 self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt) 438 439 def test_depth(self) -> None: 440 nested_tuple = (1, (2, (3, (4, (5, 6))))) 441 nested_dict = {1: {2: {3: {4: {5: {6: 6}}}}}} 442 nested_list = [1, [2, [3, [4, [5, [6, []]]]]]] 443 self.assertEqual(pprint.pformat(nested_tuple), repr(nested_tuple)) 444 self.assertEqual(pprint.pformat(nested_dict), repr(nested_dict)) 445 self.assertEqual(pprint.pformat(nested_list), repr(nested_list)) 446 447 lv1_tuple = '(1, (...))' 448 lv1_dict = '{1: {...}}' 449 lv1_list = '[1, [...]]' 450 self.assertEqual(pprint.pformat(nested_tuple, depth=1), lv1_tuple) 451 self.assertEqual(pprint.pformat(nested_dict, depth=1), lv1_dict) 452 self.assertEqual(pprint.pformat(nested_list, depth=1), lv1_list) 453 454 def test_sort_unorderable_values(self) -> None: 455 # Issue 3976: sorted pprints fail for unorderable values. 456 n = 20 457 keys = [Unorderable() for i in range(n)] 458 random.shuffle(keys) 459 skeys = sorted(keys, key=id) 460 clean = lambda s: s.replace(' ', '').replace('\n','') # type: Callable[[str], str] 461 462 self.assertEqual(clean(pprint.pformat(set(keys))), 463 '{' + ','.join(map(repr, skeys)) + '}') 464 self.assertEqual(clean(pprint.pformat(frozenset(keys))), 465 'frozenset({' + ','.join(map(repr, skeys)) + '})') 466 self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys))), 467 '{' + ','.join('%r:None' % k for k in skeys) + '}') 468 469class DottedPrettyPrinter(pprint.PrettyPrinter): 470 471 def format(self, object: object, context: Dict[int, Any], maxlevels: int, 472 level: int) -> Tuple[str, int, int]: 473 if isinstance(object, str): 474 if ' ' in object: 475 return repr(object), 1, 0 476 else: 477 return object, 0, 0 478 else: 479 return pprint.PrettyPrinter.format( 480 self, object, context, maxlevels, level) 481 482 483def test_main() -> None: 484 test.support.run_unittest(QueryTestCase) 485 486 487if __name__ == "__main__": 488 test_main() 489