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