displaypub.py
138 lines
| 4.8 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r3277 | """An interface for publishing rich data to frontends. | ||
Brian Granger
|
r3276 | |||
Brian Granger
|
r3278 | There are two components of the display system: | ||
* Display formatters, which take a Python object and compute the | ||||
MinRK
|
r10447 | representation of the object in various formats (text, HTML, SVG, etc.). | ||
Brian Granger
|
r3278 | * The display publisher that is used to send the representation data to the | ||
various frontends. | ||||
This module defines the logic display publishing. The display publisher uses | ||||
the ``display_data`` message type that is defined in the IPython messaging | ||||
spec. | ||||
Brian Granger
|
r3276 | """ | ||
MinRK
|
r16585 | # Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||||
Brian Granger
|
r3276 | |||
Brian Granger
|
r3286 | |||
Thomas Kluyver
|
r22192 | import sys | ||
Min RK
|
r21253 | from traitlets.config.configurable import Configurable | ||
Matthias Bussonnier
|
r25335 | from traitlets import List | ||
Brian Granger
|
r3276 | |||
Thomas Kluyver
|
r17124 | # This used to be defined here - it is imported for backwards compatibility | ||
Matthias Bussonnier
|
r25632 | from .display_functions import publish_display_data | ||
Thomas Kluyver
|
r17124 | |||
Brian Granger
|
r3276 | #----------------------------------------------------------------------------- | ||
# Main payload class | ||||
#----------------------------------------------------------------------------- | ||||
Matthias Bussonnier
|
r25164 | |||
Brian Granger
|
r3276 | class DisplayPublisher(Configurable): | ||
Brian Granger
|
r3278 | """A traited class that publishes display data to frontends. | ||
Instances of this class are created by the main IPython object and should | ||||
be accessed there. | ||||
""" | ||||
Brian Granger
|
r3276 | |||
Matthias Bussonnier
|
r25164 | def __init__(self, shell=None, *args, **kwargs): | ||
self.shell = shell | ||||
super().__init__(*args, **kwargs) | ||||
MinRK
|
r16585 | def _validate_data(self, data, metadata=None): | ||
Brian Granger
|
r3278 | """Validate the display data. | ||
Parameters | ||||
---------- | ||||
data : dict | ||||
The formata data dictionary. | ||||
metadata : dict | ||||
Any metadata for the data. | ||||
""" | ||||
Brian Granger
|
r3276 | if not isinstance(data, dict): | ||
raise TypeError('data must be a dict, got: %r' % data) | ||||
if metadata is not None: | ||||
if not isinstance(metadata, dict): | ||||
raise TypeError('metadata must be a dict, got: %r' % data) | ||||
Min RK
|
r23015 | # use * to indicate transient, update are keyword-only | ||
Matthias Bussonnier
|
r25164 | def publish(self, data, metadata=None, source=None, *, transient=None, update=False, **kwargs) -> None: | ||
Brian Granger
|
r3277 | """Publish data and metadata to all frontends. | ||
Brian Granger
|
r3276 | |||
Brian Granger
|
r3277 | See the ``display_data`` message in the messaging documentation for | ||
more details about this message type. | ||||
Brian Granger
|
r3278 | The following MIME types are currently implemented: | ||
* text/plain | ||||
* text/html | ||||
Andrew Jesaitis
|
r16364 | * text/markdown | ||
Brian Granger
|
r3278 | * text/latex | ||
* application/json | ||||
Brian E. Granger
|
r4526 | * application/javascript | ||
Brian Granger
|
r3278 | * image/png | ||
Brian E. Granger
|
r4528 | * image/jpeg | ||
Brian E. Granger
|
r4526 | * image/svg+xml | ||
Brian Granger
|
r3278 | |||
Brian Granger
|
r3277 | Parameters | ||
---------- | ||||
data : dict | ||||
Bernardo B. Marques
|
r4872 | A dictionary having keys that are valid MIME types (like | ||
Brian Granger
|
r3277 | 'text/plain' or 'image/svg+xml') and values that are the data for | ||
that MIME type. The data itself must be a JSON'able data | ||||
structure. Minimally all data should have the 'text/plain' data, | ||||
which can be displayed by all frontends. If more than the plain | ||||
text is given, it is up to the frontend to decide which | ||||
representation to use. | ||||
metadata : dict | ||||
A dictionary for metadata related to the data. This can contain | ||||
arbitrary key, value pairs that frontends can use to interpret | ||||
MinRK
|
r10446 | the data. Metadata specific to each mime-type can be specified | ||
in the metadata dict with the same mime-type keys as | ||||
the data itself. | ||||
MinRK
|
r16585 | source : str, deprecated | ||
Unused. | ||||
Matthias Bussonnier
|
r26498 | transient : dict, keyword-only | ||
Min RK
|
r23015 | A dictionary for transient data. | ||
Data in this dictionary should not be persisted as part of saving this output. | ||||
Examples include 'display_id'. | ||||
Matthias Bussonnier
|
r26498 | update : bool, keyword-only, default: False | ||
Min RK
|
r23015 | If True, only update existing outputs with the same display_id, | ||
rather than creating a new output. | ||||
Brian Granger
|
r3277 | """ | ||
MinRK
|
r6422 | |||
Matthias Bussonnier
|
r25164 | handlers = {} | ||
if self.shell is not None: | ||||
Matthias Bussonnier
|
r25278 | handlers = getattr(self.shell, 'mime_renderers', {}) | ||
Matthias Bussonnier
|
r25164 | |||
for mime, handler in handlers.items(): | ||||
if mime in data: | ||||
handler(data[mime], metadata.get(mime, None)) | ||||
return | ||||
Bradley M. Froehle
|
r7859 | if 'text/plain' in data: | ||
Thomas Kluyver
|
r22192 | print(data['text/plain']) | ||
Brian Granger
|
r3277 | |||
Jonathan Frederic
|
r12592 | def clear_output(self, wait=False): | ||
MinRK
|
r6422 | """Clear the output of the cell receiving output.""" | ||
Thomas Kluyver
|
r22192 | print('\033[2K\r', end='') | ||
sys.stdout.flush() | ||||
print('\033[2K\r', end='') | ||||
sys.stderr.flush() | ||||
MinRK
|
r12223 | |||
class CapturingDisplayPublisher(DisplayPublisher): | ||||
"""A DisplayPublisher that stores""" | ||||
outputs = List() | ||||
Henry Fredrick Schreiner
|
r23963 | def publish(self, data, metadata=None, source=None, *, transient=None, update=False): | ||
Henry Fredrick Schreiner
|
r23969 | self.outputs.append({'data':data, 'metadata':metadata, | ||
'transient':transient, 'update':update}) | ||||
Henry Fredrick Schreiner
|
r23963 | |||
Jonathan Frederic
|
r12592 | def clear_output(self, wait=False): | ||
super(CapturingDisplayPublisher, self).clear_output(wait) | ||||
Henry Fredrick Schreiner
|
r23963 | |||
Jonathan Frederic
|
r13904 | # empty the list, *do not* reassign a new list | ||
Henry Fredrick Schreiner
|
r23969 | self.outputs.clear() | ||