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