##// END OF EJS Templates
Merge pull request #10539 from Carreau/fix-repr-mime...
Min RK -
r23616:9e7fbf0b merge
parent child Browse files
Show More
@@ -1,986 +1,1002 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Display formatters.
3 3
4 4 Inheritance diagram:
5 5
6 6 .. inheritance-diagram:: IPython.core.formatters
7 7 :parts: 3
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 import abc
14 14 import json
15 15 import sys
16 16 import traceback
17 17 import warnings
18 18 from io import StringIO
19 19
20 20 from decorator import decorator
21 21
22 22 from traitlets.config.configurable import Configurable
23 23 from IPython.core.getipython import get_ipython
24 24 from IPython.utils.sentinel import Sentinel
25 25 from IPython.utils.dir2 import get_real_method
26 26 from IPython.lib import pretty
27 27 from traitlets import (
28 28 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
29 29 ForwardDeclaredInstance,
30 30 default, observe,
31 31 )
32 32
33 33
34 34 class DisplayFormatter(Configurable):
35 35
36 36 active_types = List(Unicode(),
37 37 help="""List of currently active mime-types to display.
38 38 You can use this to set a white-list for formats to display.
39 39
40 40 Most users will not need to change this value.
41 41 """).tag(config=True)
42 42
43 43 @default('active_types')
44 44 def _active_types_default(self):
45 45 return self.format_types
46 46
47 47 @observe('active_types')
48 48 def _active_types_changed(self, change):
49 49 for key, formatter in self.formatters.items():
50 50 if key in change['new']:
51 51 formatter.enabled = True
52 52 else:
53 53 formatter.enabled = False
54 54
55 55 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
56 56 @default('ipython_display_formatter')
57 57 def _default_formatter(self):
58 58 return IPythonDisplayFormatter(parent=self)
59 59
60 60 mimebundle_formatter = ForwardDeclaredInstance('FormatterABC')
61 61 @default('mimebundle_formatter')
62 62 def _default_mime_formatter(self):
63 63 return MimeBundleFormatter(parent=self)
64 64
65 65 # A dict of formatter whose keys are format types (MIME types) and whose
66 66 # values are subclasses of BaseFormatter.
67 67 formatters = Dict()
68 68 @default('formatters')
69 69 def _formatters_default(self):
70 70 """Activate the default formatters."""
71 71 formatter_classes = [
72 72 PlainTextFormatter,
73 73 HTMLFormatter,
74 74 MarkdownFormatter,
75 75 SVGFormatter,
76 76 PNGFormatter,
77 77 PDFFormatter,
78 78 JPEGFormatter,
79 79 LatexFormatter,
80 80 JSONFormatter,
81 81 JavascriptFormatter
82 82 ]
83 83 d = {}
84 84 for cls in formatter_classes:
85 85 f = cls(parent=self)
86 86 d[f.format_type] = f
87 87 return d
88 88
89 89 def format(self, obj, include=None, exclude=None):
90 90 """Return a format data dict for an object.
91 91
92 92 By default all format types will be computed.
93 93
94 The following MIME types are currently implemented:
94 The following MIME types are usually implemented:
95 95
96 96 * text/plain
97 97 * text/html
98 98 * text/markdown
99 99 * text/latex
100 100 * application/json
101 101 * application/javascript
102 102 * application/pdf
103 103 * image/png
104 104 * image/jpeg
105 105 * image/svg+xml
106 106
107 107 Parameters
108 108 ----------
109 109 obj : object
110 110 The Python object whose format data will be computed.
111 include : list or tuple, optional
111 include : list, tuple or set; optional
112 112 A list of format type strings (MIME types) to include in the
113 113 format data dict. If this is set *only* the format types included
114 114 in this list will be computed.
115 exclude : list or tuple, optional
115 exclude : list, tuple or set; optional
116 116 A list of format type string (MIME types) to exclude in the format
117 117 data dict. If this is set all format types will be computed,
118 118 except for those included in this argument.
119 Mimetypes present in exclude will take precedence over the ones in include
119 120
120 121 Returns
121 122 -------
122 123 (format_dict, metadata_dict) : tuple of two dicts
123 124
124 125 format_dict is a dictionary of key/value pairs, one of each format that was
125 126 generated for the object. The keys are the format types, which
126 127 will usually be MIME type strings and the values and JSON'able
127 128 data structure containing the raw data for the representation in
128 129 that format.
129 130
130 131 metadata_dict is a dictionary of metadata about each mime-type output.
131 132 Its keys will be a strict subset of the keys in format_dict.
133
134 Notes
135 -----
136
137 If an object implement `_repr_mimebundle_` as well as various
138 `_repr_*_`, the data returned by `_repr_mimebundle_` will take
139 precedence and the corresponding `_repr_*_` for this mimetype will
140 not be called.
141
132 142 """
133 143 format_dict = {}
134 144 md_dict = {}
135 145
136 146 if self.ipython_display_formatter(obj):
137 147 # object handled itself, don't proceed
138 148 return {}, {}
139 149
140 150 format_dict, md_dict = self.mimebundle_formatter(obj)
141 151
152 if format_dict or md_dict:
153 if include:
154 format_dict = {k:v for k,v in format_dict.items() if k in include}
155 md_dict = {k:v for k,v in md_dict.items() if k in include}
156 if exclude:
157 format_dict = {k:v for k,v in format_dict.items() if k not in exclude}
158 md_dict = {k:v for k,v in md_dict.items() if k not in exclude}
159
142 160 for format_type, formatter in self.formatters.items():
143 161 if format_type in format_dict:
144 162 # already got it from mimebundle, don't render again
145 163 continue
146 164 if include and format_type not in include:
147 165 continue
148 166 if exclude and format_type in exclude:
149 167 continue
150 168
151 169 md = None
152 170 try:
153 171 data = formatter(obj)
154 172 except:
155 173 # FIXME: log the exception
156 174 raise
157 175
158 176 # formatters can return raw data or (data, metadata)
159 177 if isinstance(data, tuple) and len(data) == 2:
160 178 data, md = data
161 179
162 180 if data is not None:
163 181 format_dict[format_type] = data
164 182 if md is not None:
165 183 md_dict[format_type] = md
166
167 184 return format_dict, md_dict
168 185
169 186 @property
170 187 def format_types(self):
171 188 """Return the format types (MIME types) of the active formatters."""
172 189 return list(self.formatters.keys())
173 190
174 191
175 192 #-----------------------------------------------------------------------------
176 193 # Formatters for specific format types (text, html, svg, etc.)
177 194 #-----------------------------------------------------------------------------
178 195
179 196
180 197 def _safe_repr(obj):
181 198 """Try to return a repr of an object
182 199
183 200 always returns a string, at least.
184 201 """
185 202 try:
186 203 return repr(obj)
187 204 except Exception as e:
188 205 return "un-repr-able object (%r)" % e
189 206
190 207
191 208 class FormatterWarning(UserWarning):
192 209 """Warning class for errors in formatters"""
193 210
194 211 @decorator
195 212 def catch_format_error(method, self, *args, **kwargs):
196 213 """show traceback on failed format call"""
197 214 try:
198 215 r = method(self, *args, **kwargs)
199 216 except NotImplementedError:
200 217 # don't warn on NotImplementedErrors
201 218 return None
202 219 except Exception:
203 220 exc_info = sys.exc_info()
204 221 ip = get_ipython()
205 222 if ip is not None:
206 223 ip.showtraceback(exc_info)
207 224 else:
208 225 traceback.print_exception(*exc_info)
209 226 return None
210 227 return self._check_return(r, args[0])
211 228
212 229
213 230 class FormatterABC(metaclass=abc.ABCMeta):
214 231 """ Abstract base class for Formatters.
215 232
216 233 A formatter is a callable class that is responsible for computing the
217 234 raw format data for a particular format type (MIME type). For example,
218 235 an HTML formatter would have a format type of `text/html` and would return
219 236 the HTML representation of the object when called.
220 237 """
221 238
222 239 # The format type of the data returned, usually a MIME type.
223 240 format_type = 'text/plain'
224 241
225 242 # Is the formatter enabled...
226 243 enabled = True
227 244
228 245 @abc.abstractmethod
229 246 def __call__(self, obj):
230 247 """Return a JSON'able representation of the object.
231 248
232 249 If the object cannot be formatted by this formatter,
233 250 warn and return None.
234 251 """
235 252 return repr(obj)
236 253
237 254
238 255 def _mod_name_key(typ):
239 256 """Return a (__module__, __name__) tuple for a type.
240 257
241 258 Used as key in Formatter.deferred_printers.
242 259 """
243 260 module = getattr(typ, '__module__', None)
244 261 name = getattr(typ, '__name__', None)
245 262 return (module, name)
246 263
247 264
248 265 def _get_type(obj):
249 266 """Return the type of an instance (old and new-style)"""
250 267 return getattr(obj, '__class__', None) or type(obj)
251 268
252 269
253 270 _raise_key_error = Sentinel('_raise_key_error', __name__,
254 271 """
255 272 Special value to raise a KeyError
256 273
257 274 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
258 275 """)
259 276
260 277
261 278 class BaseFormatter(Configurable):
262 279 """A base formatter class that is configurable.
263 280
264 281 This formatter should usually be used as the base class of all formatters.
265 282 It is a traited :class:`Configurable` class and includes an extensible
266 283 API for users to determine how their objects are formatted. The following
267 284 logic is used to find a function to format an given object.
268 285
269 286 1. The object is introspected to see if it has a method with the name
270 287 :attr:`print_method`. If is does, that object is passed to that method
271 288 for formatting.
272 289 2. If no print method is found, three internal dictionaries are consulted
273 290 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
274 291 and :attr:`deferred_printers`.
275 292
276 293 Users should use these dictionaries to register functions that will be
277 294 used to compute the format data for their objects (if those objects don't
278 295 have the special print methods). The easiest way of using these
279 296 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
280 297 methods.
281 298
282 299 If no function/callable is found to compute the format data, ``None`` is
283 300 returned and this format type is not used.
284 301 """
285 302
286 303 format_type = Unicode('text/plain')
287 304 _return_type = str
288 305
289 306 enabled = Bool(True).tag(config=True)
290 307
291 308 print_method = ObjectName('__repr__')
292 309
293 310 # The singleton printers.
294 311 # Maps the IDs of the builtin singleton objects to the format functions.
295 312 singleton_printers = Dict().tag(config=True)
296 313
297 314 # The type-specific printers.
298 315 # Map type objects to the format functions.
299 316 type_printers = Dict().tag(config=True)
300 317
301 318 # The deferred-import type-specific printers.
302 319 # Map (modulename, classname) pairs to the format functions.
303 320 deferred_printers = Dict().tag(config=True)
304 321
305 322 @catch_format_error
306 323 def __call__(self, obj):
307 324 """Compute the format for an object."""
308 325 if self.enabled:
309 326 # lookup registered printer
310 327 try:
311 328 printer = self.lookup(obj)
312 329 except KeyError:
313 330 pass
314 331 else:
315 332 return printer(obj)
316 333 # Finally look for special method names
317 334 method = get_real_method(obj, self.print_method)
318 335 if method is not None:
319 336 return method()
320 337 return None
321 338 else:
322 339 return None
323 340
324 341 def __contains__(self, typ):
325 342 """map in to lookup_by_type"""
326 343 try:
327 344 self.lookup_by_type(typ)
328 345 except KeyError:
329 346 return False
330 347 else:
331 348 return True
332 349
333 350 def _check_return(self, r, obj):
334 351 """Check that a return value is appropriate
335 352
336 353 Return the value if so, None otherwise, warning if invalid.
337 354 """
338 355 if r is None or isinstance(r, self._return_type) or \
339 356 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
340 357 return r
341 358 else:
342 359 warnings.warn(
343 360 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
344 361 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
345 362 FormatterWarning
346 363 )
347 364
348 365 def lookup(self, obj):
349 366 """Look up the formatter for a given instance.
350 367
351 368 Parameters
352 369 ----------
353 370 obj : object instance
354 371
355 372 Returns
356 373 -------
357 374 f : callable
358 375 The registered formatting callable for the type.
359 376
360 377 Raises
361 378 ------
362 379 KeyError if the type has not been registered.
363 380 """
364 381 # look for singleton first
365 382 obj_id = id(obj)
366 383 if obj_id in self.singleton_printers:
367 384 return self.singleton_printers[obj_id]
368 385 # then lookup by type
369 386 return self.lookup_by_type(_get_type(obj))
370 387
371 388 def lookup_by_type(self, typ):
372 389 """Look up the registered formatter for a type.
373 390
374 391 Parameters
375 392 ----------
376 393 typ : type or '__module__.__name__' string for a type
377 394
378 395 Returns
379 396 -------
380 397 f : callable
381 398 The registered formatting callable for the type.
382 399
383 400 Raises
384 401 ------
385 402 KeyError if the type has not been registered.
386 403 """
387 404 if isinstance(typ, str):
388 405 typ_key = tuple(typ.rsplit('.',1))
389 406 if typ_key not in self.deferred_printers:
390 407 # We may have it cached in the type map. We will have to
391 408 # iterate over all of the types to check.
392 409 for cls in self.type_printers:
393 410 if _mod_name_key(cls) == typ_key:
394 411 return self.type_printers[cls]
395 412 else:
396 413 return self.deferred_printers[typ_key]
397 414 else:
398 415 for cls in pretty._get_mro(typ):
399 416 if cls in self.type_printers or self._in_deferred_types(cls):
400 417 return self.type_printers[cls]
401 418
402 419 # If we have reached here, the lookup failed.
403 420 raise KeyError("No registered printer for {0!r}".format(typ))
404 421
405 422 def for_type(self, typ, func=None):
406 423 """Add a format function for a given type.
407 424
408 425 Parameters
409 426 -----------
410 427 typ : type or '__module__.__name__' string for a type
411 428 The class of the object that will be formatted using `func`.
412 429 func : callable
413 430 A callable for computing the format data.
414 431 `func` will be called with the object to be formatted,
415 432 and will return the raw data in this formatter's format.
416 433 Subclasses may use a different call signature for the
417 434 `func` argument.
418 435
419 436 If `func` is None or not specified, there will be no change,
420 437 only returning the current value.
421 438
422 439 Returns
423 440 -------
424 441 oldfunc : callable
425 442 The currently registered callable.
426 443 If you are registering a new formatter,
427 444 this will be the previous value (to enable restoring later).
428 445 """
429 446 # if string given, interpret as 'pkg.module.class_name'
430 447 if isinstance(typ, str):
431 448 type_module, type_name = typ.rsplit('.', 1)
432 449 return self.for_type_by_name(type_module, type_name, func)
433 450
434 451 try:
435 452 oldfunc = self.lookup_by_type(typ)
436 453 except KeyError:
437 454 oldfunc = None
438 455
439 456 if func is not None:
440 457 self.type_printers[typ] = func
441 458
442 459 return oldfunc
443 460
444 461 def for_type_by_name(self, type_module, type_name, func=None):
445 462 """Add a format function for a type specified by the full dotted
446 463 module and name of the type, rather than the type of the object.
447 464
448 465 Parameters
449 466 ----------
450 467 type_module : str
451 468 The full dotted name of the module the type is defined in, like
452 469 ``numpy``.
453 470 type_name : str
454 471 The name of the type (the class name), like ``dtype``
455 472 func : callable
456 473 A callable for computing the format data.
457 474 `func` will be called with the object to be formatted,
458 475 and will return the raw data in this formatter's format.
459 476 Subclasses may use a different call signature for the
460 477 `func` argument.
461 478
462 479 If `func` is None or unspecified, there will be no change,
463 480 only returning the current value.
464 481
465 482 Returns
466 483 -------
467 484 oldfunc : callable
468 485 The currently registered callable.
469 486 If you are registering a new formatter,
470 487 this will be the previous value (to enable restoring later).
471 488 """
472 489 key = (type_module, type_name)
473 490
474 491 try:
475 492 oldfunc = self.lookup_by_type("%s.%s" % key)
476 493 except KeyError:
477 494 oldfunc = None
478 495
479 496 if func is not None:
480 497 self.deferred_printers[key] = func
481 498 return oldfunc
482 499
483 500 def pop(self, typ, default=_raise_key_error):
484 501 """Pop a formatter for the given type.
485 502
486 503 Parameters
487 504 ----------
488 505 typ : type or '__module__.__name__' string for a type
489 506 default : object
490 507 value to be returned if no formatter is registered for typ.
491 508
492 509 Returns
493 510 -------
494 511 obj : object
495 512 The last registered object for the type.
496 513
497 514 Raises
498 515 ------
499 516 KeyError if the type is not registered and default is not specified.
500 517 """
501 518
502 519 if isinstance(typ, str):
503 520 typ_key = tuple(typ.rsplit('.',1))
504 521 if typ_key not in self.deferred_printers:
505 522 # We may have it cached in the type map. We will have to
506 523 # iterate over all of the types to check.
507 524 for cls in self.type_printers:
508 525 if _mod_name_key(cls) == typ_key:
509 526 old = self.type_printers.pop(cls)
510 527 break
511 528 else:
512 529 old = default
513 530 else:
514 531 old = self.deferred_printers.pop(typ_key)
515 532 else:
516 533 if typ in self.type_printers:
517 534 old = self.type_printers.pop(typ)
518 535 else:
519 536 old = self.deferred_printers.pop(_mod_name_key(typ), default)
520 537 if old is _raise_key_error:
521 538 raise KeyError("No registered value for {0!r}".format(typ))
522 539 return old
523 540
524 541 def _in_deferred_types(self, cls):
525 542 """
526 543 Check if the given class is specified in the deferred type registry.
527 544
528 545 Successful matches will be moved to the regular type registry for future use.
529 546 """
530 547 mod = getattr(cls, '__module__', None)
531 548 name = getattr(cls, '__name__', None)
532 549 key = (mod, name)
533 550 if key in self.deferred_printers:
534 551 # Move the printer over to the regular registry.
535 552 printer = self.deferred_printers.pop(key)
536 553 self.type_printers[cls] = printer
537 554 return True
538 555 return False
539 556
540 557
541 558 class PlainTextFormatter(BaseFormatter):
542 559 """The default pretty-printer.
543 560
544 561 This uses :mod:`IPython.lib.pretty` to compute the format data of
545 562 the object. If the object cannot be pretty printed, :func:`repr` is used.
546 563 See the documentation of :mod:`IPython.lib.pretty` for details on
547 564 how to write pretty printers. Here is a simple example::
548 565
549 566 def dtype_pprinter(obj, p, cycle):
550 567 if cycle:
551 568 return p.text('dtype(...)')
552 569 if hasattr(obj, 'fields'):
553 570 if obj.fields is None:
554 571 p.text(repr(obj))
555 572 else:
556 573 p.begin_group(7, 'dtype([')
557 574 for i, field in enumerate(obj.descr):
558 575 if i > 0:
559 576 p.text(',')
560 577 p.breakable()
561 578 p.pretty(field)
562 579 p.end_group(7, '])')
563 580 """
564 581
565 582 # The format type of data returned.
566 583 format_type = Unicode('text/plain')
567 584
568 585 # This subclass ignores this attribute as it always need to return
569 586 # something.
570 587 enabled = Bool(True).tag(config=False)
571 588
572 589 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
573 590 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
574 591
575 592 Set to 0 to disable truncation.
576 593 """
577 594 ).tag(config=True)
578 595
579 596 # Look for a _repr_pretty_ methods to use for pretty printing.
580 597 print_method = ObjectName('_repr_pretty_')
581 598
582 599 # Whether to pretty-print or not.
583 600 pprint = Bool(True).tag(config=True)
584 601
585 602 # Whether to be verbose or not.
586 603 verbose = Bool(False).tag(config=True)
587 604
588 605 # The maximum width.
589 606 max_width = Integer(79).tag(config=True)
590 607
591 608 # The newline character.
592 609 newline = Unicode('\n').tag(config=True)
593 610
594 611 # format-string for pprinting floats
595 612 float_format = Unicode('%r')
596 613 # setter for float precision, either int or direct format-string
597 614 float_precision = CUnicode('').tag(config=True)
598 615
599 616 @observe('float_precision')
600 617 def _float_precision_changed(self, change):
601 618 """float_precision changed, set float_format accordingly.
602 619
603 620 float_precision can be set by int or str.
604 621 This will set float_format, after interpreting input.
605 622 If numpy has been imported, numpy print precision will also be set.
606 623
607 624 integer `n` sets format to '%.nf', otherwise, format set directly.
608 625
609 626 An empty string returns to defaults (repr for float, 8 for numpy).
610 627
611 628 This parameter can be set via the '%precision' magic.
612 629 """
613 630
614 631 new = change['new']
615 632 if '%' in new:
616 633 # got explicit format string
617 634 fmt = new
618 635 try:
619 636 fmt%3.14159
620 637 except Exception:
621 638 raise ValueError("Precision must be int or format string, not %r"%new)
622 639 elif new:
623 640 # otherwise, should be an int
624 641 try:
625 642 i = int(new)
626 643 assert i >= 0
627 644 except ValueError:
628 645 raise ValueError("Precision must be int or format string, not %r"%new)
629 646 except AssertionError:
630 647 raise ValueError("int precision must be non-negative, not %r"%i)
631 648
632 649 fmt = '%%.%if'%i
633 650 if 'numpy' in sys.modules:
634 651 # set numpy precision if it has been imported
635 652 import numpy
636 653 numpy.set_printoptions(precision=i)
637 654 else:
638 655 # default back to repr
639 656 fmt = '%r'
640 657 if 'numpy' in sys.modules:
641 658 import numpy
642 659 # numpy default is 8
643 660 numpy.set_printoptions(precision=8)
644 661 self.float_format = fmt
645 662
646 663 # Use the default pretty printers from IPython.lib.pretty.
647 664 @default('singleton_printers')
648 665 def _singleton_printers_default(self):
649 666 return pretty._singleton_pprinters.copy()
650 667
651 668 @default('type_printers')
652 669 def _type_printers_default(self):
653 670 d = pretty._type_pprinters.copy()
654 671 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
655 672 return d
656 673
657 674 @default('deferred_printers')
658 675 def _deferred_printers_default(self):
659 676 return pretty._deferred_type_pprinters.copy()
660 677
661 678 #### FormatterABC interface ####
662 679
663 680 @catch_format_error
664 681 def __call__(self, obj):
665 682 """Compute the pretty representation of the object."""
666 683 if not self.pprint:
667 684 return repr(obj)
668 685 else:
669 686 stream = StringIO()
670 687 printer = pretty.RepresentationPrinter(stream, self.verbose,
671 688 self.max_width, self.newline,
672 689 max_seq_length=self.max_seq_length,
673 690 singleton_pprinters=self.singleton_printers,
674 691 type_pprinters=self.type_printers,
675 692 deferred_pprinters=self.deferred_printers)
676 693 printer.pretty(obj)
677 694 printer.flush()
678 695 return stream.getvalue()
679 696
680 697
681 698 class HTMLFormatter(BaseFormatter):
682 699 """An HTML formatter.
683 700
684 701 To define the callables that compute the HTML representation of your
685 702 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
686 703 or :meth:`for_type_by_name` methods to register functions that handle
687 704 this.
688 705
689 706 The return value of this formatter should be a valid HTML snippet that
690 707 could be injected into an existing DOM. It should *not* include the
691 708 ```<html>`` or ```<body>`` tags.
692 709 """
693 710 format_type = Unicode('text/html')
694 711
695 712 print_method = ObjectName('_repr_html_')
696 713
697 714
698 715 class MarkdownFormatter(BaseFormatter):
699 716 """A Markdown formatter.
700 717
701 718 To define the callables that compute the Markdown representation of your
702 719 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
703 720 or :meth:`for_type_by_name` methods to register functions that handle
704 721 this.
705 722
706 723 The return value of this formatter should be a valid Markdown.
707 724 """
708 725 format_type = Unicode('text/markdown')
709 726
710 727 print_method = ObjectName('_repr_markdown_')
711 728
712 729 class SVGFormatter(BaseFormatter):
713 730 """An SVG formatter.
714 731
715 732 To define the callables that compute the SVG representation of your
716 733 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
717 734 or :meth:`for_type_by_name` methods to register functions that handle
718 735 this.
719 736
720 737 The return value of this formatter should be valid SVG enclosed in
721 738 ```<svg>``` tags, that could be injected into an existing DOM. It should
722 739 *not* include the ```<html>`` or ```<body>`` tags.
723 740 """
724 741 format_type = Unicode('image/svg+xml')
725 742
726 743 print_method = ObjectName('_repr_svg_')
727 744
728 745
729 746 class PNGFormatter(BaseFormatter):
730 747 """A PNG formatter.
731 748
732 749 To define the callables that compute the PNG representation of your
733 750 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
734 751 or :meth:`for_type_by_name` methods to register functions that handle
735 752 this.
736 753
737 754 The return value of this formatter should be raw PNG data, *not*
738 755 base64 encoded.
739 756 """
740 757 format_type = Unicode('image/png')
741 758
742 759 print_method = ObjectName('_repr_png_')
743 760
744 761 _return_type = (bytes, str)
745 762
746 763
747 764 class JPEGFormatter(BaseFormatter):
748 765 """A JPEG formatter.
749 766
750 767 To define the callables that compute the JPEG representation of your
751 768 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
752 769 or :meth:`for_type_by_name` methods to register functions that handle
753 770 this.
754 771
755 772 The return value of this formatter should be raw JPEG data, *not*
756 773 base64 encoded.
757 774 """
758 775 format_type = Unicode('image/jpeg')
759 776
760 777 print_method = ObjectName('_repr_jpeg_')
761 778
762 779 _return_type = (bytes, str)
763 780
764 781
765 782 class LatexFormatter(BaseFormatter):
766 783 """A LaTeX formatter.
767 784
768 785 To define the callables that compute the LaTeX representation of your
769 786 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
770 787 or :meth:`for_type_by_name` methods to register functions that handle
771 788 this.
772 789
773 790 The return value of this formatter should be a valid LaTeX equation,
774 791 enclosed in either ```$```, ```$$``` or another LaTeX equation
775 792 environment.
776 793 """
777 794 format_type = Unicode('text/latex')
778 795
779 796 print_method = ObjectName('_repr_latex_')
780 797
781 798
782 799 class JSONFormatter(BaseFormatter):
783 800 """A JSON string formatter.
784 801
785 802 To define the callables that compute the JSONable representation of
786 803 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
787 804 or :meth:`for_type_by_name` methods to register functions that handle
788 805 this.
789 806
790 807 The return value of this formatter should be a JSONable list or dict.
791 808 JSON scalars (None, number, string) are not allowed, only dict or list containers.
792 809 """
793 810 format_type = Unicode('application/json')
794 811 _return_type = (list, dict)
795 812
796 813 print_method = ObjectName('_repr_json_')
797 814
798 815 def _check_return(self, r, obj):
799 816 """Check that a return value is appropriate
800 817
801 818 Return the value if so, None otherwise, warning if invalid.
802 819 """
803 820 if r is None:
804 821 return
805 822 md = None
806 823 if isinstance(r, tuple):
807 824 # unpack data, metadata tuple for type checking on first element
808 825 r, md = r
809 826
810 827 # handle deprecated JSON-as-string form from IPython < 3
811 828 if isinstance(r, str):
812 829 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
813 830 FormatterWarning)
814 831 r = json.loads(r)
815 832
816 833 if md is not None:
817 834 # put the tuple back together
818 835 r = (r, md)
819 836 return super(JSONFormatter, self)._check_return(r, obj)
820 837
821 838
822 839 class JavascriptFormatter(BaseFormatter):
823 840 """A Javascript formatter.
824 841
825 842 To define the callables that compute the Javascript representation of
826 843 your objects, define a :meth:`_repr_javascript_` method or use the
827 844 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
828 845 that handle this.
829 846
830 847 The return value of this formatter should be valid Javascript code and
831 848 should *not* be enclosed in ```<script>``` tags.
832 849 """
833 850 format_type = Unicode('application/javascript')
834 851
835 852 print_method = ObjectName('_repr_javascript_')
836 853
837 854
838 855 class PDFFormatter(BaseFormatter):
839 856 """A PDF formatter.
840 857
841 858 To define the callables that compute the PDF representation of your
842 859 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
843 860 or :meth:`for_type_by_name` methods to register functions that handle
844 861 this.
845 862
846 863 The return value of this formatter should be raw PDF data, *not*
847 864 base64 encoded.
848 865 """
849 866 format_type = Unicode('application/pdf')
850 867
851 868 print_method = ObjectName('_repr_pdf_')
852 869
853 870 _return_type = (bytes, str)
854 871
855 872 class IPythonDisplayFormatter(BaseFormatter):
856 873 """An escape-hatch Formatter for objects that know how to display themselves.
857 874
858 875 To define the callables that compute the representation of your
859 876 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
860 877 or :meth:`for_type_by_name` methods to register functions that handle
861 878 this. Unlike mime-type displays, this method should not return anything,
862 879 instead calling any appropriate display methods itself.
863 880
864 881 This display formatter has highest priority.
865 882 If it fires, no other display formatter will be called.
866 883
867 884 Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types
868 885 without registering a new Formatter.
869 886
870 887 IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types,
871 888 so `_ipython_display_` should only be used for objects that require unusual
872 889 display patterns, such as multiple display calls.
873 890 """
874 891 print_method = ObjectName('_ipython_display_')
875 892 _return_type = (type(None), bool)
876 893
877 894 @catch_format_error
878 895 def __call__(self, obj):
879 896 """Compute the format for an object."""
880 897 if self.enabled:
881 898 # lookup registered printer
882 899 try:
883 900 printer = self.lookup(obj)
884 901 except KeyError:
885 902 pass
886 903 else:
887 904 printer(obj)
888 905 return True
889 906 # Finally look for special method names
890 907 method = get_real_method(obj, self.print_method)
891 908 if method is not None:
892 909 method()
893 910 return True
894 911
895 912
896 913 class MimeBundleFormatter(BaseFormatter):
897 914 """A Formatter for arbitrary mime-types.
898 915
899 916 Unlike other `_repr_<mimetype>_` methods,
900 917 `_repr_mimebundle_` should return mime-bundle data,
901 918 either the mime-keyed `data` dictionary or the tuple `(data, metadata)`.
902 919 Any mime-type is valid.
903 920
904 921 To define the callables that compute the mime-bundle representation of your
905 922 objects, define a :meth:`_repr_mimebundle_` method or use the :meth:`for_type`
906 923 or :meth:`for_type_by_name` methods to register functions that handle
907 924 this.
908 925
909 926 .. versionadded:: 6.1
910 927 """
911 928 print_method = ObjectName('_repr_mimebundle_')
912 929 _return_type = dict
913 930
914 931 def _check_return(self, r, obj):
915 932 r = super(MimeBundleFormatter, self)._check_return(r, obj)
916 933 # always return (data, metadata):
917 934 if r is None:
918 935 return {}, {}
919 936 if not isinstance(r, tuple):
920 937 return r, {}
921 938 return r
922 939
923 940
924 941 FormatterABC.register(BaseFormatter)
925 942 FormatterABC.register(PlainTextFormatter)
926 943 FormatterABC.register(HTMLFormatter)
927 944 FormatterABC.register(MarkdownFormatter)
928 945 FormatterABC.register(SVGFormatter)
929 946 FormatterABC.register(PNGFormatter)
930 947 FormatterABC.register(PDFFormatter)
931 948 FormatterABC.register(JPEGFormatter)
932 949 FormatterABC.register(LatexFormatter)
933 950 FormatterABC.register(JSONFormatter)
934 951 FormatterABC.register(JavascriptFormatter)
935 952 FormatterABC.register(IPythonDisplayFormatter)
936 953 FormatterABC.register(MimeBundleFormatter)
937 954
938 955
939 956 def format_display_data(obj, include=None, exclude=None):
940 957 """Return a format data dict for an object.
941 958
942 959 By default all format types will be computed.
943 960
944 961 The following MIME types are currently implemented:
945 962
946 963 * text/plain
947 964 * text/html
948 965 * text/markdown
949 966 * text/latex
950 967 * application/json
951 968 * application/javascript
952 969 * application/pdf
953 970 * image/png
954 971 * image/jpeg
955 972 * image/svg+xml
956 973
957 974 Parameters
958 975 ----------
959 976 obj : object
960 977 The Python object whose format data will be computed.
961 978
962 979 Returns
963 980 -------
964 981 format_dict : dict
965 982 A dictionary of key/value pairs, one or each format that was
966 983 generated for the object. The keys are the format types, which
967 984 will usually be MIME type strings and the values and JSON'able
968 985 data structure containing the raw data for the representation in
969 986 that format.
970 987 include : list or tuple, optional
971 988 A list of format type strings (MIME types) to include in the
972 989 format data dict. If this is set *only* the format types included
973 990 in this list will be computed.
974 991 exclude : list or tuple, optional
975 992 A list of format type string (MIME types) to exclue in the format
976 993 data dict. If this is set all format types will be computed,
977 994 except for those included in this argument.
978 995 """
979 996 from IPython.core.interactiveshell import InteractiveShell
980 997
981 998 return InteractiveShell.instance().display_formatter.format(
982 999 obj,
983 1000 include,
984 1001 exclude
985 1002 )
986
@@ -1,490 +1,503 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 nt.assert_equal(f(A()), 'foo')
52 52 nt.assert_equal(f(B()), 'foo')
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 mod = C.__module__
120 120
121 121 type_str = '%s.%s' % (C.__module__, 'C')
122 122
123 123 # initial return, None
124 124 nt.assert_is(f.for_type(type_str, foo_printer), None)
125 125 # no func queries
126 126 nt.assert_is(f.for_type(type_str), foo_printer)
127 127 nt.assert_in(_mod_name_key(C), f.deferred_printers)
128 128 nt.assert_is(f.for_type(C), foo_printer)
129 129 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
130 130 nt.assert_in(C, f.type_printers)
131 131
132 132 def test_for_type_by_name():
133 133 f = PlainTextFormatter()
134 134
135 135 mod = C.__module__
136 136
137 137 # initial return, None
138 138 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
139 139 # no func queries
140 140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
141 141 # shouldn't change anything
142 142 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
143 143 # None should do the same
144 144 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
145 145 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
146 146
147 147 def test_lookup():
148 148 f = PlainTextFormatter()
149 149
150 150 f.for_type(C, foo_printer)
151 151 nt.assert_is(f.lookup(C()), foo_printer)
152 152 with nt.assert_raises(KeyError):
153 153 f.lookup(A())
154 154
155 155 def test_lookup_string():
156 156 f = PlainTextFormatter()
157 157 type_str = '%s.%s' % (C.__module__, 'C')
158 158
159 159 f.for_type(type_str, foo_printer)
160 160 nt.assert_is(f.lookup(C()), foo_printer)
161 161 # should move from deferred to imported dict
162 162 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
163 163 nt.assert_in(C, f.type_printers)
164 164
165 165 def test_lookup_by_type():
166 166 f = PlainTextFormatter()
167 167 f.for_type(C, foo_printer)
168 168 nt.assert_is(f.lookup_by_type(C), foo_printer)
169 169 type_str = '%s.%s' % (C.__module__, 'C')
170 170 with nt.assert_raises(KeyError):
171 171 f.lookup_by_type(A)
172 172
173 173 def test_lookup_by_type_string():
174 174 f = PlainTextFormatter()
175 175 type_str = '%s.%s' % (C.__module__, 'C')
176 176 f.for_type(type_str, foo_printer)
177 177
178 178 # verify insertion
179 179 nt.assert_in(_mod_name_key(C), f.deferred_printers)
180 180 nt.assert_not_in(C, f.type_printers)
181 181
182 182 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
183 183 # lookup by string doesn't cause import
184 184 nt.assert_in(_mod_name_key(C), f.deferred_printers)
185 185 nt.assert_not_in(C, f.type_printers)
186 186
187 187 nt.assert_is(f.lookup_by_type(C), foo_printer)
188 188 # should move from deferred to imported dict
189 189 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
190 190 nt.assert_in(C, f.type_printers)
191 191
192 192 def test_in_formatter():
193 193 f = PlainTextFormatter()
194 194 f.for_type(C, foo_printer)
195 195 type_str = '%s.%s' % (C.__module__, 'C')
196 196 nt.assert_in(C, f)
197 197 nt.assert_in(type_str, f)
198 198
199 199 def test_string_in_formatter():
200 200 f = PlainTextFormatter()
201 201 type_str = '%s.%s' % (C.__module__, 'C')
202 202 f.for_type(type_str, foo_printer)
203 203 nt.assert_in(type_str, f)
204 204 nt.assert_in(C, f)
205 205
206 206 def test_pop():
207 207 f = PlainTextFormatter()
208 208 f.for_type(C, foo_printer)
209 209 nt.assert_is(f.lookup_by_type(C), foo_printer)
210 210 nt.assert_is(f.pop(C, None), foo_printer)
211 211 f.for_type(C, foo_printer)
212 212 nt.assert_is(f.pop(C), foo_printer)
213 213 with nt.assert_raises(KeyError):
214 214 f.lookup_by_type(C)
215 215 with nt.assert_raises(KeyError):
216 216 f.pop(C)
217 217 with nt.assert_raises(KeyError):
218 218 f.pop(A)
219 219 nt.assert_is(f.pop(A, None), None)
220 220
221 221 def test_pop_string():
222 222 f = PlainTextFormatter()
223 223 type_str = '%s.%s' % (C.__module__, 'C')
224 224
225 225 with nt.assert_raises(KeyError):
226 226 f.pop(type_str)
227 227
228 228 f.for_type(type_str, foo_printer)
229 229 f.pop(type_str)
230 230 with nt.assert_raises(KeyError):
231 231 f.lookup_by_type(C)
232 232 with nt.assert_raises(KeyError):
233 233 f.pop(type_str)
234 234
235 235 f.for_type(C, foo_printer)
236 236 nt.assert_is(f.pop(type_str, None), foo_printer)
237 237 with nt.assert_raises(KeyError):
238 238 f.lookup_by_type(C)
239 239 with nt.assert_raises(KeyError):
240 240 f.pop(type_str)
241 241 nt.assert_is(f.pop(type_str, None), None)
242 242
243 243
244 244 def test_error_method():
245 245 f = HTMLFormatter()
246 246 class BadHTML(object):
247 247 def _repr_html_(self):
248 248 raise ValueError("Bad HTML")
249 249 bad = BadHTML()
250 250 with capture_output() as captured:
251 251 result = f(bad)
252 252 nt.assert_is(result, None)
253 253 nt.assert_in("Traceback", captured.stdout)
254 254 nt.assert_in("Bad HTML", captured.stdout)
255 255 nt.assert_in("_repr_html_", captured.stdout)
256 256
257 257 def test_nowarn_notimplemented():
258 258 f = HTMLFormatter()
259 259 class HTMLNotImplemented(object):
260 260 def _repr_html_(self):
261 261 raise NotImplementedError
262 262 h = HTMLNotImplemented()
263 263 with capture_output() as captured:
264 264 result = f(h)
265 265 nt.assert_is(result, None)
266 266 nt.assert_equal("", captured.stderr)
267 267 nt.assert_equal("", captured.stdout)
268 268
269 269 def test_warn_error_for_type():
270 270 f = HTMLFormatter()
271 271 f.for_type(int, lambda i: name_error)
272 272 with capture_output() as captured:
273 273 result = f(5)
274 274 nt.assert_is(result, None)
275 275 nt.assert_in("Traceback", captured.stdout)
276 276 nt.assert_in("NameError", captured.stdout)
277 277 nt.assert_in("name_error", captured.stdout)
278 278
279 279 def test_error_pretty_method():
280 280 f = PlainTextFormatter()
281 281 class BadPretty(object):
282 282 def _repr_pretty_(self):
283 283 return "hello"
284 284 bad = BadPretty()
285 285 with capture_output() as captured:
286 286 result = f(bad)
287 287 nt.assert_is(result, None)
288 288 nt.assert_in("Traceback", captured.stdout)
289 289 nt.assert_in("_repr_pretty_", captured.stdout)
290 290 nt.assert_in("given", captured.stdout)
291 291 nt.assert_in("argument", captured.stdout)
292 292
293 293
294 294 def test_bad_repr_traceback():
295 295 f = PlainTextFormatter()
296 296 bad = BadRepr()
297 297 with capture_output() as captured:
298 298 result = f(bad)
299 299 # catches error, returns None
300 300 nt.assert_is(result, None)
301 301 nt.assert_in("Traceback", captured.stdout)
302 302 nt.assert_in("__repr__", captured.stdout)
303 303 nt.assert_in("ValueError", captured.stdout)
304 304
305 305
306 306 class MakePDF(object):
307 307 def _repr_pdf_(self):
308 308 return 'PDF'
309 309
310 310 def test_pdf_formatter():
311 311 pdf = MakePDF()
312 312 f = PDFFormatter()
313 313 nt.assert_equal(f(pdf), 'PDF')
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 nt.assert_equal(result, "hello")
328 328 nt.assert_equal(captured.stderr, "")
329 329
330 330 def test_print_method_weird():
331 331
332 332 class TextMagicHat(object):
333 333 def __getattr__(self, key):
334 334 return key
335 335
336 336 f = HTMLFormatter()
337 337
338 338 text_hat = TextMagicHat()
339 339 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
340 340 with capture_output() as captured:
341 341 result = f(text_hat)
342 342
343 343 nt.assert_is(result, None)
344 344 nt.assert_not_in("FormatterWarning", captured.stderr)
345 345
346 346 class CallableMagicHat(object):
347 347 def __getattr__(self, key):
348 348 return lambda : key
349 349
350 350 call_hat = CallableMagicHat()
351 351 with capture_output() as captured:
352 352 result = f(call_hat)
353 353
354 354 nt.assert_equal(result, None)
355 355
356 356 class BadReprArgs(object):
357 357 def _repr_html_(self, extra, args):
358 358 return "html"
359 359
360 360 bad = BadReprArgs()
361 361 with capture_output() as captured:
362 362 result = f(bad)
363 363
364 364 nt.assert_is(result, None)
365 365 nt.assert_not_in("FormatterWarning", captured.stderr)
366 366
367 367
368 368 def test_format_config():
369 369 """config objects don't pretend to support fancy reprs with lazy attrs"""
370 370 f = HTMLFormatter()
371 371 cfg = Config()
372 372 with capture_output() as captured:
373 373 result = f(cfg)
374 374 nt.assert_is(result, None)
375 375 nt.assert_equal(captured.stderr, "")
376 376
377 377 with capture_output() as captured:
378 378 result = f(Config)
379 379 nt.assert_is(result, None)
380 380 nt.assert_equal(captured.stderr, "")
381 381
382 382 def test_pretty_max_seq_length():
383 383 f = PlainTextFormatter(max_seq_length=1)
384 384 lis = list(range(3))
385 385 text = f(lis)
386 386 nt.assert_equal(text, '[0, ...]')
387 387 f.max_seq_length = 0
388 388 text = f(lis)
389 389 nt.assert_equal(text, '[0, 1, 2]')
390 390 text = f(list(range(1024)))
391 391 lines = text.splitlines()
392 392 nt.assert_equal(len(lines), 1024)
393 393
394 394
395 395 def test_ipython_display_formatter():
396 396 """Objects with _ipython_display_ defined bypass other formatters"""
397 397 f = get_ipython().display_formatter
398 398 catcher = []
399 399 class SelfDisplaying(object):
400 400 def _ipython_display_(self):
401 401 catcher.append(self)
402 402
403 403 class NotSelfDisplaying(object):
404 404 def __repr__(self):
405 405 return "NotSelfDisplaying"
406 406
407 407 def _ipython_display_(self):
408 408 raise NotImplementedError
409 409
410 410 save_enabled = f.ipython_display_formatter.enabled
411 411 f.ipython_display_formatter.enabled = True
412 412
413 413 yes = SelfDisplaying()
414 414 no = NotSelfDisplaying()
415 415
416 416 d, md = f.format(no)
417 417 nt.assert_equal(d, {'text/plain': repr(no)})
418 418 nt.assert_equal(md, {})
419 419 nt.assert_equal(catcher, [])
420 420
421 421 d, md = f.format(yes)
422 422 nt.assert_equal(d, {})
423 423 nt.assert_equal(md, {})
424 424 nt.assert_equal(catcher, [yes])
425 425
426 426 f.ipython_display_formatter.enabled = save_enabled
427 427
428 428
429 429 def test_json_as_string_deprecated():
430 430 class JSONString(object):
431 431 def _repr_json_(self):
432 432 return '{}'
433 433
434 434 f = JSONFormatter()
435 435 with warnings.catch_warnings(record=True) as w:
436 436 d = f(JSONString())
437 437 nt.assert_equal(d, {})
438 438 nt.assert_equal(len(w), 1)
439 439
440 440
441 441 def test_repr_mime():
442 442 class HasReprMime(object):
443 443 def _repr_mimebundle_(self):
444 444 return {
445 445 'application/json+test.v2': {
446 446 'x': 'y'
447 }
447 },
448 'plain/text' : '<HasReprMime>',
449 'image/png' : 'i-overwrite'
448 450 }
449
451
452 def _repr_png_(self):
453 return 'should-be-overwritten'
450 454 def _repr_html_(self):
451 455 return '<b>hi!</b>'
452 456
453 457 f = get_ipython().display_formatter
454 458 html_f = f.formatters['text/html']
455 459 save_enabled = html_f.enabled
456 460 html_f.enabled = True
457 461 obj = HasReprMime()
458 462 d, md = f.format(obj)
459 463 html_f.enabled = save_enabled
460 464
461 nt.assert_equal(sorted(d), ['application/json+test.v2', 'text/html', 'text/plain'])
465 nt.assert_equal(sorted(d), ['application/json+test.v2',
466 'image/png',
467 'plain/text',
468 'text/html',
469 'text/plain'])
462 470 nt.assert_equal(md, {})
463 471
472 d, md = f.format(obj, include={'image/png'})
473 nt.assert_equal(list(d.keys()), ['image/png'],
474 'Include should filter out even things from repr_mimebundle')
475 nt.assert_equal(d['image/png'], 'i-overwrite', '_repr_mimebundle_ take precedence')
476
464 477
465 478 def test_repr_mime_meta():
466 479 class HasReprMimeMeta(object):
467 480 def _repr_mimebundle_(self):
468 481 data = {
469 482 'image/png': 'base64-image-data',
470 483 }
471 484 metadata = {
472 485 'image/png': {
473 486 'width': 5,
474 487 'height': 10,
475 488 }
476 489 }
477 490 return (data, metadata)
478 491
479 492 f = get_ipython().display_formatter
480 493 obj = HasReprMimeMeta()
481 494 d, md = f.format(obj)
482 495 nt.assert_equal(sorted(d), ['image/png', 'text/plain'])
483 496 nt.assert_equal(md, {
484 497 'image/png': {
485 498 'width': 5,
486 499 'height': 10,
487 500 }
488 501 })
489 502
490 503
General Comments 0
You need to be logged in to leave comments. Login now