Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/IPython/core/display_functions.py: 24%
83 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1# -*- coding: utf-8 -*-
2"""Top-level display functions for displaying object in different formats."""
4# Copyright (c) IPython Development Team.
5# Distributed under the terms of the Modified BSD License.
8from binascii import b2a_hex
9import os
10import sys
11import warnings
13__all__ = ['display', 'clear_output', 'publish_display_data', 'update_display', 'DisplayHandle']
15#-----------------------------------------------------------------------------
16# utility functions
17#-----------------------------------------------------------------------------
20def _merge(d1, d2):
21 """Like update, but merges sub-dicts instead of clobbering at the top level.
23 Updates d1 in-place
24 """
26 if not isinstance(d2, dict) or not isinstance(d1, dict):
27 return d2
28 for key, value in d2.items():
29 d1[key] = _merge(d1.get(key), value)
30 return d1
33#-----------------------------------------------------------------------------
34# Main functions
35#-----------------------------------------------------------------------------
37class _Sentinel:
38 def __repr__(self):
39 return "<deprecated>"
42_sentinel = _Sentinel()
44# use * to indicate transient is keyword-only
45def publish_display_data(
46 data, metadata=None, source=_sentinel, *, transient=None, **kwargs
47):
48 """Publish data and metadata to all frontends.
50 See the ``display_data`` message in the messaging documentation for
51 more details about this message type.
53 Keys of data and metadata can be any mime-type.
55 Parameters
56 ----------
57 data : dict
58 A dictionary having keys that are valid MIME types (like
59 'text/plain' or 'image/svg+xml') and values that are the data for
60 that MIME type. The data itself must be a JSON'able data
61 structure. Minimally all data should have the 'text/plain' data,
62 which can be displayed by all frontends. If more than the plain
63 text is given, it is up to the frontend to decide which
64 representation to use.
65 metadata : dict
66 A dictionary for metadata related to the data. This can contain
67 arbitrary key, value pairs that frontends can use to interpret
68 the data. mime-type keys matching those in data can be used
69 to specify metadata about particular representations.
70 source : str, deprecated
71 Unused.
72 transient : dict, keyword-only
73 A dictionary of transient data, such as display_id.
74 """
75 from IPython.core.interactiveshell import InteractiveShell
77 if source is not _sentinel:
78 warnings.warn(
79 "The `source` parameter emit a deprecation warning since"
80 " IPython 8.0, it had no effects for a long time and will "
81 " be removed in future versions.",
82 DeprecationWarning,
83 stacklevel=2,
84 )
85 display_pub = InteractiveShell.instance().display_pub
87 # only pass transient if supplied,
88 # to avoid errors with older ipykernel.
89 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
90 if transient:
91 kwargs['transient'] = transient
93 display_pub.publish(
94 data=data,
95 metadata=metadata,
96 **kwargs
97 )
100def _new_id():
101 """Generate a new random text id with urandom"""
102 return b2a_hex(os.urandom(16)).decode('ascii')
105def display(
106 *objs,
107 include=None,
108 exclude=None,
109 metadata=None,
110 transient=None,
111 display_id=None,
112 raw=False,
113 clear=False,
114 **kwargs
115):
116 """Display a Python object in all frontends.
118 By default all representations will be computed and sent to the frontends.
119 Frontends can decide which representation is used and how.
121 In terminal IPython this will be similar to using :func:`print`, for use in richer
122 frontends see Jupyter notebook examples with rich display logic.
124 Parameters
125 ----------
126 *objs : object
127 The Python objects to display.
128 raw : bool, optional
129 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
130 or Python objects that need to be formatted before display? [default: False]
131 include : list, tuple or set, optional
132 A list of format type strings (MIME types) to include in the
133 format data dict. If this is set *only* the format types included
134 in this list will be computed.
135 exclude : list, tuple or set, optional
136 A list of format type strings (MIME types) to exclude in the format
137 data dict. If this is set all format types will be computed,
138 except for those included in this argument.
139 metadata : dict, optional
140 A dictionary of metadata to associate with the output.
141 mime-type keys in this dictionary will be associated with the individual
142 representation formats, if they exist.
143 transient : dict, optional
144 A dictionary of transient data to associate with the output.
145 Data in this dict should not be persisted to files (e.g. notebooks).
146 display_id : str, bool optional
147 Set an id for the display.
148 This id can be used for updating this display area later via update_display.
149 If given as `True`, generate a new `display_id`
150 clear : bool, optional
151 Should the output area be cleared before displaying anything? If True,
152 this will wait for additional output before clearing. [default: False]
153 **kwargs : additional keyword-args, optional
154 Additional keyword-arguments are passed through to the display publisher.
156 Returns
157 -------
158 handle: DisplayHandle
159 Returns a handle on updatable displays for use with :func:`update_display`,
160 if `display_id` is given. Returns :any:`None` if no `display_id` is given
161 (default).
163 Examples
164 --------
165 >>> class Json(object):
166 ... def __init__(self, json):
167 ... self.json = json
168 ... def _repr_pretty_(self, pp, cycle):
169 ... import json
170 ... pp.text(json.dumps(self.json, indent=2))
171 ... def __repr__(self):
172 ... return str(self.json)
173 ...
175 >>> d = Json({1:2, 3: {4:5}})
177 >>> print(d)
178 {1: 2, 3: {4: 5}}
180 >>> display(d)
181 {
182 "1": 2,
183 "3": {
184 "4": 5
185 }
186 }
188 >>> def int_formatter(integer, pp, cycle):
189 ... pp.text('I'*integer)
191 >>> plain = get_ipython().display_formatter.formatters['text/plain']
192 >>> plain.for_type(int, int_formatter)
193 <function _repr_pprint at 0x...>
194 >>> display(7-5)
195 II
197 >>> del plain.type_printers[int]
198 >>> display(7-5)
199 2
201 See Also
202 --------
203 :func:`update_display`
205 Notes
206 -----
207 In Python, objects can declare their textual representation using the
208 `__repr__` method. IPython expands on this idea and allows objects to declare
209 other, rich representations including:
211 - HTML
212 - JSON
213 - PNG
214 - JPEG
215 - SVG
216 - LaTeX
218 A single object can declare some or all of these representations; all are
219 handled by IPython's display system.
221 The main idea of the first approach is that you have to implement special
222 display methods when you define your class, one for each representation you
223 want to use. Here is a list of the names of the special methods and the
224 values they must return:
226 - `_repr_html_`: return raw HTML as a string, or a tuple (see below).
227 - `_repr_json_`: return a JSONable dict, or a tuple (see below).
228 - `_repr_jpeg_`: return raw JPEG data, or a tuple (see below).
229 - `_repr_png_`: return raw PNG data, or a tuple (see below).
230 - `_repr_svg_`: return raw SVG data as a string, or a tuple (see below).
231 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$",
232 or a tuple (see below).
233 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
234 from all mimetypes to data.
235 Use this for any mime-type not listed above.
237 The above functions may also return the object's metadata alonside the
238 data. If the metadata is available, the functions will return a tuple
239 containing the data and metadata, in that order. If there is no metadata
240 available, then the functions will return the data only.
242 When you are directly writing your own classes, you can adapt them for
243 display in IPython by following the above approach. But in practice, you
244 often need to work with existing classes that you can't easily modify.
246 You can refer to the documentation on integrating with the display system in
247 order to register custom formatters for already existing types
248 (:ref:`integrating_rich_display`).
250 .. versionadded:: 5.4 display available without import
251 .. versionadded:: 6.1 display available without import
253 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
254 the user without import. If you are using display in a document that might
255 be used in a pure python context or with older version of IPython, use the
256 following import at the top of your file::
258 from IPython.display import display
260 """
261 from IPython.core.interactiveshell import InteractiveShell
263 if not InteractiveShell.initialized():
264 # Directly print objects.
265 print(*objs)
266 return
268 if transient is None:
269 transient = {}
270 if metadata is None:
271 metadata={}
272 if display_id:
273 if display_id is True:
274 display_id = _new_id()
275 transient['display_id'] = display_id
276 if kwargs.get('update') and 'display_id' not in transient:
277 raise TypeError('display_id required for update_display')
278 if transient:
279 kwargs['transient'] = transient
281 if not objs and display_id:
282 # if given no objects, but still a request for a display_id,
283 # we assume the user wants to insert an empty output that
284 # can be updated later
285 objs = [{}]
286 raw = True
288 if not raw:
289 format = InteractiveShell.instance().display_formatter.format
291 if clear:
292 clear_output(wait=True)
294 for obj in objs:
295 if raw:
296 publish_display_data(data=obj, metadata=metadata, **kwargs)
297 else:
298 format_dict, md_dict = format(obj, include=include, exclude=exclude)
299 if not format_dict:
300 # nothing to display (e.g. _ipython_display_ took over)
301 continue
302 if metadata:
303 # kwarg-specified metadata gets precedence
304 _merge(md_dict, metadata)
305 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
306 if display_id:
307 return DisplayHandle(display_id)
310# use * for keyword-only display_id arg
311def update_display(obj, *, display_id, **kwargs):
312 """Update an existing display by id
314 Parameters
315 ----------
316 obj
317 The object with which to update the display
318 display_id : keyword-only
319 The id of the display to update
321 See Also
322 --------
323 :func:`display`
324 """
325 kwargs['update'] = True
326 display(obj, display_id=display_id, **kwargs)
329class DisplayHandle(object):
330 """A handle on an updatable display
332 Call `.update(obj)` to display a new object.
334 Call `.display(obj`) to add a new instance of this display,
335 and update existing instances.
337 See Also
338 --------
340 :func:`display`, :func:`update_display`
342 """
344 def __init__(self, display_id=None):
345 if display_id is None:
346 display_id = _new_id()
347 self.display_id = display_id
349 def __repr__(self):
350 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
352 def display(self, obj, **kwargs):
353 """Make a new display with my id, updating existing instances.
355 Parameters
356 ----------
357 obj
358 object to display
359 **kwargs
360 additional keyword arguments passed to display
361 """
362 display(obj, display_id=self.display_id, **kwargs)
364 def update(self, obj, **kwargs):
365 """Update existing displays with my id
367 Parameters
368 ----------
369 obj
370 object to display
371 **kwargs
372 additional keyword arguments passed to update_display
373 """
374 update_display(obj, display_id=self.display_id, **kwargs)
377def clear_output(wait=False):
378 """Clear the output of the current cell receiving output.
380 Parameters
381 ----------
382 wait : bool [default: false]
383 Wait to clear the output until new output is available to replace it."""
384 from IPython.core.interactiveshell import InteractiveShell
385 if InteractiveShell.initialized():
386 InteractiveShell.instance().display_pub.clear_output(wait)
387 else:
388 print('\033[2K\r', end='')
389 sys.stdout.flush()
390 print('\033[2K\r', end='')
391 sys.stderr.flush()