##// END OF EJS Templates
Merge pull request #13714 from frenzymadness/fix_xxlimited...
Matthias Bussonnier -
r27711:b9c796a6 merge
parent child Browse files
Show More
@@ -1,536 +1,539 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 expected_output = (
145 "xxlimited.Null" if sys.version_info < (3, 10, 6) else "xxlimited_35.Null"
146 )
144 147 xxlimited = pytest.importorskip(module_name)
145 148 output = pretty.pretty(xxlimited.Null)
146 assert output == "xxlimited.Null"
149 assert output == expected_output
147 150
148 151
149 152 def test_pprint_nomod():
150 153 """
151 154 Test that pprint works for classes with no __module__.
152 155 """
153 156 output = pretty.pretty(NoModule)
154 157 assert output == "NoModule"
155 158
156 159
157 160 def test_pprint_break():
158 161 """
159 162 Test that p.break_ produces expected output
160 163 """
161 164 output = pretty.pretty(Breaking())
162 165 expected = "TG: Breaking(\n ):"
163 166 assert output == expected
164 167
165 168 def test_pprint_break_repr():
166 169 """
167 170 Test that p.break_ is used in repr
168 171 """
169 172 output = pretty.pretty([[BreakingRepr()]])
170 173 expected = "[[Breaking(\n )]]"
171 174 assert output == expected
172 175
173 176 output = pretty.pretty([[BreakingRepr()]*2])
174 177 expected = "[[Breaking(\n ),\n Breaking(\n )]]"
175 178 assert output == expected
176 179
177 180 def test_bad_repr():
178 181 """Don't catch bad repr errors"""
179 182 with pytest.raises(ZeroDivisionError):
180 183 pretty.pretty(BadRepr())
181 184
182 185 class BadException(Exception):
183 186 def __str__(self):
184 187 return -1
185 188
186 189 class ReallyBadRepr(object):
187 190 __module__ = 1
188 191 @property
189 192 def __class__(self):
190 193 raise ValueError("I am horrible")
191 194
192 195 def __repr__(self):
193 196 raise BadException()
194 197
195 198 def test_really_bad_repr():
196 199 with pytest.raises(BadException):
197 200 pretty.pretty(ReallyBadRepr())
198 201
199 202
200 203 class SA(object):
201 204 pass
202 205
203 206 class SB(SA):
204 207 pass
205 208
206 209 class TestsPretty(unittest.TestCase):
207 210
208 211 def test_super_repr(self):
209 212 # "<super: module_name.SA, None>"
210 213 output = pretty.pretty(super(SA))
211 214 self.assertRegex(output, r"<super: \S+.SA, None>")
212 215
213 216 # "<super: module_name.SA, <module_name.SB at 0x...>>"
214 217 sb = SB()
215 218 output = pretty.pretty(super(SA, sb))
216 219 self.assertRegex(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
217 220
218 221
219 222 def test_long_list(self):
220 223 lis = list(range(10000))
221 224 p = pretty.pretty(lis)
222 225 last2 = p.rsplit('\n', 2)[-2:]
223 226 self.assertEqual(last2, [' 999,', ' ...]'])
224 227
225 228 def test_long_set(self):
226 229 s = set(range(10000))
227 230 p = pretty.pretty(s)
228 231 last2 = p.rsplit('\n', 2)[-2:]
229 232 self.assertEqual(last2, [' 999,', ' ...}'])
230 233
231 234 def test_long_tuple(self):
232 235 tup = tuple(range(10000))
233 236 p = pretty.pretty(tup)
234 237 last2 = p.rsplit('\n', 2)[-2:]
235 238 self.assertEqual(last2, [' 999,', ' ...)'])
236 239
237 240 def test_long_dict(self):
238 241 d = { n:n for n in range(10000) }
239 242 p = pretty.pretty(d)
240 243 last2 = p.rsplit('\n', 2)[-2:]
241 244 self.assertEqual(last2, [' 999: 999,', ' ...}'])
242 245
243 246 def test_unbound_method(self):
244 247 output = pretty.pretty(MyObj.somemethod)
245 248 self.assertIn('MyObj.somemethod', output)
246 249
247 250
248 251 class MetaClass(type):
249 252 def __new__(cls, name):
250 253 return type.__new__(cls, name, (object,), {'name': name})
251 254
252 255 def __repr__(self):
253 256 return "[CUSTOM REPR FOR CLASS %s]" % self.name
254 257
255 258
256 259 ClassWithMeta = MetaClass('ClassWithMeta')
257 260
258 261
259 262 def test_metaclass_repr():
260 263 output = pretty.pretty(ClassWithMeta)
261 264 assert output == "[CUSTOM REPR FOR CLASS ClassWithMeta]"
262 265
263 266
264 267 def test_unicode_repr():
265 268 u = u"üniçodé"
266 269 ustr = u
267 270
268 271 class C(object):
269 272 def __repr__(self):
270 273 return ustr
271 274
272 275 c = C()
273 276 p = pretty.pretty(c)
274 277 assert p == u
275 278 p = pretty.pretty([c])
276 279 assert p == "[%s]" % u
277 280
278 281
279 282 def test_basic_class():
280 283 def type_pprint_wrapper(obj, p, cycle):
281 284 if obj is MyObj:
282 285 type_pprint_wrapper.called = True
283 286 return pretty._type_pprint(obj, p, cycle)
284 287 type_pprint_wrapper.called = False
285 288
286 289 stream = StringIO()
287 290 printer = pretty.RepresentationPrinter(stream)
288 291 printer.type_pprinters[type] = type_pprint_wrapper
289 292 printer.pretty(MyObj)
290 293 printer.flush()
291 294 output = stream.getvalue()
292 295
293 296 assert output == "%s.MyObj" % __name__
294 297 assert type_pprint_wrapper.called is True
295 298
296 299
297 300 def test_collections_userlist():
298 301 # Create userlist with cycle
299 302 a = UserList()
300 303 a.append(a)
301 304
302 305 cases = [
303 306 (UserList(), "UserList([])"),
304 307 (
305 308 UserList(i for i in range(1000, 1020)),
306 309 "UserList([1000,\n"
307 310 " 1001,\n"
308 311 " 1002,\n"
309 312 " 1003,\n"
310 313 " 1004,\n"
311 314 " 1005,\n"
312 315 " 1006,\n"
313 316 " 1007,\n"
314 317 " 1008,\n"
315 318 " 1009,\n"
316 319 " 1010,\n"
317 320 " 1011,\n"
318 321 " 1012,\n"
319 322 " 1013,\n"
320 323 " 1014,\n"
321 324 " 1015,\n"
322 325 " 1016,\n"
323 326 " 1017,\n"
324 327 " 1018,\n"
325 328 " 1019])",
326 329 ),
327 330 (a, "UserList([UserList(...)])"),
328 331 ]
329 332 for obj, expected in cases:
330 333 assert pretty.pretty(obj) == expected
331 334
332 335
333 336 # TODO : pytest.mark.parametrise once nose is gone.
334 337 def test_collections_defaultdict():
335 338 # Create defaultdicts with cycles
336 339 a = defaultdict()
337 340 a.default_factory = a
338 341 b = defaultdict(list)
339 342 b['key'] = b
340 343
341 344 # Dictionary order cannot be relied on, test against single keys.
342 345 cases = [
343 346 (defaultdict(list), 'defaultdict(list, {})'),
344 347 (defaultdict(list, {'key': '-' * 50}),
345 348 "defaultdict(list,\n"
346 349 " {'key': '--------------------------------------------------'})"),
347 350 (a, 'defaultdict(defaultdict(...), {})'),
348 351 (b, "defaultdict(list, {'key': defaultdict(...)})"),
349 352 ]
350 353 for obj, expected in cases:
351 354 assert pretty.pretty(obj) == expected
352 355
353 356
354 357 # TODO : pytest.mark.parametrise once nose is gone.
355 358 def test_collections_ordereddict():
356 359 # Create OrderedDict with cycle
357 360 a = OrderedDict()
358 361 a['key'] = a
359 362
360 363 cases = [
361 364 (OrderedDict(), 'OrderedDict()'),
362 365 (OrderedDict((i, i) for i in range(1000, 1010)),
363 366 'OrderedDict([(1000, 1000),\n'
364 367 ' (1001, 1001),\n'
365 368 ' (1002, 1002),\n'
366 369 ' (1003, 1003),\n'
367 370 ' (1004, 1004),\n'
368 371 ' (1005, 1005),\n'
369 372 ' (1006, 1006),\n'
370 373 ' (1007, 1007),\n'
371 374 ' (1008, 1008),\n'
372 375 ' (1009, 1009)])'),
373 376 (a, "OrderedDict([('key', OrderedDict(...))])"),
374 377 ]
375 378 for obj, expected in cases:
376 379 assert pretty.pretty(obj) == expected
377 380
378 381
379 382 # TODO : pytest.mark.parametrise once nose is gone.
380 383 def test_collections_deque():
381 384 # Create deque with cycle
382 385 a = deque()
383 386 a.append(a)
384 387
385 388 cases = [
386 389 (deque(), 'deque([])'),
387 390 (deque(i for i in range(1000, 1020)),
388 391 'deque([1000,\n'
389 392 ' 1001,\n'
390 393 ' 1002,\n'
391 394 ' 1003,\n'
392 395 ' 1004,\n'
393 396 ' 1005,\n'
394 397 ' 1006,\n'
395 398 ' 1007,\n'
396 399 ' 1008,\n'
397 400 ' 1009,\n'
398 401 ' 1010,\n'
399 402 ' 1011,\n'
400 403 ' 1012,\n'
401 404 ' 1013,\n'
402 405 ' 1014,\n'
403 406 ' 1015,\n'
404 407 ' 1016,\n'
405 408 ' 1017,\n'
406 409 ' 1018,\n'
407 410 ' 1019])'),
408 411 (a, 'deque([deque(...)])'),
409 412 ]
410 413 for obj, expected in cases:
411 414 assert pretty.pretty(obj) == expected
412 415
413 416
414 417 # TODO : pytest.mark.parametrise once nose is gone.
415 418 def test_collections_counter():
416 419 class MyCounter(Counter):
417 420 pass
418 421 cases = [
419 422 (Counter(), 'Counter()'),
420 423 (Counter(a=1), "Counter({'a': 1})"),
421 424 (MyCounter(a=1), "MyCounter({'a': 1})"),
422 425 ]
423 426 for obj, expected in cases:
424 427 assert pretty.pretty(obj) == expected
425 428
426 429 # TODO : pytest.mark.parametrise once nose is gone.
427 430 def test_mappingproxy():
428 431 MP = types.MappingProxyType
429 432 underlying_dict = {}
430 433 mp_recursive = MP(underlying_dict)
431 434 underlying_dict[2] = mp_recursive
432 435 underlying_dict[3] = underlying_dict
433 436
434 437 cases = [
435 438 (MP({}), "mappingproxy({})"),
436 439 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
437 440 (MP({k: k.upper() for k in string.ascii_lowercase}),
438 441 "mappingproxy({'a': 'A',\n"
439 442 " 'b': 'B',\n"
440 443 " 'c': 'C',\n"
441 444 " 'd': 'D',\n"
442 445 " 'e': 'E',\n"
443 446 " 'f': 'F',\n"
444 447 " 'g': 'G',\n"
445 448 " 'h': 'H',\n"
446 449 " 'i': 'I',\n"
447 450 " 'j': 'J',\n"
448 451 " 'k': 'K',\n"
449 452 " 'l': 'L',\n"
450 453 " 'm': 'M',\n"
451 454 " 'n': 'N',\n"
452 455 " 'o': 'O',\n"
453 456 " 'p': 'P',\n"
454 457 " 'q': 'Q',\n"
455 458 " 'r': 'R',\n"
456 459 " 's': 'S',\n"
457 460 " 't': 'T',\n"
458 461 " 'u': 'U',\n"
459 462 " 'v': 'V',\n"
460 463 " 'w': 'W',\n"
461 464 " 'x': 'X',\n"
462 465 " 'y': 'Y',\n"
463 466 " 'z': 'Z'})"),
464 467 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
465 468 (underlying_dict,
466 469 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
467 470 ]
468 471 for obj, expected in cases:
469 472 assert pretty.pretty(obj) == expected
470 473
471 474
472 475 # TODO : pytest.mark.parametrise once nose is gone.
473 476 def test_simplenamespace():
474 477 SN = types.SimpleNamespace
475 478
476 479 sn_recursive = SN()
477 480 sn_recursive.first = sn_recursive
478 481 sn_recursive.second = sn_recursive
479 482 cases = [
480 483 (SN(), "namespace()"),
481 484 (SN(x=SN()), "namespace(x=namespace())"),
482 485 (SN(a_long_name=[SN(s=string.ascii_lowercase)]*3, a_short_name=None),
483 486 "namespace(a_long_name=[namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
484 487 " namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
485 488 " namespace(s='abcdefghijklmnopqrstuvwxyz')],\n"
486 489 " a_short_name=None)"),
487 490 (sn_recursive, "namespace(first=namespace(...), second=namespace(...))"),
488 491 ]
489 492 for obj, expected in cases:
490 493 assert pretty.pretty(obj) == expected
491 494
492 495
493 496 def test_pretty_environ():
494 497 dict_repr = pretty.pretty(dict(os.environ))
495 498 # reindent to align with 'environ' prefix
496 499 dict_indented = dict_repr.replace('\n', '\n' + (' ' * len('environ')))
497 500 env_repr = pretty.pretty(os.environ)
498 501 assert env_repr == "environ" + dict_indented
499 502
500 503
501 504 def test_function_pretty():
502 505 "Test pretty print of function"
503 506 # posixpath is a pure python module, its interface is consistent
504 507 # across Python distributions
505 508 import posixpath
506 509
507 510 assert pretty.pretty(posixpath.join) == "<function posixpath.join(a, *p)>"
508 511
509 512 # custom function
510 513 def meaning_of_life(question=None):
511 514 if question:
512 515 return 42
513 516 return "Don't panic"
514 517
515 518 assert "meaning_of_life(question=None)" in pretty.pretty(meaning_of_life)
516 519
517 520
518 521 class OrderedCounter(Counter, OrderedDict):
519 522 'Counter that remembers the order elements are first encountered'
520 523
521 524 def __repr__(self):
522 525 return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
523 526
524 527 def __reduce__(self):
525 528 return self.__class__, (OrderedDict(self),)
526 529
527 530 class MySet(set): # Override repr of a basic type
528 531 def __repr__(self):
529 532 return 'mine'
530 533
531 534 def test_custom_repr():
532 535 """A custom repr should override a pretty printer for a parent type"""
533 536 oc = OrderedCounter("abracadabra")
534 537 assert "OrderedCounter(OrderedDict" in pretty.pretty(oc)
535 538
536 539 assert pretty.pretty(MySet()) == "mine"
General Comments 0
You need to be logged in to leave comments. Login now