##// END OF EJS Templates
Adding comma so that Lint with Darker check passes
Jono Tassia -
Show More
@@ -1,540 +1,540 b''
1 1 # coding: utf-8
2 2 """Tests for IPython.lib.pretty."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from collections import Counter, defaultdict, deque, OrderedDict, UserList
9 9 import os
10 10 import pytest
11 11 import types
12 12 import string
13 13 import sys
14 14 import unittest
15 15
16 16 import pytest
17 17
18 18 from IPython.lib import pretty
19 19
20 20 from io import StringIO
21 21
22 22
23 23 class MyList(object):
24 24 def __init__(self, content):
25 25 self.content = content
26 26 def _repr_pretty_(self, p, cycle):
27 27 if cycle:
28 28 p.text("MyList(...)")
29 29 else:
30 30 with p.group(3, "MyList(", ")"):
31 31 for (i, child) in enumerate(self.content):
32 32 if i:
33 33 p.text(",")
34 34 p.breakable()
35 35 else:
36 36 p.breakable("")
37 37 p.pretty(child)
38 38
39 39
40 40 class MyDict(dict):
41 41 def _repr_pretty_(self, p, cycle):
42 42 p.text("MyDict(...)")
43 43
44 44 class MyObj(object):
45 45 def somemethod(self):
46 46 pass
47 47
48 48
49 49 class Dummy1(object):
50 50 def _repr_pretty_(self, p, cycle):
51 51 p.text("Dummy1(...)")
52 52
53 53 class Dummy2(Dummy1):
54 54 _repr_pretty_ = None
55 55
56 56 class NoModule(object):
57 57 pass
58 58
59 59 NoModule.__module__ = None
60 60
61 61 class Breaking(object):
62 62 def _repr_pretty_(self, p, cycle):
63 63 with p.group(4,"TG: ",":"):
64 64 p.text("Breaking(")
65 65 p.break_()
66 66 p.text(")")
67 67
68 68 class BreakingRepr(object):
69 69 def __repr__(self):
70 70 return "Breaking(\n)"
71 71
72 72 class BadRepr(object):
73 73 def __repr__(self):
74 74 return 1/0
75 75
76 76
77 77 def test_indentation():
78 78 """Test correct indentation in groups"""
79 79 count = 40
80 80 gotoutput = pretty.pretty(MyList(range(count)))
81 81 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
82 82
83 83 assert gotoutput == expectedoutput
84 84
85 85
86 86 def test_dispatch():
87 87 """
88 88 Test correct dispatching: The _repr_pretty_ method for MyDict
89 89 must be found before the registered printer for dict.
90 90 """
91 91 gotoutput = pretty.pretty(MyDict())
92 92 expectedoutput = "MyDict(...)"
93 93
94 94 assert gotoutput == expectedoutput
95 95
96 96
97 97 def test_callability_checking():
98 98 """
99 99 Test that the _repr_pretty_ method is tested for callability and skipped if
100 100 not.
101 101 """
102 102 gotoutput = pretty.pretty(Dummy2())
103 103 expectedoutput = "Dummy1(...)"
104 104
105 105 assert gotoutput == expectedoutput
106 106
107 107
108 108 @pytest.mark.parametrize(
109 109 "obj,expected_output",
110 110 zip(
111 111 [
112 112 set(),
113 113 frozenset(),
114 114 set([1]),
115 115 frozenset([1]),
116 116 set([1, 2]),
117 117 frozenset([1, 2]),
118 118 set([-1, -2, -3]),
119 119 ],
120 120 [
121 121 "set()",
122 122 "frozenset()",
123 123 "{1}",
124 124 "frozenset({1})",
125 125 "{1, 2}",
126 126 "frozenset({1, 2})",
127 127 "{-3, -2, -1}",
128 128 ],
129 129 ),
130 130 )
131 131 def test_sets(obj, expected_output):
132 132 """
133 133 Test that set and frozenset use Python 3 formatting.
134 134 """
135 135 got_output = pretty.pretty(obj)
136 136 assert got_output == expected_output
137 137
138 138
139 139 def test_pprint_heap_allocated_type():
140 140 """
141 141 Test that pprint works for heap allocated types.
142 142 """
143 143 module_name = "xxlimited" if sys.version_info < (3, 10) else "xxlimited_35"
144 144 expected_output = (
145 145 "xxlimited.Null" if sys.version_info < (3, 10, 6) else "xxlimited_35.Null"
146 146 )
147 147 xxlimited = pytest.importorskip(module_name)
148 148 output = pretty.pretty(xxlimited.Null)
149 149 assert output == expected_output
150 150
151 151
152 152 def test_pprint_nomod():
153 153 """
154 154 Test that pprint works for classes with no __module__.
155 155 """
156 156 output = pretty.pretty(NoModule)
157 157 assert output == "NoModule"
158 158
159 159
160 160 def test_pprint_break():
161 161 """
162 162 Test that p.break_ produces expected output
163 163 """
164 164 output = pretty.pretty(Breaking())
165 165 expected = "TG: Breaking(\n ):"
166 166 assert output == expected
167 167
168 168 def test_pprint_break_repr():
169 169 """
170 170 Test that p.break_ is used in repr
171 171 """
172 172 output = pretty.pretty([[BreakingRepr()]])
173 173 expected = "[[Breaking(\n )]]"
174 174 assert output == expected
175 175
176 176 output = pretty.pretty([[BreakingRepr()]*2])
177 177 expected = "[[Breaking(\n ),\n Breaking(\n )]]"
178 178 assert output == expected
179 179
180 180 def test_bad_repr():
181 181 """Don't catch bad repr errors"""
182 182 with pytest.raises(ZeroDivisionError):
183 183 pretty.pretty(BadRepr())
184 184
185 185 class BadException(Exception):
186 186 def __str__(self):
187 187 return -1
188 188
189 189 class ReallyBadRepr(object):
190 190 __module__ = 1
191 191 @property
192 192 def __class__(self):
193 193 raise ValueError("I am horrible")
194 194
195 195 def __repr__(self):
196 196 raise BadException()
197 197
198 198 def test_really_bad_repr():
199 199 with pytest.raises(BadException):
200 200 pretty.pretty(ReallyBadRepr())
201 201
202 202
203 203 class SA(object):
204 204 pass
205 205
206 206 class SB(SA):
207 207 pass
208 208
209 209 class TestsPretty(unittest.TestCase):
210 210
211 211 def test_super_repr(self):
212 212 # "<super: module_name.SA, None>"
213 213 output = pretty.pretty(super(SA))
214 214 self.assertRegex(output, r"<super: \S+.SA, None>")
215 215
216 216 # "<super: module_name.SA, <module_name.SB at 0x...>>"
217 217 sb = SB()
218 218 output = pretty.pretty(super(SA, sb))
219 219 self.assertRegex(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
220 220
221 221
222 222 def test_long_list(self):
223 223 lis = list(range(10000))
224 224 p = pretty.pretty(lis)
225 225 last2 = p.rsplit('\n', 2)[-2:]
226 226 self.assertEqual(last2, [' 999,', ' ...]'])
227 227
228 228 def test_long_set(self):
229 229 s = set(range(10000))
230 230 p = pretty.pretty(s)
231 231 last2 = p.rsplit('\n', 2)[-2:]
232 232 self.assertEqual(last2, [' 999,', ' ...}'])
233 233
234 234 def test_long_tuple(self):
235 235 tup = tuple(range(10000))
236 236 p = pretty.pretty(tup)
237 237 last2 = p.rsplit('\n', 2)[-2:]
238 238 self.assertEqual(last2, [' 999,', ' ...)'])
239 239
240 240 def test_long_dict(self):
241 241 d = { n:n for n in range(10000) }
242 242 p = pretty.pretty(d)
243 243 last2 = p.rsplit('\n', 2)[-2:]
244 244 self.assertEqual(last2, [' 999: 999,', ' ...}'])
245 245
246 246 def test_unbound_method(self):
247 247 output = pretty.pretty(MyObj.somemethod)
248 248 self.assertIn('MyObj.somemethod', output)
249 249
250 250
251 251 class MetaClass(type):
252 252 def __new__(cls, name):
253 253 return type.__new__(cls, name, (object,), {'name': name})
254 254
255 255 def __repr__(self):
256 256 return "[CUSTOM REPR FOR CLASS %s]" % self.name
257 257
258 258
259 259 ClassWithMeta = MetaClass('ClassWithMeta')
260 260
261 261
262 262 def test_metaclass_repr():
263 263 output = pretty.pretty(ClassWithMeta)
264 264 assert output == "[CUSTOM REPR FOR CLASS ClassWithMeta]"
265 265
266 266
267 267 def test_unicode_repr():
268 268 u = u"üniçodé"
269 269 ustr = u
270 270
271 271 class C(object):
272 272 def __repr__(self):
273 273 return ustr
274 274
275 275 c = C()
276 276 p = pretty.pretty(c)
277 277 assert p == u
278 278 p = pretty.pretty([c])
279 279 assert p == "[%s]" % u
280 280
281 281
282 282 def test_basic_class():
283 283 def type_pprint_wrapper(obj, p, cycle):
284 284 if obj is MyObj:
285 285 type_pprint_wrapper.called = True
286 286 return pretty._type_pprint(obj, p, cycle)
287 287 type_pprint_wrapper.called = False
288 288
289 289 stream = StringIO()
290 290 printer = pretty.RepresentationPrinter(stream)
291 291 printer.type_pprinters[type] = type_pprint_wrapper
292 292 printer.pretty(MyObj)
293 293 printer.flush()
294 294 output = stream.getvalue()
295 295
296 296 assert output == "%s.MyObj" % __name__
297 297 assert type_pprint_wrapper.called is True
298 298
299 299
300 300 def test_collections_userlist():
301 301 # Create userlist with cycle
302 302 a = UserList()
303 303 a.append(a)
304 304
305 305 cases = [
306 306 (UserList(), "UserList([])"),
307 307 (
308 308 UserList(i for i in range(1000, 1020)),
309 309 "UserList([1000,\n"
310 310 " 1001,\n"
311 311 " 1002,\n"
312 312 " 1003,\n"
313 313 " 1004,\n"
314 314 " 1005,\n"
315 315 " 1006,\n"
316 316 " 1007,\n"
317 317 " 1008,\n"
318 318 " 1009,\n"
319 319 " 1010,\n"
320 320 " 1011,\n"
321 321 " 1012,\n"
322 322 " 1013,\n"
323 323 " 1014,\n"
324 324 " 1015,\n"
325 325 " 1016,\n"
326 326 " 1017,\n"
327 327 " 1018,\n"
328 328 " 1019])",
329 329 ),
330 330 (a, "UserList([UserList(...)])"),
331 331 ]
332 332 for obj, expected in cases:
333 333 assert pretty.pretty(obj) == expected
334 334
335 335
336 336 # TODO : pytest.mark.parametrise once nose is gone.
337 337 def test_collections_defaultdict():
338 338 # Create defaultdicts with cycles
339 339 a = defaultdict()
340 340 a.default_factory = a
341 341 b = defaultdict(list)
342 342 b['key'] = b
343 343
344 344 # Dictionary order cannot be relied on, test against single keys.
345 345 cases = [
346 346 (defaultdict(list), 'defaultdict(list, {})'),
347 347 (defaultdict(list, {'key': '-' * 50}),
348 348 "defaultdict(list,\n"
349 349 " {'key': '--------------------------------------------------'})"),
350 350 (a, 'defaultdict(defaultdict(...), {})'),
351 351 (b, "defaultdict(list, {'key': defaultdict(...)})"),
352 352 ]
353 353 for obj, expected in cases:
354 354 assert pretty.pretty(obj) == expected
355 355
356 356
357 357 # TODO : pytest.mark.parametrise once nose is gone.
358 358 def test_collections_ordereddict():
359 359 # Create OrderedDict with cycle
360 360 a = OrderedDict()
361 361 a['key'] = a
362 362
363 363 cases = [
364 364 (OrderedDict(), 'OrderedDict()'),
365 365 (OrderedDict((i, i) for i in range(1000, 1010)),
366 366 'OrderedDict([(1000, 1000),\n'
367 367 ' (1001, 1001),\n'
368 368 ' (1002, 1002),\n'
369 369 ' (1003, 1003),\n'
370 370 ' (1004, 1004),\n'
371 371 ' (1005, 1005),\n'
372 372 ' (1006, 1006),\n'
373 373 ' (1007, 1007),\n'
374 374 ' (1008, 1008),\n'
375 375 ' (1009, 1009)])'),
376 376 (a, "OrderedDict([('key', OrderedDict(...))])"),
377 377 ]
378 378 for obj, expected in cases:
379 379 assert pretty.pretty(obj) == expected
380 380
381 381
382 382 # TODO : pytest.mark.parametrise once nose is gone.
383 383 def test_collections_deque():
384 384 # Create deque with cycle
385 385 a = deque()
386 386 a.append(a)
387 387
388 388 cases = [
389 389 (deque(), 'deque([])'),
390 390 (deque(i for i in range(1000, 1020)),
391 391 'deque([1000,\n'
392 392 ' 1001,\n'
393 393 ' 1002,\n'
394 394 ' 1003,\n'
395 395 ' 1004,\n'
396 396 ' 1005,\n'
397 397 ' 1006,\n'
398 398 ' 1007,\n'
399 399 ' 1008,\n'
400 400 ' 1009,\n'
401 401 ' 1010,\n'
402 402 ' 1011,\n'
403 403 ' 1012,\n'
404 404 ' 1013,\n'
405 405 ' 1014,\n'
406 406 ' 1015,\n'
407 407 ' 1016,\n'
408 408 ' 1017,\n'
409 409 ' 1018,\n'
410 410 ' 1019])'),
411 411 (a, 'deque([deque(...)])'),
412 412 ]
413 413 for obj, expected in cases:
414 414 assert pretty.pretty(obj) == expected
415 415
416 416
417 417 # TODO : pytest.mark.parametrise once nose is gone.
418 418 def test_collections_counter():
419 419 class MyCounter(Counter):
420 420 pass
421 421 cases = [
422 422 (Counter(), 'Counter()'),
423 423 (Counter(a=1), "Counter({'a': 1})"),
424 424 (MyCounter(a=1), "MyCounter({'a': 1})"),
425 (Counter(a=1, c=22), "Counter({'c': 22, 'a': 1})")
425 (Counter(a=1, c=22), "Counter({'c': 22, 'a': 1})"),
426 426 ]
427 427 for obj, expected in cases:
428 428 assert pretty.pretty(obj) == expected
429 429
430 430 # TODO : pytest.mark.parametrise once nose is gone.
431 431 def test_mappingproxy():
432 432 MP = types.MappingProxyType
433 433 underlying_dict = {}
434 434 mp_recursive = MP(underlying_dict)
435 435 underlying_dict[2] = mp_recursive
436 436 underlying_dict[3] = underlying_dict
437 437
438 438 cases = [
439 439 (MP({}), "mappingproxy({})"),
440 440 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
441 441 (MP({k: k.upper() for k in string.ascii_lowercase}),
442 442 "mappingproxy({'a': 'A',\n"
443 443 " 'b': 'B',\n"
444 444 " 'c': 'C',\n"
445 445 " 'd': 'D',\n"
446 446 " 'e': 'E',\n"
447 447 " 'f': 'F',\n"
448 448 " 'g': 'G',\n"
449 449 " 'h': 'H',\n"
450 450 " 'i': 'I',\n"
451 451 " 'j': 'J',\n"
452 452 " 'k': 'K',\n"
453 453 " 'l': 'L',\n"
454 454 " 'm': 'M',\n"
455 455 " 'n': 'N',\n"
456 456 " 'o': 'O',\n"
457 457 " 'p': 'P',\n"
458 458 " 'q': 'Q',\n"
459 459 " 'r': 'R',\n"
460 460 " 's': 'S',\n"
461 461 " 't': 'T',\n"
462 462 " 'u': 'U',\n"
463 463 " 'v': 'V',\n"
464 464 " 'w': 'W',\n"
465 465 " 'x': 'X',\n"
466 466 " 'y': 'Y',\n"
467 467 " 'z': 'Z'})"),
468 468 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
469 469 (underlying_dict,
470 470 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
471 471 ]
472 472 for obj, expected in cases:
473 473 assert pretty.pretty(obj) == expected
474 474
475 475
476 476 # TODO : pytest.mark.parametrise once nose is gone.
477 477 def test_simplenamespace():
478 478 SN = types.SimpleNamespace
479 479
480 480 sn_recursive = SN()
481 481 sn_recursive.first = sn_recursive
482 482 sn_recursive.second = sn_recursive
483 483 cases = [
484 484 (SN(), "namespace()"),
485 485 (SN(x=SN()), "namespace(x=namespace())"),
486 486 (SN(a_long_name=[SN(s=string.ascii_lowercase)]*3, a_short_name=None),
487 487 "namespace(a_long_name=[namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
488 488 " namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
489 489 " namespace(s='abcdefghijklmnopqrstuvwxyz')],\n"
490 490 " a_short_name=None)"),
491 491 (sn_recursive, "namespace(first=namespace(...), second=namespace(...))"),
492 492 ]
493 493 for obj, expected in cases:
494 494 assert pretty.pretty(obj) == expected
495 495
496 496
497 497 def test_pretty_environ():
498 498 dict_repr = pretty.pretty(dict(os.environ))
499 499 # reindent to align with 'environ' prefix
500 500 dict_indented = dict_repr.replace('\n', '\n' + (' ' * len('environ')))
501 501 env_repr = pretty.pretty(os.environ)
502 502 assert env_repr == "environ" + dict_indented
503 503
504 504
505 505 def test_function_pretty():
506 506 "Test pretty print of function"
507 507 # posixpath is a pure python module, its interface is consistent
508 508 # across Python distributions
509 509 import posixpath
510 510
511 511 assert pretty.pretty(posixpath.join) == "<function posixpath.join(a, *p)>"
512 512
513 513 # custom function
514 514 def meaning_of_life(question=None):
515 515 if question:
516 516 return 42
517 517 return "Don't panic"
518 518
519 519 assert "meaning_of_life(question=None)" in pretty.pretty(meaning_of_life)
520 520
521 521
522 522 class OrderedCounter(Counter, OrderedDict):
523 523 'Counter that remembers the order elements are first encountered'
524 524
525 525 def __repr__(self):
526 526 return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
527 527
528 528 def __reduce__(self):
529 529 return self.__class__, (OrderedDict(self),)
530 530
531 531 class MySet(set): # Override repr of a basic type
532 532 def __repr__(self):
533 533 return 'mine'
534 534
535 535 def test_custom_repr():
536 536 """A custom repr should override a pretty printer for a parent type"""
537 537 oc = OrderedCounter("abracadabra")
538 538 assert "OrderedCounter(OrderedDict" in pretty.pretty(oc)
539 539
540 540 assert pretty.pretty(MySet()) == "mine"
General Comments 0
You need to be logged in to leave comments. Login now