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