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