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