##// END OF EJS Templates
Update test for displaying subclass instance
Thomas Kluyver -
Show More
@@ -1,533 +1,533
1 1 """Tests for the Formatters."""
2 2
3 3 import warnings
4 4 from math import pi
5 5
6 6 try:
7 7 import numpy
8 8 except:
9 9 numpy = None
10 10 import nose.tools as nt
11 11
12 12 from IPython import get_ipython
13 13 from traitlets.config import Config
14 14 from IPython.core.formatters import (
15 15 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
16 16 DisplayFormatter, JSONFormatter,
17 17 )
18 18 from IPython.utils.io import capture_output
19 19
20 20 class A(object):
21 21 def __repr__(self):
22 22 return 'A()'
23 23
24 24 class B(A):
25 25 def __repr__(self):
26 26 return 'B()'
27 27
28 28 class C:
29 29 pass
30 30
31 31 class BadRepr(object):
32 32 def __repr__(self):
33 33 raise ValueError("bad repr")
34 34
35 35 class BadPretty(object):
36 36 _repr_pretty_ = None
37 37
38 38 class GoodPretty(object):
39 39 def _repr_pretty_(self, pp, cycle):
40 40 pp.text('foo')
41 41
42 42 def __repr__(self):
43 43 return 'GoodPretty()'
44 44
45 45 def foo_printer(obj, pp, cycle):
46 46 pp.text('foo')
47 47
48 48 def test_pretty():
49 49 f = PlainTextFormatter()
50 50 f.for_type(A, foo_printer)
51 51 nt.assert_equal(f(A()), 'foo')
52 nt.assert_equal(f(B()), 'foo')
52 nt.assert_equal(f(B()), 'B()')
53 53 nt.assert_equal(f(GoodPretty()), 'foo')
54 54 # Just don't raise an exception for the following:
55 55 f(BadPretty())
56 56
57 57 f.pprint = False
58 58 nt.assert_equal(f(A()), 'A()')
59 59 nt.assert_equal(f(B()), 'B()')
60 60 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
61 61
62 62
63 63 def test_deferred():
64 64 f = PlainTextFormatter()
65 65
66 66 def test_precision():
67 67 """test various values for float_precision."""
68 68 f = PlainTextFormatter()
69 69 nt.assert_equal(f(pi), repr(pi))
70 70 f.float_precision = 0
71 71 if numpy:
72 72 po = numpy.get_printoptions()
73 73 nt.assert_equal(po['precision'], 0)
74 74 nt.assert_equal(f(pi), '3')
75 75 f.float_precision = 2
76 76 if numpy:
77 77 po = numpy.get_printoptions()
78 78 nt.assert_equal(po['precision'], 2)
79 79 nt.assert_equal(f(pi), '3.14')
80 80 f.float_precision = '%g'
81 81 if numpy:
82 82 po = numpy.get_printoptions()
83 83 nt.assert_equal(po['precision'], 2)
84 84 nt.assert_equal(f(pi), '3.14159')
85 85 f.float_precision = '%e'
86 86 nt.assert_equal(f(pi), '3.141593e+00')
87 87 f.float_precision = ''
88 88 if numpy:
89 89 po = numpy.get_printoptions()
90 90 nt.assert_equal(po['precision'], 8)
91 91 nt.assert_equal(f(pi), repr(pi))
92 92
93 93 def test_bad_precision():
94 94 """test various invalid values for float_precision."""
95 95 f = PlainTextFormatter()
96 96 def set_fp(p):
97 97 f.float_precision=p
98 98 nt.assert_raises(ValueError, set_fp, '%')
99 99 nt.assert_raises(ValueError, set_fp, '%.3f%i')
100 100 nt.assert_raises(ValueError, set_fp, 'foo')
101 101 nt.assert_raises(ValueError, set_fp, -1)
102 102
103 103 def test_for_type():
104 104 f = PlainTextFormatter()
105 105
106 106 # initial return, None
107 107 nt.assert_is(f.for_type(C, foo_printer), None)
108 108 # no func queries
109 109 nt.assert_is(f.for_type(C), foo_printer)
110 110 # shouldn't change anything
111 111 nt.assert_is(f.for_type(C), foo_printer)
112 112 # None should do the same
113 113 nt.assert_is(f.for_type(C, None), foo_printer)
114 114 nt.assert_is(f.for_type(C, None), foo_printer)
115 115
116 116 def test_for_type_string():
117 117 f = PlainTextFormatter()
118 118
119 119 type_str = '%s.%s' % (C.__module__, 'C')
120 120
121 121 # initial return, None
122 122 nt.assert_is(f.for_type(type_str, foo_printer), None)
123 123 # no func queries
124 124 nt.assert_is(f.for_type(type_str), foo_printer)
125 125 nt.assert_in(_mod_name_key(C), f.deferred_printers)
126 126 nt.assert_is(f.for_type(C), foo_printer)
127 127 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
128 128 nt.assert_in(C, f.type_printers)
129 129
130 130 def test_for_type_by_name():
131 131 f = PlainTextFormatter()
132 132
133 133 mod = C.__module__
134 134
135 135 # initial return, None
136 136 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
137 137 # no func queries
138 138 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
139 139 # shouldn't change anything
140 140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
141 141 # None should do the same
142 142 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
143 143 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
144 144
145 145 def test_lookup():
146 146 f = PlainTextFormatter()
147 147
148 148 f.for_type(C, foo_printer)
149 149 nt.assert_is(f.lookup(C()), foo_printer)
150 150 with nt.assert_raises(KeyError):
151 151 f.lookup(A())
152 152
153 153 def test_lookup_string():
154 154 f = PlainTextFormatter()
155 155 type_str = '%s.%s' % (C.__module__, 'C')
156 156
157 157 f.for_type(type_str, foo_printer)
158 158 nt.assert_is(f.lookup(C()), foo_printer)
159 159 # should move from deferred to imported dict
160 160 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
161 161 nt.assert_in(C, f.type_printers)
162 162
163 163 def test_lookup_by_type():
164 164 f = PlainTextFormatter()
165 165 f.for_type(C, foo_printer)
166 166 nt.assert_is(f.lookup_by_type(C), foo_printer)
167 167 with nt.assert_raises(KeyError):
168 168 f.lookup_by_type(A)
169 169
170 170 def test_lookup_by_type_string():
171 171 f = PlainTextFormatter()
172 172 type_str = '%s.%s' % (C.__module__, 'C')
173 173 f.for_type(type_str, foo_printer)
174 174
175 175 # verify insertion
176 176 nt.assert_in(_mod_name_key(C), f.deferred_printers)
177 177 nt.assert_not_in(C, f.type_printers)
178 178
179 179 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
180 180 # lookup by string doesn't cause import
181 181 nt.assert_in(_mod_name_key(C), f.deferred_printers)
182 182 nt.assert_not_in(C, f.type_printers)
183 183
184 184 nt.assert_is(f.lookup_by_type(C), foo_printer)
185 185 # should move from deferred to imported dict
186 186 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
187 187 nt.assert_in(C, f.type_printers)
188 188
189 189 def test_in_formatter():
190 190 f = PlainTextFormatter()
191 191 f.for_type(C, foo_printer)
192 192 type_str = '%s.%s' % (C.__module__, 'C')
193 193 nt.assert_in(C, f)
194 194 nt.assert_in(type_str, f)
195 195
196 196 def test_string_in_formatter():
197 197 f = PlainTextFormatter()
198 198 type_str = '%s.%s' % (C.__module__, 'C')
199 199 f.for_type(type_str, foo_printer)
200 200 nt.assert_in(type_str, f)
201 201 nt.assert_in(C, f)
202 202
203 203 def test_pop():
204 204 f = PlainTextFormatter()
205 205 f.for_type(C, foo_printer)
206 206 nt.assert_is(f.lookup_by_type(C), foo_printer)
207 207 nt.assert_is(f.pop(C, None), foo_printer)
208 208 f.for_type(C, foo_printer)
209 209 nt.assert_is(f.pop(C), foo_printer)
210 210 with nt.assert_raises(KeyError):
211 211 f.lookup_by_type(C)
212 212 with nt.assert_raises(KeyError):
213 213 f.pop(C)
214 214 with nt.assert_raises(KeyError):
215 215 f.pop(A)
216 216 nt.assert_is(f.pop(A, None), None)
217 217
218 218 def test_pop_string():
219 219 f = PlainTextFormatter()
220 220 type_str = '%s.%s' % (C.__module__, 'C')
221 221
222 222 with nt.assert_raises(KeyError):
223 223 f.pop(type_str)
224 224
225 225 f.for_type(type_str, foo_printer)
226 226 f.pop(type_str)
227 227 with nt.assert_raises(KeyError):
228 228 f.lookup_by_type(C)
229 229 with nt.assert_raises(KeyError):
230 230 f.pop(type_str)
231 231
232 232 f.for_type(C, foo_printer)
233 233 nt.assert_is(f.pop(type_str, None), foo_printer)
234 234 with nt.assert_raises(KeyError):
235 235 f.lookup_by_type(C)
236 236 with nt.assert_raises(KeyError):
237 237 f.pop(type_str)
238 238 nt.assert_is(f.pop(type_str, None), None)
239 239
240 240
241 241 def test_error_method():
242 242 f = HTMLFormatter()
243 243 class BadHTML(object):
244 244 def _repr_html_(self):
245 245 raise ValueError("Bad HTML")
246 246 bad = BadHTML()
247 247 with capture_output() as captured:
248 248 result = f(bad)
249 249 nt.assert_is(result, None)
250 250 nt.assert_in("Traceback", captured.stdout)
251 251 nt.assert_in("Bad HTML", captured.stdout)
252 252 nt.assert_in("_repr_html_", captured.stdout)
253 253
254 254 def test_nowarn_notimplemented():
255 255 f = HTMLFormatter()
256 256 class HTMLNotImplemented(object):
257 257 def _repr_html_(self):
258 258 raise NotImplementedError
259 259 h = HTMLNotImplemented()
260 260 with capture_output() as captured:
261 261 result = f(h)
262 262 nt.assert_is(result, None)
263 263 nt.assert_equal("", captured.stderr)
264 264 nt.assert_equal("", captured.stdout)
265 265
266 266 def test_warn_error_for_type():
267 267 f = HTMLFormatter()
268 268 f.for_type(int, lambda i: name_error)
269 269 with capture_output() as captured:
270 270 result = f(5)
271 271 nt.assert_is(result, None)
272 272 nt.assert_in("Traceback", captured.stdout)
273 273 nt.assert_in("NameError", captured.stdout)
274 274 nt.assert_in("name_error", captured.stdout)
275 275
276 276 def test_error_pretty_method():
277 277 f = PlainTextFormatter()
278 278 class BadPretty(object):
279 279 def _repr_pretty_(self):
280 280 return "hello"
281 281 bad = BadPretty()
282 282 with capture_output() as captured:
283 283 result = f(bad)
284 284 nt.assert_is(result, None)
285 285 nt.assert_in("Traceback", captured.stdout)
286 286 nt.assert_in("_repr_pretty_", captured.stdout)
287 287 nt.assert_in("given", captured.stdout)
288 288 nt.assert_in("argument", captured.stdout)
289 289
290 290
291 291 def test_bad_repr_traceback():
292 292 f = PlainTextFormatter()
293 293 bad = BadRepr()
294 294 with capture_output() as captured:
295 295 result = f(bad)
296 296 # catches error, returns None
297 297 nt.assert_is(result, None)
298 298 nt.assert_in("Traceback", captured.stdout)
299 299 nt.assert_in("__repr__", captured.stdout)
300 300 nt.assert_in("ValueError", captured.stdout)
301 301
302 302
303 303 class MakePDF(object):
304 304 def _repr_pdf_(self):
305 305 return 'PDF'
306 306
307 307 def test_pdf_formatter():
308 308 pdf = MakePDF()
309 309 f = PDFFormatter()
310 310 nt.assert_equal(f(pdf), 'PDF')
311 311
312 312 def test_print_method_bound():
313 313 f = HTMLFormatter()
314 314 class MyHTML(object):
315 315 def _repr_html_(self):
316 316 return "hello"
317 317 with capture_output() as captured:
318 318 result = f(MyHTML)
319 319 nt.assert_is(result, None)
320 320 nt.assert_not_in("FormatterWarning", captured.stderr)
321 321
322 322 with capture_output() as captured:
323 323 result = f(MyHTML())
324 324 nt.assert_equal(result, "hello")
325 325 nt.assert_equal(captured.stderr, "")
326 326
327 327 def test_print_method_weird():
328 328
329 329 class TextMagicHat(object):
330 330 def __getattr__(self, key):
331 331 return key
332 332
333 333 f = HTMLFormatter()
334 334
335 335 text_hat = TextMagicHat()
336 336 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
337 337 with capture_output() as captured:
338 338 result = f(text_hat)
339 339
340 340 nt.assert_is(result, None)
341 341 nt.assert_not_in("FormatterWarning", captured.stderr)
342 342
343 343 class CallableMagicHat(object):
344 344 def __getattr__(self, key):
345 345 return lambda : key
346 346
347 347 call_hat = CallableMagicHat()
348 348 with capture_output() as captured:
349 349 result = f(call_hat)
350 350
351 351 nt.assert_equal(result, None)
352 352
353 353 class BadReprArgs(object):
354 354 def _repr_html_(self, extra, args):
355 355 return "html"
356 356
357 357 bad = BadReprArgs()
358 358 with capture_output() as captured:
359 359 result = f(bad)
360 360
361 361 nt.assert_is(result, None)
362 362 nt.assert_not_in("FormatterWarning", captured.stderr)
363 363
364 364
365 365 def test_format_config():
366 366 """config objects don't pretend to support fancy reprs with lazy attrs"""
367 367 f = HTMLFormatter()
368 368 cfg = Config()
369 369 with capture_output() as captured:
370 370 result = f(cfg)
371 371 nt.assert_is(result, None)
372 372 nt.assert_equal(captured.stderr, "")
373 373
374 374 with capture_output() as captured:
375 375 result = f(Config)
376 376 nt.assert_is(result, None)
377 377 nt.assert_equal(captured.stderr, "")
378 378
379 379 def test_pretty_max_seq_length():
380 380 f = PlainTextFormatter(max_seq_length=1)
381 381 lis = list(range(3))
382 382 text = f(lis)
383 383 nt.assert_equal(text, '[0, ...]')
384 384 f.max_seq_length = 0
385 385 text = f(lis)
386 386 nt.assert_equal(text, '[0, 1, 2]')
387 387 text = f(list(range(1024)))
388 388 lines = text.splitlines()
389 389 nt.assert_equal(len(lines), 1024)
390 390
391 391
392 392 def test_ipython_display_formatter():
393 393 """Objects with _ipython_display_ defined bypass other formatters"""
394 394 f = get_ipython().display_formatter
395 395 catcher = []
396 396 class SelfDisplaying(object):
397 397 def _ipython_display_(self):
398 398 catcher.append(self)
399 399
400 400 class NotSelfDisplaying(object):
401 401 def __repr__(self):
402 402 return "NotSelfDisplaying"
403 403
404 404 def _ipython_display_(self):
405 405 raise NotImplementedError
406 406
407 407 save_enabled = f.ipython_display_formatter.enabled
408 408 f.ipython_display_formatter.enabled = True
409 409
410 410 yes = SelfDisplaying()
411 411 no = NotSelfDisplaying()
412 412
413 413 d, md = f.format(no)
414 414 nt.assert_equal(d, {'text/plain': repr(no)})
415 415 nt.assert_equal(md, {})
416 416 nt.assert_equal(catcher, [])
417 417
418 418 d, md = f.format(yes)
419 419 nt.assert_equal(d, {})
420 420 nt.assert_equal(md, {})
421 421 nt.assert_equal(catcher, [yes])
422 422
423 423 f.ipython_display_formatter.enabled = save_enabled
424 424
425 425
426 426 def test_json_as_string_deprecated():
427 427 class JSONString(object):
428 428 def _repr_json_(self):
429 429 return '{}'
430 430
431 431 f = JSONFormatter()
432 432 with warnings.catch_warnings(record=True) as w:
433 433 d = f(JSONString())
434 434 nt.assert_equal(d, {})
435 435 nt.assert_equal(len(w), 1)
436 436
437 437
438 438 def test_repr_mime():
439 439 class HasReprMime(object):
440 440 def _repr_mimebundle_(self, include=None, exclude=None):
441 441 return {
442 442 'application/json+test.v2': {
443 443 'x': 'y'
444 444 },
445 445 'plain/text' : '<HasReprMime>',
446 446 'image/png' : 'i-overwrite'
447 447 }
448 448
449 449 def _repr_png_(self):
450 450 return 'should-be-overwritten'
451 451 def _repr_html_(self):
452 452 return '<b>hi!</b>'
453 453
454 454 f = get_ipython().display_formatter
455 455 html_f = f.formatters['text/html']
456 456 save_enabled = html_f.enabled
457 457 html_f.enabled = True
458 458 obj = HasReprMime()
459 459 d, md = f.format(obj)
460 460 html_f.enabled = save_enabled
461 461
462 462 nt.assert_equal(sorted(d), ['application/json+test.v2',
463 463 'image/png',
464 464 'plain/text',
465 465 'text/html',
466 466 'text/plain'])
467 467 nt.assert_equal(md, {})
468 468
469 469 d, md = f.format(obj, include={'image/png'})
470 470 nt.assert_equal(list(d.keys()), ['image/png'],
471 471 'Include should filter out even things from repr_mimebundle')
472 472 nt.assert_equal(d['image/png'], 'i-overwrite', '_repr_mimebundle_ take precedence')
473 473
474 474
475 475
476 476 def test_pass_correct_include_exclude():
477 477 class Tester(object):
478 478
479 479 def __init__(self, include=None, exclude=None):
480 480 self.include = include
481 481 self.exclude = exclude
482 482
483 483 def _repr_mimebundle_(self, include, exclude, **kwargs):
484 484 if include and (include != self.include):
485 485 raise ValueError('include got modified: display() may be broken.')
486 486 if exclude and (exclude != self.exclude):
487 487 raise ValueError('exclude got modified: display() may be broken.')
488 488
489 489 return None
490 490
491 491 include = {'a', 'b', 'c'}
492 492 exclude = {'c', 'e' , 'f'}
493 493
494 494 f = get_ipython().display_formatter
495 495 f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude)
496 496 f.format(Tester(exclude=exclude), exclude=exclude)
497 497 f.format(Tester(include=include), include=include)
498 498
499 499
500 500 def test_repr_mime_meta():
501 501 class HasReprMimeMeta(object):
502 502 def _repr_mimebundle_(self, include=None, exclude=None):
503 503 data = {
504 504 'image/png': 'base64-image-data',
505 505 }
506 506 metadata = {
507 507 'image/png': {
508 508 'width': 5,
509 509 'height': 10,
510 510 }
511 511 }
512 512 return (data, metadata)
513 513
514 514 f = get_ipython().display_formatter
515 515 obj = HasReprMimeMeta()
516 516 d, md = f.format(obj)
517 517 nt.assert_equal(sorted(d), ['image/png', 'text/plain'])
518 518 nt.assert_equal(md, {
519 519 'image/png': {
520 520 'width': 5,
521 521 'height': 10,
522 522 }
523 523 })
524 524
525 525 def test_repr_mime_failure():
526 526 class BadReprMime(object):
527 527 def _repr_mimebundle_(self, include=None, exclude=None):
528 528 raise RuntimeError
529 529
530 530 f = get_ipython().display_formatter
531 531 obj = BadReprMime()
532 532 d, md = f.format(obj)
533 533 nt.assert_in('text/plain', d)
General Comments 0
You need to be logged in to leave comments. Login now