##// END OF EJS Templates
Document _repr_mimebundle_...
Matthias Bussonnier -
Show More

The requested changes are too big and content was truncated. Show full diff

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