Show More
@@ -1,6 +1,61 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """Display formatters. |
|
2 | """Display formatters. | |
3 |
|
3 | |||
|
4 | This module defines the base instances in order to implement custom | |||
|
5 | formatters/mimetypes | |||
|
6 | got objects: | |||
|
7 | ||||
|
8 | As we want to see internal IPython working we are going to use the following | |||
|
9 | function to diaply objects instead of the normal print or display method: | |||
|
10 | ||||
|
11 | >>> ip = get_ipython() | |||
|
12 | >>> ip.display_formatter.format(...) | |||
|
13 | ({'text/plain': 'Ellipsis'}, {}) | |||
|
14 | ||||
|
15 | This return a tuple with the mimebumdle for the current object, and the | |||
|
16 | associated metadata. | |||
|
17 | ||||
|
18 | ||||
|
19 | We can now define our own formatter and register it: | |||
|
20 | ||||
|
21 | ||||
|
22 | >>> from IPython.core.formatters import BaseFormatter, FormatterABC | |||
|
23 | ||||
|
24 | ||||
|
25 | >>> class LLMFormatter(BaseFormatter): | |||
|
26 | ... | |||
|
27 | ... format_type = 'x-vendor/llm' | |||
|
28 | ... print_method = '_repr_llm_' | |||
|
29 | ... _return_type = (dict, str) | |||
|
30 | ||||
|
31 | >>> llm_formatter = LLMFormatter(parent=ip.display_formatter) | |||
|
32 | ||||
|
33 | >>> ip.display_formatter.formatters[LLMFormatter.format_type] = llm_formatter | |||
|
34 | ||||
|
35 | Now any class that define `_repr_llm_` will return a x-vendor/llm as part of | |||
|
36 | it's display data: | |||
|
37 | ||||
|
38 | >>> class A: | |||
|
39 | ... | |||
|
40 | ... def _repr_llm_(self, *kwargs): | |||
|
41 | ... return 'This a A' | |||
|
42 | ... | |||
|
43 | ||||
|
44 | >>> ip.display_formatter.format(A()) | |||
|
45 | ({'text/plain': '<IPython.core.formatters.A at ...>', 'x-vendor/llm': 'This a A'}, {}) | |||
|
46 | ||||
|
47 | As usual, you can register methods for third party types (see | |||
|
48 | :ref:`third_party_formatting`) | |||
|
49 | ||||
|
50 | >>> def llm_int(obj): | |||
|
51 | ... return 'This is the integer %s, in between %s and %s'%(obj, obj-1, obj+1) | |||
|
52 | ||||
|
53 | >>> llm_formatter.for_type(int, llm_int) | |||
|
54 | ||||
|
55 | >>> ip.display_formatter.format(42) | |||
|
56 | ({'text/plain': '42', 'x-vendor/llm': 'This is the integer 42, in between 41 and 43'}, {}) | |||
|
57 | ||||
|
58 | ||||
4 | Inheritance diagram: |
|
59 | Inheritance diagram: | |
5 |
|
60 | |||
6 | .. inheritance-diagram:: IPython.core.formatters |
|
61 | .. inheritance-diagram:: IPython.core.formatters | |
@@ -37,9 +92,10 b' class DisplayFormatter(Configurable):' | |||||
37 | active_types = List(Unicode(), |
|
92 | active_types = List(Unicode(), | |
38 | help="""List of currently active mime-types to display. |
|
93 | help="""List of currently active mime-types to display. | |
39 | You can use this to set a white-list for formats to display. |
|
94 | You can use this to set a white-list for formats to display. | |
40 |
|
95 | |||
41 | Most users will not need to change this value. |
|
96 | Most users will not need to change this value. | |
42 | """).tag(config=True) |
|
97 | """, | |
|
98 | ).tag(config=True) | |||
43 |
|
99 | |||
44 | @default('active_types') |
|
100 | @default('active_types') | |
45 | def _active_types_default(self): |
|
101 | def _active_types_default(self): | |
@@ -144,7 +200,7 b' class DisplayFormatter(Configurable):' | |||||
144 | """ |
|
200 | """ | |
145 | format_dict = {} |
|
201 | format_dict = {} | |
146 | md_dict = {} |
|
202 | md_dict = {} | |
147 |
|
203 | |||
148 | if self.ipython_display_formatter(obj): |
|
204 | if self.ipython_display_formatter(obj): | |
149 | # object handled itself, don't proceed |
|
205 | # object handled itself, don't proceed | |
150 | return {}, {} |
|
206 | return {}, {} | |
@@ -176,18 +232,18 b' class DisplayFormatter(Configurable):' | |||||
176 | continue |
|
232 | continue | |
177 | if exclude and format_type in exclude: |
|
233 | if exclude and format_type in exclude: | |
178 | continue |
|
234 | continue | |
179 |
|
235 | |||
180 | md = None |
|
236 | md = None | |
181 | try: |
|
237 | try: | |
182 | data = formatter(obj) |
|
238 | data = formatter(obj) | |
183 | except: |
|
239 | except: | |
184 | # FIXME: log the exception |
|
240 | # FIXME: log the exception | |
185 | raise |
|
241 | raise | |
186 |
|
242 | |||
187 | # formatters can return raw data or (data, metadata) |
|
243 | # formatters can return raw data or (data, metadata) | |
188 | if isinstance(data, tuple) and len(data) == 2: |
|
244 | if isinstance(data, tuple) and len(data) == 2: | |
189 | data, md = data |
|
245 | data, md = data | |
190 |
|
246 | |||
191 | if data is not None: |
|
247 | if data is not None: | |
192 | format_dict[format_type] = data |
|
248 | format_dict[format_type] = data | |
193 | if md is not None: |
|
249 | if md is not None: | |
@@ -252,7 +308,7 b' class FormatterABC(metaclass=abc.ABCMeta):' | |||||
252 |
|
308 | |||
253 | # Is the formatter enabled... |
|
309 | # Is the formatter enabled... | |
254 | enabled = True |
|
310 | enabled = True | |
255 |
|
311 | |||
256 | @abc.abstractmethod |
|
312 | @abc.abstractmethod | |
257 | def __call__(self, obj): |
|
313 | def __call__(self, obj): | |
258 | """Return a JSON'able representation of the object. |
|
314 | """Return a JSON'able representation of the object. | |
@@ -278,12 +334,15 b' def _get_type(obj):' | |||||
278 | return getattr(obj, '__class__', None) or type(obj) |
|
334 | return getattr(obj, '__class__', None) or type(obj) | |
279 |
|
335 | |||
280 |
|
336 | |||
281 |
_raise_key_error = Sentinel( |
|
337 | _raise_key_error = Sentinel( | |
282 | """ |
|
338 | "_raise_key_error", | |
|
339 | __name__, | |||
|
340 | """ | |||
283 | Special value to raise a KeyError |
|
341 | Special value to raise a KeyError | |
284 |
|
342 | |||
285 | Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop` |
|
343 | Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop` | |
286 |
""" |
|
344 | """, | |
|
345 | ) | |||
287 |
|
346 | |||
288 |
|
347 | |||
289 | class BaseFormatter(Configurable): |
|
348 | class BaseFormatter(Configurable): | |
@@ -329,7 +388,7 b' class BaseFormatter(Configurable):' | |||||
329 | # The deferred-import type-specific printers. |
|
388 | # The deferred-import type-specific printers. | |
330 | # Map (modulename, classname) pairs to the format functions. |
|
389 | # Map (modulename, classname) pairs to the format functions. | |
331 | deferred_printers = Dict().tag(config=True) |
|
390 | deferred_printers = Dict().tag(config=True) | |
332 |
|
391 | |||
333 | @catch_format_error |
|
392 | @catch_format_error | |
334 | def __call__(self, obj): |
|
393 | def __call__(self, obj): | |
335 | """Compute the format for an object.""" |
|
394 | """Compute the format for an object.""" | |
@@ -348,7 +407,7 b' class BaseFormatter(Configurable):' | |||||
348 | return None |
|
407 | return None | |
349 | else: |
|
408 | else: | |
350 | return None |
|
409 | return None | |
351 |
|
410 | |||
352 | def __contains__(self, typ): |
|
411 | def __contains__(self, typ): | |
353 | """map in to lookup_by_type""" |
|
412 | """map in to lookup_by_type""" | |
354 | try: |
|
413 | try: | |
@@ -357,7 +416,7 b' class BaseFormatter(Configurable):' | |||||
357 | return False |
|
416 | return False | |
358 | else: |
|
417 | else: | |
359 | return True |
|
418 | return True | |
360 |
|
419 | |||
361 | def _check_return(self, r, obj): |
|
420 | def _check_return(self, r, obj): | |
362 | """Check that a return value is appropriate |
|
421 | """Check that a return value is appropriate | |
363 |
|
422 | |||
@@ -372,7 +431,7 b' class BaseFormatter(Configurable):' | |||||
372 | (self.format_type, type(r), self._return_type, _safe_repr(obj)), |
|
431 | (self.format_type, type(r), self._return_type, _safe_repr(obj)), | |
373 | FormatterWarning |
|
432 | FormatterWarning | |
374 | ) |
|
433 | ) | |
375 |
|
434 | |||
376 | def lookup(self, obj): |
|
435 | def lookup(self, obj): | |
377 | """Look up the formatter for a given instance. |
|
436 | """Look up the formatter for a given instance. | |
378 |
|
437 | |||
@@ -395,7 +454,7 b' class BaseFormatter(Configurable):' | |||||
395 | return self.singleton_printers[obj_id] |
|
454 | return self.singleton_printers[obj_id] | |
396 | # then lookup by type |
|
455 | # then lookup by type | |
397 | return self.lookup_by_type(_get_type(obj)) |
|
456 | return self.lookup_by_type(_get_type(obj)) | |
398 |
|
457 | |||
399 | def lookup_by_type(self, typ): |
|
458 | def lookup_by_type(self, typ): | |
400 | """Look up the registered formatter for a type. |
|
459 | """Look up the registered formatter for a type. | |
401 |
|
460 | |||
@@ -426,7 +485,7 b' class BaseFormatter(Configurable):' | |||||
426 | for cls in pretty._get_mro(typ): |
|
485 | for cls in pretty._get_mro(typ): | |
427 | if cls in self.type_printers or self._in_deferred_types(cls): |
|
486 | if cls in self.type_printers or self._in_deferred_types(cls): | |
428 | return self.type_printers[cls] |
|
487 | return self.type_printers[cls] | |
429 |
|
488 | |||
430 | # If we have reached here, the lookup failed. |
|
489 | # If we have reached here, the lookup failed. | |
431 | raise KeyError("No registered printer for {0!r}".format(typ)) |
|
490 | raise KeyError("No registered printer for {0!r}".format(typ)) | |
432 |
|
491 | |||
@@ -459,15 +518,15 b' class BaseFormatter(Configurable):' | |||||
459 | if isinstance(typ, str): |
|
518 | if isinstance(typ, str): | |
460 | type_module, type_name = typ.rsplit('.', 1) |
|
519 | type_module, type_name = typ.rsplit('.', 1) | |
461 | return self.for_type_by_name(type_module, type_name, func) |
|
520 | return self.for_type_by_name(type_module, type_name, func) | |
462 |
|
521 | |||
463 | try: |
|
522 | try: | |
464 | oldfunc = self.lookup_by_type(typ) |
|
523 | oldfunc = self.lookup_by_type(typ) | |
465 | except KeyError: |
|
524 | except KeyError: | |
466 | oldfunc = None |
|
525 | oldfunc = None | |
467 |
|
526 | |||
468 | if func is not None: |
|
527 | if func is not None: | |
469 | self.type_printers[typ] = func |
|
528 | self.type_printers[typ] = func | |
470 |
|
529 | |||
471 | return oldfunc |
|
530 | return oldfunc | |
472 |
|
531 | |||
473 | def for_type_by_name(self, type_module, type_name, func=None): |
|
532 | def for_type_by_name(self, type_module, type_name, func=None): | |
@@ -501,16 +560,16 b' class BaseFormatter(Configurable):' | |||||
501 | this will be the previous value (to enable restoring later). |
|
560 | this will be the previous value (to enable restoring later). | |
502 | """ |
|
561 | """ | |
503 | key = (type_module, type_name) |
|
562 | key = (type_module, type_name) | |
504 |
|
563 | |||
505 | try: |
|
564 | try: | |
506 | oldfunc = self.lookup_by_type("%s.%s" % key) |
|
565 | oldfunc = self.lookup_by_type("%s.%s" % key) | |
507 | except KeyError: |
|
566 | except KeyError: | |
508 | oldfunc = None |
|
567 | oldfunc = None | |
509 |
|
568 | |||
510 | if func is not None: |
|
569 | if func is not None: | |
511 | self.deferred_printers[key] = func |
|
570 | self.deferred_printers[key] = func | |
512 | return oldfunc |
|
571 | return oldfunc | |
513 |
|
572 | |||
514 | def pop(self, typ, default=_raise_key_error): |
|
573 | def pop(self, typ, default=_raise_key_error): | |
515 | """Pop a formatter for the given type. |
|
574 | """Pop a formatter for the given type. | |
516 |
|
575 | |||
@@ -529,7 +588,7 b' class BaseFormatter(Configurable):' | |||||
529 | ------ |
|
588 | ------ | |
530 | KeyError if the type is not registered and default is not specified. |
|
589 | KeyError if the type is not registered and default is not specified. | |
531 | """ |
|
590 | """ | |
532 |
|
591 | |||
533 | if isinstance(typ, str): |
|
592 | if isinstance(typ, str): | |
534 | typ_key = tuple(typ.rsplit('.',1)) |
|
593 | typ_key = tuple(typ.rsplit('.',1)) | |
535 | if typ_key not in self.deferred_printers: |
|
594 | if typ_key not in self.deferred_printers: | |
@@ -599,14 +658,14 b' class PlainTextFormatter(BaseFormatter):' | |||||
599 | # This subclass ignores this attribute as it always need to return |
|
658 | # This subclass ignores this attribute as it always need to return | |
600 | # something. |
|
659 | # something. | |
601 | enabled = Bool(True).tag(config=False) |
|
660 | enabled = Bool(True).tag(config=False) | |
602 |
|
661 | |||
603 | max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, |
|
662 | max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, | |
604 | help="""Truncate large collections (lists, dicts, tuples, sets) to this size. |
|
663 | help="""Truncate large collections (lists, dicts, tuples, sets) to this size. | |
605 |
|
664 | |||
606 | Set to 0 to disable truncation. |
|
665 | Set to 0 to disable truncation. | |
607 | """ |
|
666 | """, | |
608 | ).tag(config=True) |
|
667 | ).tag(config=True) | |
609 |
|
668 | |||
610 | # Look for a _repr_pretty_ methods to use for pretty printing. |
|
669 | # Look for a _repr_pretty_ methods to use for pretty printing. | |
611 | print_method = ObjectName('_repr_pretty_') |
|
670 | print_method = ObjectName('_repr_pretty_') | |
612 |
|
671 | |||
@@ -775,7 +834,7 b' class PNGFormatter(BaseFormatter):' | |||||
775 | format_type = Unicode('image/png') |
|
834 | format_type = Unicode('image/png') | |
776 |
|
835 | |||
777 | print_method = ObjectName('_repr_png_') |
|
836 | print_method = ObjectName('_repr_png_') | |
778 |
|
837 | |||
779 | _return_type = (bytes, str) |
|
838 | _return_type = (bytes, str) | |
780 |
|
839 | |||
781 |
|
840 | |||
@@ -829,7 +888,7 b' class JSONFormatter(BaseFormatter):' | |||||
829 | _return_type = (list, dict) |
|
888 | _return_type = (list, dict) | |
830 |
|
889 | |||
831 | print_method = ObjectName('_repr_json_') |
|
890 | print_method = ObjectName('_repr_json_') | |
832 |
|
891 | |||
833 | def _check_return(self, r, obj): |
|
892 | def _check_return(self, r, obj): | |
834 | """Check that a return value is appropriate |
|
893 | """Check that a return value is appropriate | |
835 |
|
894 | |||
@@ -887,19 +946,19 b' class PDFFormatter(BaseFormatter):' | |||||
887 |
|
946 | |||
888 | class IPythonDisplayFormatter(BaseFormatter): |
|
947 | class IPythonDisplayFormatter(BaseFormatter): | |
889 | """An escape-hatch Formatter for objects that know how to display themselves. |
|
948 | """An escape-hatch Formatter for objects that know how to display themselves. | |
890 |
|
949 | |||
891 | To define the callables that compute the representation of your |
|
950 | To define the callables that compute the representation of your | |
892 | objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type` |
|
951 | objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type` | |
893 | or :meth:`for_type_by_name` methods to register functions that handle |
|
952 | or :meth:`for_type_by_name` methods to register functions that handle | |
894 | this. Unlike mime-type displays, this method should not return anything, |
|
953 | this. Unlike mime-type displays, this method should not return anything, | |
895 | instead calling any appropriate display methods itself. |
|
954 | instead calling any appropriate display methods itself. | |
896 |
|
955 | |||
897 | This display formatter has highest priority. |
|
956 | This display formatter has highest priority. | |
898 | If it fires, no other display formatter will be called. |
|
957 | If it fires, no other display formatter will be called. | |
899 |
|
958 | |||
900 | Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types |
|
959 | Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types | |
901 | without registering a new Formatter. |
|
960 | without registering a new Formatter. | |
902 |
|
961 | |||
903 | IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types, |
|
962 | IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types, | |
904 | so `_ipython_display_` should only be used for objects that require unusual |
|
963 | so `_ipython_display_` should only be used for objects that require unusual | |
905 | display patterns, such as multiple display calls. |
|
964 | display patterns, such as multiple display calls. | |
@@ -943,7 +1002,7 b' class MimeBundleFormatter(BaseFormatter):' | |||||
943 | """ |
|
1002 | """ | |
944 | print_method = ObjectName('_repr_mimebundle_') |
|
1003 | print_method = ObjectName('_repr_mimebundle_') | |
945 | _return_type = dict |
|
1004 | _return_type = dict | |
946 |
|
1005 | |||
947 | def _check_return(self, r, obj): |
|
1006 | def _check_return(self, r, obj): | |
948 | r = super(MimeBundleFormatter, self)._check_return(r, obj) |
|
1007 | r = super(MimeBundleFormatter, self)._check_return(r, obj) | |
949 | # always return (data, metadata): |
|
1008 | # always return (data, metadata): |
@@ -9,7 +9,7 b' Tab completion' | |||||
9 |
|
9 | |||
10 | To change the attributes displayed by tab-completing your object, define a |
|
10 | To change the attributes displayed by tab-completing your object, define a | |
11 | ``__dir__(self)`` method for it. For more details, see the documentation of the |
|
11 | ``__dir__(self)`` method for it. For more details, see the documentation of the | |
12 | built-in `dir() function <http://docs.python.org/library/functions.html#dir>`_. |
|
12 | built-in :external+python:py:func:`dir` | |
13 |
|
13 | |||
14 | You can also customise key completions for your objects, e.g. pressing tab after |
|
14 | You can also customise key completions for your objects, e.g. pressing tab after | |
15 | ``obj["a``. To do so, define a method ``_ipython_key_completions_()``, which |
|
15 | ``obj["a``. To do so, define a method ``_ipython_key_completions_()``, which | |
@@ -25,7 +25,7 b' Rich display' | |||||
25 | ============ |
|
25 | ============ | |
26 |
|
26 | |||
27 | Custom methods |
|
27 | Custom methods | |
28 |
-------------- |
|
28 | -------------- | |
29 |
|
29 | |||
30 | IPython can display richer representations of objects. |
|
30 | IPython can display richer representations of objects. | |
31 | To do this, you can define ``_ipython_display_()``, or any of a number of |
|
31 | To do this, you can define ``_ipython_display_()``, or any of a number of | |
@@ -154,6 +154,8 b' to inform the frontend how to size the image.' | |||||
154 |
|
154 | |||
155 |
|
155 | |||
156 |
|
156 | |||
|
157 | .. _third_party_formatting: | |||
|
158 | ||||
157 | Formatters for third-party types |
|
159 | Formatters for third-party types | |
158 | -------------------------------- |
|
160 | -------------------------------- | |
159 |
|
161 |
General Comments 0
You need to be logged in to leave comments.
Login now