##// END OF EJS Templates
Add update_display...
Min RK -
Show More
@@ -1,1030 +1,1052 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 try:
8 try:
9 from base64 import encodebytes as base64_encode
9 from base64 import encodebytes as base64_encode
10 except ImportError:
10 except ImportError:
11 from base64 import encodestring as base64_encode
11 from base64 import encodestring as base64_encode
12
12
13 import json
13 import json
14 import mimetypes
14 import mimetypes
15 import os
15 import os
16 import struct
16 import struct
17 import sys
17 import sys
18 import warnings
18 import warnings
19
19
20 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
20 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
21 unicode_type)
21 unicode_type)
22 from IPython.testing.skipdoctest import skip_doctest
22 from IPython.testing.skipdoctest import skip_doctest
23
23
24 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
24 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
25 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
25 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
26 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
26 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
27 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
27 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
28 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
28 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
29 'publish_display_data']
29 'publish_display_data', 'update_display']
30
30
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 # utility functions
32 # utility functions
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34
34
35 def _safe_exists(path):
35 def _safe_exists(path):
36 """Check path, but don't let exceptions raise"""
36 """Check path, but don't let exceptions raise"""
37 try:
37 try:
38 return os.path.exists(path)
38 return os.path.exists(path)
39 except Exception:
39 except Exception:
40 return False
40 return False
41
41
42 def _merge(d1, d2):
42 def _merge(d1, d2):
43 """Like update, but merges sub-dicts instead of clobbering at the top level.
43 """Like update, but merges sub-dicts instead of clobbering at the top level.
44
44
45 Updates d1 in-place
45 Updates d1 in-place
46 """
46 """
47
47
48 if not isinstance(d2, dict) or not isinstance(d1, dict):
48 if not isinstance(d2, dict) or not isinstance(d1, dict):
49 return d2
49 return d2
50 for key, value in d2.items():
50 for key, value in d2.items():
51 d1[key] = _merge(d1.get(key), value)
51 d1[key] = _merge(d1.get(key), value)
52 return d1
52 return d1
53
53
54 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
54 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
55 """internal implementation of all display_foo methods
55 """internal implementation of all display_foo methods
56
56
57 Parameters
57 Parameters
58 ----------
58 ----------
59 mimetype : str
59 mimetype : str
60 The mimetype to be published (e.g. 'image/png')
60 The mimetype to be published (e.g. 'image/png')
61 objs : tuple of objects
61 objs : tuple of objects
62 The Python objects to display, or if raw=True raw text data to
62 The Python objects to display, or if raw=True raw text data to
63 display.
63 display.
64 raw : bool
64 raw : bool
65 Are the data objects raw data or Python objects that need to be
65 Are the data objects raw data or Python objects that need to be
66 formatted before display? [default: False]
66 formatted before display? [default: False]
67 metadata : dict (optional)
67 metadata : dict (optional)
68 Metadata to be associated with the specific mimetype output.
68 Metadata to be associated with the specific mimetype output.
69 """
69 """
70 if metadata:
70 if metadata:
71 metadata = {mimetype: metadata}
71 metadata = {mimetype: metadata}
72 if raw:
72 if raw:
73 # turn list of pngdata into list of { 'image/png': pngdata }
73 # turn list of pngdata into list of { 'image/png': pngdata }
74 objs = [ {mimetype: obj} for obj in objs ]
74 objs = [ {mimetype: obj} for obj in objs ]
75 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
75 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Main functions
78 # Main functions
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81 def publish_display_data(data, metadata=None, source=None):
81 def publish_display_data(data, metadata=None, source=None, transient=None, **kwargs):
82 """Publish data and metadata to all frontends.
82 """Publish data and metadata to all frontends.
83
83
84 See the ``display_data`` message in the messaging documentation for
84 See the ``display_data`` message in the messaging documentation for
85 more details about this message type.
85 more details about this message type.
86
86
87 The following MIME types are currently implemented:
87 The following MIME types are currently implemented:
88
88
89 * text/plain
89 * text/plain
90 * text/html
90 * text/html
91 * text/markdown
91 * text/markdown
92 * text/latex
92 * text/latex
93 * application/json
93 * application/json
94 * application/javascript
94 * application/javascript
95 * image/png
95 * image/png
96 * image/jpeg
96 * image/jpeg
97 * image/svg+xml
97 * image/svg+xml
98
98
99 Parameters
99 Parameters
100 ----------
100 ----------
101 data : dict
101 data : dict
102 A dictionary having keys that are valid MIME types (like
102 A dictionary having keys that are valid MIME types (like
103 'text/plain' or 'image/svg+xml') and values that are the data for
103 'text/plain' or 'image/svg+xml') and values that are the data for
104 that MIME type. The data itself must be a JSON'able data
104 that MIME type. The data itself must be a JSON'able data
105 structure. Minimally all data should have the 'text/plain' data,
105 structure. Minimally all data should have the 'text/plain' data,
106 which can be displayed by all frontends. If more than the plain
106 which can be displayed by all frontends. If more than the plain
107 text is given, it is up to the frontend to decide which
107 text is given, it is up to the frontend to decide which
108 representation to use.
108 representation to use.
109 metadata : dict
109 metadata : dict
110 A dictionary for metadata related to the data. This can contain
110 A dictionary for metadata related to the data. This can contain
111 arbitrary key, value pairs that frontends can use to interpret
111 arbitrary key, value pairs that frontends can use to interpret
112 the data. mime-type keys matching those in data can be used
112 the data. mime-type keys matching those in data can be used
113 to specify metadata about particular representations.
113 to specify metadata about particular representations.
114 source : str, deprecated
114 source : str, deprecated
115 Unused.
115 Unused.
116 traisient : dict
117 A dictionary of transient data.
116 """
118 """
117 from IPython.core.interactiveshell import InteractiveShell
119 from IPython.core.interactiveshell import InteractiveShell
118 InteractiveShell.instance().display_pub.publish(
120 InteractiveShell.instance().display_pub.publish(
119 data=data,
121 data=data,
120 metadata=metadata,
122 metadata=metadata,
123 transient=transient,
124 **kwargs
121 )
125 )
122
126
123 def display(*objs, **kwargs):
127 def display(*objs, **kwargs):
124 """Display a Python object in all frontends.
128 """Display a Python object in all frontends.
125
129
126 By default all representations will be computed and sent to the frontends.
130 By default all representations will be computed and sent to the frontends.
127 Frontends can decide which representation is used and how.
131 Frontends can decide which representation is used and how.
128
132
129 Parameters
133 Parameters
130 ----------
134 ----------
131 objs : tuple of objects
135 objs : tuple of objects
132 The Python objects to display.
136 The Python objects to display.
133 raw : bool, optional
137 raw : bool, optional
134 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
138 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
135 or Python objects that need to be formatted before display? [default: False]
139 or Python objects that need to be formatted before display? [default: False]
136 include : list or tuple, optional
140 include : list or tuple, optional
137 A list of format type strings (MIME types) to include in the
141 A list of format type strings (MIME types) to include in the
138 format data dict. If this is set *only* the format types included
142 format data dict. If this is set *only* the format types included
139 in this list will be computed.
143 in this list will be computed.
140 exclude : list or tuple, optional
144 exclude : list or tuple, optional
141 A list of format type strings (MIME types) to exclude in the format
145 A list of format type strings (MIME types) to exclude in the format
142 data dict. If this is set all format types will be computed,
146 data dict. If this is set all format types will be computed,
143 except for those included in this argument.
147 except for those included in this argument.
144 metadata : dict, optional
148 metadata : dict, optional
145 A dictionary of metadata to associate with the output.
149 A dictionary of metadata to associate with the output.
146 mime-type keys in this dictionary will be associated with the individual
150 mime-type keys in this dictionary will be associated with the individual
147 representation formats, if they exist.
151 representation formats, if they exist.
152 transient : dict, optional
153 A dictionary of transient data to associate with the output.
154 Data in this dict should not be persisted to files (e.g. notebooks).
155 display_id : str, optional
156 Set an id for the display.
157 This id can be used for updating this display area later via update_display.
148 """
158 """
149 raw = kwargs.get('raw', False)
159 raw = kwargs.pop('raw', False)
150 include = kwargs.get('include')
160 include = kwargs.pop('include', None)
151 exclude = kwargs.get('exclude')
161 exclude = kwargs.pop('exclude', None)
152 metadata = kwargs.get('metadata')
162 metadata = kwargs.pop('metadata', None)
163 transient = kwargs.setdefault('transient', {})
164 if 'display_id' in kwargs:
165 transient['display_id'] = kwargs.pop('display_id')
166 if kwargs.get('update') and 'display_id' not in transient:
167 raise TypeError('display_id required for update_display')
153
168
154 from IPython.core.interactiveshell import InteractiveShell
169 from IPython.core.interactiveshell import InteractiveShell
155
170
156 if not raw:
171 if not raw:
157 format = InteractiveShell.instance().display_formatter.format
172 format = InteractiveShell.instance().display_formatter.format
158
173
159 for obj in objs:
174 for obj in objs:
160 if raw:
175 if raw:
161 publish_display_data(data=obj, metadata=metadata)
176 publish_display_data(data=obj, metadata=metadata, **kwargs)
162 else:
177 else:
163 format_dict, md_dict = format(obj, include=include, exclude=exclude)
178 format_dict, md_dict = format(obj, include=include, exclude=exclude)
164 if not format_dict:
179 if not format_dict:
165 # nothing to display (e.g. _ipython_display_ took over)
180 # nothing to display (e.g. _ipython_display_ took over)
166 continue
181 continue
167 if metadata:
182 if metadata:
168 # kwarg-specified metadata gets precedence
183 # kwarg-specified metadata gets precedence
169 _merge(md_dict, metadata)
184 _merge(md_dict, metadata)
170 publish_display_data(data=format_dict, metadata=md_dict)
185 publish_display_data(data=format_dict, metadata=md_dict,
186 **kwargs)
187
188
189 def update_display(*objs, **kwargs):
190 """Update an existing display"""
191 kwargs['update'] = True
192 return display(*objs, **kwargs)
171
193
172
194
173 def display_pretty(*objs, **kwargs):
195 def display_pretty(*objs, **kwargs):
174 """Display the pretty (default) representation of an object.
196 """Display the pretty (default) representation of an object.
175
197
176 Parameters
198 Parameters
177 ----------
199 ----------
178 objs : tuple of objects
200 objs : tuple of objects
179 The Python objects to display, or if raw=True raw text data to
201 The Python objects to display, or if raw=True raw text data to
180 display.
202 display.
181 raw : bool
203 raw : bool
182 Are the data objects raw data or Python objects that need to be
204 Are the data objects raw data or Python objects that need to be
183 formatted before display? [default: False]
205 formatted before display? [default: False]
184 metadata : dict (optional)
206 metadata : dict (optional)
185 Metadata to be associated with the specific mimetype output.
207 Metadata to be associated with the specific mimetype output.
186 """
208 """
187 _display_mimetype('text/plain', objs, **kwargs)
209 _display_mimetype('text/plain', objs, **kwargs)
188
210
189
211
190 def display_html(*objs, **kwargs):
212 def display_html(*objs, **kwargs):
191 """Display the HTML representation of an object.
213 """Display the HTML representation of an object.
192
214
193 Note: If raw=False and the object does not have a HTML
215 Note: If raw=False and the object does not have a HTML
194 representation, no HTML will be shown.
216 representation, no HTML will be shown.
195
217
196 Parameters
218 Parameters
197 ----------
219 ----------
198 objs : tuple of objects
220 objs : tuple of objects
199 The Python objects to display, or if raw=True raw HTML data to
221 The Python objects to display, or if raw=True raw HTML data to
200 display.
222 display.
201 raw : bool
223 raw : bool
202 Are the data objects raw data or Python objects that need to be
224 Are the data objects raw data or Python objects that need to be
203 formatted before display? [default: False]
225 formatted before display? [default: False]
204 metadata : dict (optional)
226 metadata : dict (optional)
205 Metadata to be associated with the specific mimetype output.
227 Metadata to be associated with the specific mimetype output.
206 """
228 """
207 _display_mimetype('text/html', objs, **kwargs)
229 _display_mimetype('text/html', objs, **kwargs)
208
230
209
231
210 def display_markdown(*objs, **kwargs):
232 def display_markdown(*objs, **kwargs):
211 """Displays the Markdown representation of an object.
233 """Displays the Markdown representation of an object.
212
234
213 Parameters
235 Parameters
214 ----------
236 ----------
215 objs : tuple of objects
237 objs : tuple of objects
216 The Python objects to display, or if raw=True raw markdown data to
238 The Python objects to display, or if raw=True raw markdown data to
217 display.
239 display.
218 raw : bool
240 raw : bool
219 Are the data objects raw data or Python objects that need to be
241 Are the data objects raw data or Python objects that need to be
220 formatted before display? [default: False]
242 formatted before display? [default: False]
221 metadata : dict (optional)
243 metadata : dict (optional)
222 Metadata to be associated with the specific mimetype output.
244 Metadata to be associated with the specific mimetype output.
223 """
245 """
224
246
225 _display_mimetype('text/markdown', objs, **kwargs)
247 _display_mimetype('text/markdown', objs, **kwargs)
226
248
227
249
228 def display_svg(*objs, **kwargs):
250 def display_svg(*objs, **kwargs):
229 """Display the SVG representation of an object.
251 """Display the SVG representation of an object.
230
252
231 Parameters
253 Parameters
232 ----------
254 ----------
233 objs : tuple of objects
255 objs : tuple of objects
234 The Python objects to display, or if raw=True raw svg data to
256 The Python objects to display, or if raw=True raw svg data to
235 display.
257 display.
236 raw : bool
258 raw : bool
237 Are the data objects raw data or Python objects that need to be
259 Are the data objects raw data or Python objects that need to be
238 formatted before display? [default: False]
260 formatted before display? [default: False]
239 metadata : dict (optional)
261 metadata : dict (optional)
240 Metadata to be associated with the specific mimetype output.
262 Metadata to be associated with the specific mimetype output.
241 """
263 """
242 _display_mimetype('image/svg+xml', objs, **kwargs)
264 _display_mimetype('image/svg+xml', objs, **kwargs)
243
265
244
266
245 def display_png(*objs, **kwargs):
267 def display_png(*objs, **kwargs):
246 """Display the PNG representation of an object.
268 """Display the PNG representation of an object.
247
269
248 Parameters
270 Parameters
249 ----------
271 ----------
250 objs : tuple of objects
272 objs : tuple of objects
251 The Python objects to display, or if raw=True raw png data to
273 The Python objects to display, or if raw=True raw png data to
252 display.
274 display.
253 raw : bool
275 raw : bool
254 Are the data objects raw data or Python objects that need to be
276 Are the data objects raw data or Python objects that need to be
255 formatted before display? [default: False]
277 formatted before display? [default: False]
256 metadata : dict (optional)
278 metadata : dict (optional)
257 Metadata to be associated with the specific mimetype output.
279 Metadata to be associated with the specific mimetype output.
258 """
280 """
259 _display_mimetype('image/png', objs, **kwargs)
281 _display_mimetype('image/png', objs, **kwargs)
260
282
261
283
262 def display_jpeg(*objs, **kwargs):
284 def display_jpeg(*objs, **kwargs):
263 """Display the JPEG representation of an object.
285 """Display the JPEG representation of an object.
264
286
265 Parameters
287 Parameters
266 ----------
288 ----------
267 objs : tuple of objects
289 objs : tuple of objects
268 The Python objects to display, or if raw=True raw JPEG data to
290 The Python objects to display, or if raw=True raw JPEG data to
269 display.
291 display.
270 raw : bool
292 raw : bool
271 Are the data objects raw data or Python objects that need to be
293 Are the data objects raw data or Python objects that need to be
272 formatted before display? [default: False]
294 formatted before display? [default: False]
273 metadata : dict (optional)
295 metadata : dict (optional)
274 Metadata to be associated with the specific mimetype output.
296 Metadata to be associated with the specific mimetype output.
275 """
297 """
276 _display_mimetype('image/jpeg', objs, **kwargs)
298 _display_mimetype('image/jpeg', objs, **kwargs)
277
299
278
300
279 def display_latex(*objs, **kwargs):
301 def display_latex(*objs, **kwargs):
280 """Display the LaTeX representation of an object.
302 """Display the LaTeX representation of an object.
281
303
282 Parameters
304 Parameters
283 ----------
305 ----------
284 objs : tuple of objects
306 objs : tuple of objects
285 The Python objects to display, or if raw=True raw latex data to
307 The Python objects to display, or if raw=True raw latex data to
286 display.
308 display.
287 raw : bool
309 raw : bool
288 Are the data objects raw data or Python objects that need to be
310 Are the data objects raw data or Python objects that need to be
289 formatted before display? [default: False]
311 formatted before display? [default: False]
290 metadata : dict (optional)
312 metadata : dict (optional)
291 Metadata to be associated with the specific mimetype output.
313 Metadata to be associated with the specific mimetype output.
292 """
314 """
293 _display_mimetype('text/latex', objs, **kwargs)
315 _display_mimetype('text/latex', objs, **kwargs)
294
316
295
317
296 def display_json(*objs, **kwargs):
318 def display_json(*objs, **kwargs):
297 """Display the JSON representation of an object.
319 """Display the JSON representation of an object.
298
320
299 Note that not many frontends support displaying JSON.
321 Note that not many frontends support displaying JSON.
300
322
301 Parameters
323 Parameters
302 ----------
324 ----------
303 objs : tuple of objects
325 objs : tuple of objects
304 The Python objects to display, or if raw=True raw json data to
326 The Python objects to display, or if raw=True raw json data to
305 display.
327 display.
306 raw : bool
328 raw : bool
307 Are the data objects raw data or Python objects that need to be
329 Are the data objects raw data or Python objects that need to be
308 formatted before display? [default: False]
330 formatted before display? [default: False]
309 metadata : dict (optional)
331 metadata : dict (optional)
310 Metadata to be associated with the specific mimetype output.
332 Metadata to be associated with the specific mimetype output.
311 """
333 """
312 _display_mimetype('application/json', objs, **kwargs)
334 _display_mimetype('application/json', objs, **kwargs)
313
335
314
336
315 def display_javascript(*objs, **kwargs):
337 def display_javascript(*objs, **kwargs):
316 """Display the Javascript representation of an object.
338 """Display the Javascript representation of an object.
317
339
318 Parameters
340 Parameters
319 ----------
341 ----------
320 objs : tuple of objects
342 objs : tuple of objects
321 The Python objects to display, or if raw=True raw javascript data to
343 The Python objects to display, or if raw=True raw javascript data to
322 display.
344 display.
323 raw : bool
345 raw : bool
324 Are the data objects raw data or Python objects that need to be
346 Are the data objects raw data or Python objects that need to be
325 formatted before display? [default: False]
347 formatted before display? [default: False]
326 metadata : dict (optional)
348 metadata : dict (optional)
327 Metadata to be associated with the specific mimetype output.
349 Metadata to be associated with the specific mimetype output.
328 """
350 """
329 _display_mimetype('application/javascript', objs, **kwargs)
351 _display_mimetype('application/javascript', objs, **kwargs)
330
352
331
353
332 def display_pdf(*objs, **kwargs):
354 def display_pdf(*objs, **kwargs):
333 """Display the PDF representation of an object.
355 """Display the PDF representation of an object.
334
356
335 Parameters
357 Parameters
336 ----------
358 ----------
337 objs : tuple of objects
359 objs : tuple of objects
338 The Python objects to display, or if raw=True raw javascript data to
360 The Python objects to display, or if raw=True raw javascript data to
339 display.
361 display.
340 raw : bool
362 raw : bool
341 Are the data objects raw data or Python objects that need to be
363 Are the data objects raw data or Python objects that need to be
342 formatted before display? [default: False]
364 formatted before display? [default: False]
343 metadata : dict (optional)
365 metadata : dict (optional)
344 Metadata to be associated with the specific mimetype output.
366 Metadata to be associated with the specific mimetype output.
345 """
367 """
346 _display_mimetype('application/pdf', objs, **kwargs)
368 _display_mimetype('application/pdf', objs, **kwargs)
347
369
348
370
349 #-----------------------------------------------------------------------------
371 #-----------------------------------------------------------------------------
350 # Smart classes
372 # Smart classes
351 #-----------------------------------------------------------------------------
373 #-----------------------------------------------------------------------------
352
374
353
375
354 class DisplayObject(object):
376 class DisplayObject(object):
355 """An object that wraps data to be displayed."""
377 """An object that wraps data to be displayed."""
356
378
357 _read_flags = 'r'
379 _read_flags = 'r'
358 _show_mem_addr = False
380 _show_mem_addr = False
359
381
360 def __init__(self, data=None, url=None, filename=None):
382 def __init__(self, data=None, url=None, filename=None):
361 """Create a display object given raw data.
383 """Create a display object given raw data.
362
384
363 When this object is returned by an expression or passed to the
385 When this object is returned by an expression or passed to the
364 display function, it will result in the data being displayed
386 display function, it will result in the data being displayed
365 in the frontend. The MIME type of the data should match the
387 in the frontend. The MIME type of the data should match the
366 subclasses used, so the Png subclass should be used for 'image/png'
388 subclasses used, so the Png subclass should be used for 'image/png'
367 data. If the data is a URL, the data will first be downloaded
389 data. If the data is a URL, the data will first be downloaded
368 and then displayed. If
390 and then displayed. If
369
391
370 Parameters
392 Parameters
371 ----------
393 ----------
372 data : unicode, str or bytes
394 data : unicode, str or bytes
373 The raw data or a URL or file to load the data from
395 The raw data or a URL or file to load the data from
374 url : unicode
396 url : unicode
375 A URL to download the data from.
397 A URL to download the data from.
376 filename : unicode
398 filename : unicode
377 Path to a local file to load the data from.
399 Path to a local file to load the data from.
378 """
400 """
379 if data is not None and isinstance(data, string_types):
401 if data is not None and isinstance(data, string_types):
380 if data.startswith('http') and url is None:
402 if data.startswith('http') and url is None:
381 url = data
403 url = data
382 filename = None
404 filename = None
383 data = None
405 data = None
384 elif _safe_exists(data) and filename is None:
406 elif _safe_exists(data) and filename is None:
385 url = None
407 url = None
386 filename = data
408 filename = data
387 data = None
409 data = None
388
410
389 self.data = data
411 self.data = data
390 self.url = url
412 self.url = url
391 self.filename = None if filename is None else unicode_type(filename)
413 self.filename = None if filename is None else unicode_type(filename)
392
414
393 self.reload()
415 self.reload()
394 self._check_data()
416 self._check_data()
395
417
396 def __repr__(self):
418 def __repr__(self):
397 if not self._show_mem_addr:
419 if not self._show_mem_addr:
398 cls = self.__class__
420 cls = self.__class__
399 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
421 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
400 else:
422 else:
401 r = super(DisplayObject, self).__repr__()
423 r = super(DisplayObject, self).__repr__()
402 return r
424 return r
403
425
404 def _check_data(self):
426 def _check_data(self):
405 """Override in subclasses if there's something to check."""
427 """Override in subclasses if there's something to check."""
406 pass
428 pass
407
429
408 def reload(self):
430 def reload(self):
409 """Reload the raw data from file or URL."""
431 """Reload the raw data from file or URL."""
410 if self.filename is not None:
432 if self.filename is not None:
411 with open(self.filename, self._read_flags) as f:
433 with open(self.filename, self._read_flags) as f:
412 self.data = f.read()
434 self.data = f.read()
413 elif self.url is not None:
435 elif self.url is not None:
414 try:
436 try:
415 try:
437 try:
416 from urllib.request import urlopen # Py3
438 from urllib.request import urlopen # Py3
417 except ImportError:
439 except ImportError:
418 from urllib2 import urlopen
440 from urllib2 import urlopen
419 response = urlopen(self.url)
441 response = urlopen(self.url)
420 self.data = response.read()
442 self.data = response.read()
421 # extract encoding from header, if there is one:
443 # extract encoding from header, if there is one:
422 encoding = None
444 encoding = None
423 for sub in response.headers['content-type'].split(';'):
445 for sub in response.headers['content-type'].split(';'):
424 sub = sub.strip()
446 sub = sub.strip()
425 if sub.startswith('charset'):
447 if sub.startswith('charset'):
426 encoding = sub.split('=')[-1].strip()
448 encoding = sub.split('=')[-1].strip()
427 break
449 break
428 # decode data, if an encoding was specified
450 # decode data, if an encoding was specified
429 if encoding:
451 if encoding:
430 self.data = self.data.decode(encoding, 'replace')
452 self.data = self.data.decode(encoding, 'replace')
431 except:
453 except:
432 self.data = None
454 self.data = None
433
455
434 class TextDisplayObject(DisplayObject):
456 class TextDisplayObject(DisplayObject):
435 """Validate that display data is text"""
457 """Validate that display data is text"""
436 def _check_data(self):
458 def _check_data(self):
437 if self.data is not None and not isinstance(self.data, string_types):
459 if self.data is not None and not isinstance(self.data, string_types):
438 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
460 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
439
461
440 class Pretty(TextDisplayObject):
462 class Pretty(TextDisplayObject):
441
463
442 def _repr_pretty_(self):
464 def _repr_pretty_(self):
443 return self.data
465 return self.data
444
466
445
467
446 class HTML(TextDisplayObject):
468 class HTML(TextDisplayObject):
447
469
448 def _repr_html_(self):
470 def _repr_html_(self):
449 return self.data
471 return self.data
450
472
451 def __html__(self):
473 def __html__(self):
452 """
474 """
453 This method exists to inform other HTML-using modules (e.g. Markupsafe,
475 This method exists to inform other HTML-using modules (e.g. Markupsafe,
454 htmltag, etc) that this object is HTML and does not need things like
476 htmltag, etc) that this object is HTML and does not need things like
455 special characters (<>&) escaped.
477 special characters (<>&) escaped.
456 """
478 """
457 return self._repr_html_()
479 return self._repr_html_()
458
480
459
481
460 class Markdown(TextDisplayObject):
482 class Markdown(TextDisplayObject):
461
483
462 def _repr_markdown_(self):
484 def _repr_markdown_(self):
463 return self.data
485 return self.data
464
486
465
487
466 class Math(TextDisplayObject):
488 class Math(TextDisplayObject):
467
489
468 def _repr_latex_(self):
490 def _repr_latex_(self):
469 s = self.data.strip('$')
491 s = self.data.strip('$')
470 return "$$%s$$" % s
492 return "$$%s$$" % s
471
493
472
494
473 class Latex(TextDisplayObject):
495 class Latex(TextDisplayObject):
474
496
475 def _repr_latex_(self):
497 def _repr_latex_(self):
476 return self.data
498 return self.data
477
499
478
500
479 class SVG(DisplayObject):
501 class SVG(DisplayObject):
480
502
481 # wrap data in a property, which extracts the <svg> tag, discarding
503 # wrap data in a property, which extracts the <svg> tag, discarding
482 # document headers
504 # document headers
483 _data = None
505 _data = None
484
506
485 @property
507 @property
486 def data(self):
508 def data(self):
487 return self._data
509 return self._data
488
510
489 @data.setter
511 @data.setter
490 def data(self, svg):
512 def data(self, svg):
491 if svg is None:
513 if svg is None:
492 self._data = None
514 self._data = None
493 return
515 return
494 # parse into dom object
516 # parse into dom object
495 from xml.dom import minidom
517 from xml.dom import minidom
496 svg = cast_bytes_py2(svg)
518 svg = cast_bytes_py2(svg)
497 x = minidom.parseString(svg)
519 x = minidom.parseString(svg)
498 # get svg tag (should be 1)
520 # get svg tag (should be 1)
499 found_svg = x.getElementsByTagName('svg')
521 found_svg = x.getElementsByTagName('svg')
500 if found_svg:
522 if found_svg:
501 svg = found_svg[0].toxml()
523 svg = found_svg[0].toxml()
502 else:
524 else:
503 # fallback on the input, trust the user
525 # fallback on the input, trust the user
504 # but this is probably an error.
526 # but this is probably an error.
505 pass
527 pass
506 svg = cast_unicode(svg)
528 svg = cast_unicode(svg)
507 self._data = svg
529 self._data = svg
508
530
509 def _repr_svg_(self):
531 def _repr_svg_(self):
510 return self.data
532 return self.data
511
533
512
534
513 class JSON(DisplayObject):
535 class JSON(DisplayObject):
514 """JSON expects a JSON-able dict or list
536 """JSON expects a JSON-able dict or list
515
537
516 not an already-serialized JSON string.
538 not an already-serialized JSON string.
517
539
518 Scalar types (None, number, string) are not allowed, only dict or list containers.
540 Scalar types (None, number, string) are not allowed, only dict or list containers.
519 """
541 """
520 # wrap data in a property, which warns about passing already-serialized JSON
542 # wrap data in a property, which warns about passing already-serialized JSON
521 _data = None
543 _data = None
522 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None):
544 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None):
523 """Create a JSON display object given raw data.
545 """Create a JSON display object given raw data.
524
546
525 Parameters
547 Parameters
526 ----------
548 ----------
527 data : dict or list
549 data : dict or list
528 JSON data to display. Not an already-serialized JSON string.
550 JSON data to display. Not an already-serialized JSON string.
529 Scalar types (None, number, string) are not allowed, only dict
551 Scalar types (None, number, string) are not allowed, only dict
530 or list containers.
552 or list containers.
531 url : unicode
553 url : unicode
532 A URL to download the data from.
554 A URL to download the data from.
533 filename : unicode
555 filename : unicode
534 Path to a local file to load the data from.
556 Path to a local file to load the data from.
535 expanded : boolean
557 expanded : boolean
536 Metadata to control whether a JSON display component is expanded.
558 Metadata to control whether a JSON display component is expanded.
537 metadata: dict
559 metadata: dict
538 Specify extra metadata to attach to the json display object.
560 Specify extra metadata to attach to the json display object.
539 """
561 """
540 self.expanded = expanded
562 self.expanded = expanded
541 self.metadata = metadata
563 self.metadata = metadata
542 super(JSON, self).__init__(data=data, url=url, filename=filename)
564 super(JSON, self).__init__(data=data, url=url, filename=filename)
543
565
544 def _check_data(self):
566 def _check_data(self):
545 if self.data is not None and not isinstance(self.data, (dict, list)):
567 if self.data is not None and not isinstance(self.data, (dict, list)):
546 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
568 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
547
569
548 @property
570 @property
549 def data(self):
571 def data(self):
550 return self._data
572 return self._data
551
573
552 @data.setter
574 @data.setter
553 def data(self, data):
575 def data(self, data):
554 if isinstance(data, string_types):
576 if isinstance(data, string_types):
555 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
577 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
556 data = json.loads(data)
578 data = json.loads(data)
557 self._data = data
579 self._data = data
558
580
559 def _data_and_metadata(self):
581 def _data_and_metadata(self):
560 md = {'expanded': self.expanded}
582 md = {'expanded': self.expanded}
561 if self.metadata:
583 if self.metadata:
562 md.update(self.metadata)
584 md.update(self.metadata)
563 return self.data, md
585 return self.data, md
564
586
565 def _repr_json_(self):
587 def _repr_json_(self):
566 return self._data_and_metadata()
588 return self._data_and_metadata()
567
589
568 css_t = """$("head").append($("<link/>").attr({
590 css_t = """$("head").append($("<link/>").attr({
569 rel: "stylesheet",
591 rel: "stylesheet",
570 type: "text/css",
592 type: "text/css",
571 href: "%s"
593 href: "%s"
572 }));
594 }));
573 """
595 """
574
596
575 lib_t1 = """$.getScript("%s", function () {
597 lib_t1 = """$.getScript("%s", function () {
576 """
598 """
577 lib_t2 = """});
599 lib_t2 = """});
578 """
600 """
579
601
580 class Javascript(TextDisplayObject):
602 class Javascript(TextDisplayObject):
581
603
582 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
604 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
583 """Create a Javascript display object given raw data.
605 """Create a Javascript display object given raw data.
584
606
585 When this object is returned by an expression or passed to the
607 When this object is returned by an expression or passed to the
586 display function, it will result in the data being displayed
608 display function, it will result in the data being displayed
587 in the frontend. If the data is a URL, the data will first be
609 in the frontend. If the data is a URL, the data will first be
588 downloaded and then displayed.
610 downloaded and then displayed.
589
611
590 In the Notebook, the containing element will be available as `element`,
612 In the Notebook, the containing element will be available as `element`,
591 and jQuery will be available. Content appended to `element` will be
613 and jQuery will be available. Content appended to `element` will be
592 visible in the output area.
614 visible in the output area.
593
615
594 Parameters
616 Parameters
595 ----------
617 ----------
596 data : unicode, str or bytes
618 data : unicode, str or bytes
597 The Javascript source code or a URL to download it from.
619 The Javascript source code or a URL to download it from.
598 url : unicode
620 url : unicode
599 A URL to download the data from.
621 A URL to download the data from.
600 filename : unicode
622 filename : unicode
601 Path to a local file to load the data from.
623 Path to a local file to load the data from.
602 lib : list or str
624 lib : list or str
603 A sequence of Javascript library URLs to load asynchronously before
625 A sequence of Javascript library URLs to load asynchronously before
604 running the source code. The full URLs of the libraries should
626 running the source code. The full URLs of the libraries should
605 be given. A single Javascript library URL can also be given as a
627 be given. A single Javascript library URL can also be given as a
606 string.
628 string.
607 css: : list or str
629 css: : list or str
608 A sequence of css files to load before running the source code.
630 A sequence of css files to load before running the source code.
609 The full URLs of the css files should be given. A single css URL
631 The full URLs of the css files should be given. A single css URL
610 can also be given as a string.
632 can also be given as a string.
611 """
633 """
612 if isinstance(lib, string_types):
634 if isinstance(lib, string_types):
613 lib = [lib]
635 lib = [lib]
614 elif lib is None:
636 elif lib is None:
615 lib = []
637 lib = []
616 if isinstance(css, string_types):
638 if isinstance(css, string_types):
617 css = [css]
639 css = [css]
618 elif css is None:
640 elif css is None:
619 css = []
641 css = []
620 if not isinstance(lib, (list,tuple)):
642 if not isinstance(lib, (list,tuple)):
621 raise TypeError('expected sequence, got: %r' % lib)
643 raise TypeError('expected sequence, got: %r' % lib)
622 if not isinstance(css, (list,tuple)):
644 if not isinstance(css, (list,tuple)):
623 raise TypeError('expected sequence, got: %r' % css)
645 raise TypeError('expected sequence, got: %r' % css)
624 self.lib = lib
646 self.lib = lib
625 self.css = css
647 self.css = css
626 super(Javascript, self).__init__(data=data, url=url, filename=filename)
648 super(Javascript, self).__init__(data=data, url=url, filename=filename)
627
649
628 def _repr_javascript_(self):
650 def _repr_javascript_(self):
629 r = ''
651 r = ''
630 for c in self.css:
652 for c in self.css:
631 r += css_t % c
653 r += css_t % c
632 for l in self.lib:
654 for l in self.lib:
633 r += lib_t1 % l
655 r += lib_t1 % l
634 r += self.data
656 r += self.data
635 r += lib_t2*len(self.lib)
657 r += lib_t2*len(self.lib)
636 return r
658 return r
637
659
638 # constants for identifying png/jpeg data
660 # constants for identifying png/jpeg data
639 _PNG = b'\x89PNG\r\n\x1a\n'
661 _PNG = b'\x89PNG\r\n\x1a\n'
640 _JPEG = b'\xff\xd8'
662 _JPEG = b'\xff\xd8'
641
663
642 def _pngxy(data):
664 def _pngxy(data):
643 """read the (width, height) from a PNG header"""
665 """read the (width, height) from a PNG header"""
644 ihdr = data.index(b'IHDR')
666 ihdr = data.index(b'IHDR')
645 # next 8 bytes are width/height
667 # next 8 bytes are width/height
646 w4h4 = data[ihdr+4:ihdr+12]
668 w4h4 = data[ihdr+4:ihdr+12]
647 return struct.unpack('>ii', w4h4)
669 return struct.unpack('>ii', w4h4)
648
670
649 def _jpegxy(data):
671 def _jpegxy(data):
650 """read the (width, height) from a JPEG header"""
672 """read the (width, height) from a JPEG header"""
651 # adapted from http://www.64lines.com/jpeg-width-height
673 # adapted from http://www.64lines.com/jpeg-width-height
652
674
653 idx = 4
675 idx = 4
654 while True:
676 while True:
655 block_size = struct.unpack('>H', data[idx:idx+2])[0]
677 block_size = struct.unpack('>H', data[idx:idx+2])[0]
656 idx = idx + block_size
678 idx = idx + block_size
657 if data[idx:idx+2] == b'\xFF\xC0':
679 if data[idx:idx+2] == b'\xFF\xC0':
658 # found Start of Frame
680 # found Start of Frame
659 iSOF = idx
681 iSOF = idx
660 break
682 break
661 else:
683 else:
662 # read another block
684 # read another block
663 idx += 2
685 idx += 2
664
686
665 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
687 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
666 return w, h
688 return w, h
667
689
668 class Image(DisplayObject):
690 class Image(DisplayObject):
669
691
670 _read_flags = 'rb'
692 _read_flags = 'rb'
671 _FMT_JPEG = u'jpeg'
693 _FMT_JPEG = u'jpeg'
672 _FMT_PNG = u'png'
694 _FMT_PNG = u'png'
673 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
695 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
674
696
675 def __init__(self, data=None, url=None, filename=None, format=None,
697 def __init__(self, data=None, url=None, filename=None, format=None,
676 embed=None, width=None, height=None, retina=False,
698 embed=None, width=None, height=None, retina=False,
677 unconfined=False, metadata=None):
699 unconfined=False, metadata=None):
678 """Create a PNG/JPEG image object given raw data.
700 """Create a PNG/JPEG image object given raw data.
679
701
680 When this object is returned by an input cell or passed to the
702 When this object is returned by an input cell or passed to the
681 display function, it will result in the image being displayed
703 display function, it will result in the image being displayed
682 in the frontend.
704 in the frontend.
683
705
684 Parameters
706 Parameters
685 ----------
707 ----------
686 data : unicode, str or bytes
708 data : unicode, str or bytes
687 The raw image data or a URL or filename to load the data from.
709 The raw image data or a URL or filename to load the data from.
688 This always results in embedded image data.
710 This always results in embedded image data.
689 url : unicode
711 url : unicode
690 A URL to download the data from. If you specify `url=`,
712 A URL to download the data from. If you specify `url=`,
691 the image data will not be embedded unless you also specify `embed=True`.
713 the image data will not be embedded unless you also specify `embed=True`.
692 filename : unicode
714 filename : unicode
693 Path to a local file to load the data from.
715 Path to a local file to load the data from.
694 Images from a file are always embedded.
716 Images from a file are always embedded.
695 format : unicode
717 format : unicode
696 The format of the image data (png/jpeg/jpg). If a filename or URL is given
718 The format of the image data (png/jpeg/jpg). If a filename or URL is given
697 for format will be inferred from the filename extension.
719 for format will be inferred from the filename extension.
698 embed : bool
720 embed : bool
699 Should the image data be embedded using a data URI (True) or be
721 Should the image data be embedded using a data URI (True) or be
700 loaded using an <img> tag. Set this to True if you want the image
722 loaded using an <img> tag. Set this to True if you want the image
701 to be viewable later with no internet connection in the notebook.
723 to be viewable later with no internet connection in the notebook.
702
724
703 Default is `True`, unless the keyword argument `url` is set, then
725 Default is `True`, unless the keyword argument `url` is set, then
704 default value is `False`.
726 default value is `False`.
705
727
706 Note that QtConsole is not able to display images if `embed` is set to `False`
728 Note that QtConsole is not able to display images if `embed` is set to `False`
707 width : int
729 width : int
708 Width in pixels to which to constrain the image in html
730 Width in pixels to which to constrain the image in html
709 height : int
731 height : int
710 Height in pixels to which to constrain the image in html
732 Height in pixels to which to constrain the image in html
711 retina : bool
733 retina : bool
712 Automatically set the width and height to half of the measured
734 Automatically set the width and height to half of the measured
713 width and height.
735 width and height.
714 This only works for embedded images because it reads the width/height
736 This only works for embedded images because it reads the width/height
715 from image data.
737 from image data.
716 For non-embedded images, you can just set the desired display width
738 For non-embedded images, you can just set the desired display width
717 and height directly.
739 and height directly.
718 unconfined: bool
740 unconfined: bool
719 Set unconfined=True to disable max-width confinement of the image.
741 Set unconfined=True to disable max-width confinement of the image.
720 metadata: dict
742 metadata: dict
721 Specify extra metadata to attach to the image.
743 Specify extra metadata to attach to the image.
722
744
723 Examples
745 Examples
724 --------
746 --------
725 # embedded image data, works in qtconsole and notebook
747 # embedded image data, works in qtconsole and notebook
726 # when passed positionally, the first arg can be any of raw image data,
748 # when passed positionally, the first arg can be any of raw image data,
727 # a URL, or a filename from which to load image data.
749 # a URL, or a filename from which to load image data.
728 # The result is always embedding image data for inline images.
750 # The result is always embedding image data for inline images.
729 Image('http://www.google.fr/images/srpr/logo3w.png')
751 Image('http://www.google.fr/images/srpr/logo3w.png')
730 Image('/path/to/image.jpg')
752 Image('/path/to/image.jpg')
731 Image(b'RAW_PNG_DATA...')
753 Image(b'RAW_PNG_DATA...')
732
754
733 # Specifying Image(url=...) does not embed the image data,
755 # Specifying Image(url=...) does not embed the image data,
734 # it only generates `<img>` tag with a link to the source.
756 # it only generates `<img>` tag with a link to the source.
735 # This will not work in the qtconsole or offline.
757 # This will not work in the qtconsole or offline.
736 Image(url='http://www.google.fr/images/srpr/logo3w.png')
758 Image(url='http://www.google.fr/images/srpr/logo3w.png')
737
759
738 """
760 """
739 if filename is not None:
761 if filename is not None:
740 ext = self._find_ext(filename)
762 ext = self._find_ext(filename)
741 elif url is not None:
763 elif url is not None:
742 ext = self._find_ext(url)
764 ext = self._find_ext(url)
743 elif data is None:
765 elif data is None:
744 raise ValueError("No image data found. Expecting filename, url, or data.")
766 raise ValueError("No image data found. Expecting filename, url, or data.")
745 elif isinstance(data, string_types) and (
767 elif isinstance(data, string_types) and (
746 data.startswith('http') or _safe_exists(data)
768 data.startswith('http') or _safe_exists(data)
747 ):
769 ):
748 ext = self._find_ext(data)
770 ext = self._find_ext(data)
749 else:
771 else:
750 ext = None
772 ext = None
751
773
752 if format is None:
774 if format is None:
753 if ext is not None:
775 if ext is not None:
754 if ext == u'jpg' or ext == u'jpeg':
776 if ext == u'jpg' or ext == u'jpeg':
755 format = self._FMT_JPEG
777 format = self._FMT_JPEG
756 if ext == u'png':
778 if ext == u'png':
757 format = self._FMT_PNG
779 format = self._FMT_PNG
758 else:
780 else:
759 format = ext.lower()
781 format = ext.lower()
760 elif isinstance(data, bytes):
782 elif isinstance(data, bytes):
761 # infer image type from image data header,
783 # infer image type from image data header,
762 # only if format has not been specified.
784 # only if format has not been specified.
763 if data[:2] == _JPEG:
785 if data[:2] == _JPEG:
764 format = self._FMT_JPEG
786 format = self._FMT_JPEG
765
787
766 # failed to detect format, default png
788 # failed to detect format, default png
767 if format is None:
789 if format is None:
768 format = 'png'
790 format = 'png'
769
791
770 if format.lower() == 'jpg':
792 if format.lower() == 'jpg':
771 # jpg->jpeg
793 # jpg->jpeg
772 format = self._FMT_JPEG
794 format = self._FMT_JPEG
773
795
774 self.format = unicode_type(format).lower()
796 self.format = unicode_type(format).lower()
775 self.embed = embed if embed is not None else (url is None)
797 self.embed = embed if embed is not None else (url is None)
776
798
777 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
799 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
778 raise ValueError("Cannot embed the '%s' image format" % (self.format))
800 raise ValueError("Cannot embed the '%s' image format" % (self.format))
779 self.width = width
801 self.width = width
780 self.height = height
802 self.height = height
781 self.retina = retina
803 self.retina = retina
782 self.unconfined = unconfined
804 self.unconfined = unconfined
783 self.metadata = metadata
805 self.metadata = metadata
784 super(Image, self).__init__(data=data, url=url, filename=filename)
806 super(Image, self).__init__(data=data, url=url, filename=filename)
785
807
786 if retina:
808 if retina:
787 self._retina_shape()
809 self._retina_shape()
788
810
789 def _retina_shape(self):
811 def _retina_shape(self):
790 """load pixel-doubled width and height from image data"""
812 """load pixel-doubled width and height from image data"""
791 if not self.embed:
813 if not self.embed:
792 return
814 return
793 if self.format == 'png':
815 if self.format == 'png':
794 w, h = _pngxy(self.data)
816 w, h = _pngxy(self.data)
795 elif self.format == 'jpeg':
817 elif self.format == 'jpeg':
796 w, h = _jpegxy(self.data)
818 w, h = _jpegxy(self.data)
797 else:
819 else:
798 # retina only supports png
820 # retina only supports png
799 return
821 return
800 self.width = w // 2
822 self.width = w // 2
801 self.height = h // 2
823 self.height = h // 2
802
824
803 def reload(self):
825 def reload(self):
804 """Reload the raw data from file or URL."""
826 """Reload the raw data from file or URL."""
805 if self.embed:
827 if self.embed:
806 super(Image,self).reload()
828 super(Image,self).reload()
807 if self.retina:
829 if self.retina:
808 self._retina_shape()
830 self._retina_shape()
809
831
810 def _repr_html_(self):
832 def _repr_html_(self):
811 if not self.embed:
833 if not self.embed:
812 width = height = klass = ''
834 width = height = klass = ''
813 if self.width:
835 if self.width:
814 width = ' width="%d"' % self.width
836 width = ' width="%d"' % self.width
815 if self.height:
837 if self.height:
816 height = ' height="%d"' % self.height
838 height = ' height="%d"' % self.height
817 if self.unconfined:
839 if self.unconfined:
818 klass = ' class="unconfined"'
840 klass = ' class="unconfined"'
819 return u'<img src="{url}"{width}{height}{klass}/>'.format(
841 return u'<img src="{url}"{width}{height}{klass}/>'.format(
820 url=self.url,
842 url=self.url,
821 width=width,
843 width=width,
822 height=height,
844 height=height,
823 klass=klass,
845 klass=klass,
824 )
846 )
825
847
826 def _data_and_metadata(self):
848 def _data_and_metadata(self):
827 """shortcut for returning metadata with shape information, if defined"""
849 """shortcut for returning metadata with shape information, if defined"""
828 md = {}
850 md = {}
829 if self.width:
851 if self.width:
830 md['width'] = self.width
852 md['width'] = self.width
831 if self.height:
853 if self.height:
832 md['height'] = self.height
854 md['height'] = self.height
833 if self.unconfined:
855 if self.unconfined:
834 md['unconfined'] = self.unconfined
856 md['unconfined'] = self.unconfined
835 if self.metadata:
857 if self.metadata:
836 md.update(self.metadata)
858 md.update(self.metadata)
837 if md:
859 if md:
838 return self.data, md
860 return self.data, md
839 else:
861 else:
840 return self.data
862 return self.data
841
863
842 def _repr_png_(self):
864 def _repr_png_(self):
843 if self.embed and self.format == u'png':
865 if self.embed and self.format == u'png':
844 return self._data_and_metadata()
866 return self._data_and_metadata()
845
867
846 def _repr_jpeg_(self):
868 def _repr_jpeg_(self):
847 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
869 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
848 return self._data_and_metadata()
870 return self._data_and_metadata()
849
871
850 def _find_ext(self, s):
872 def _find_ext(self, s):
851 return unicode_type(s.split('.')[-1].lower())
873 return unicode_type(s.split('.')[-1].lower())
852
874
853 class Video(DisplayObject):
875 class Video(DisplayObject):
854
876
855 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
877 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
856 """Create a video object given raw data or an URL.
878 """Create a video object given raw data or an URL.
857
879
858 When this object is returned by an input cell or passed to the
880 When this object is returned by an input cell or passed to the
859 display function, it will result in the video being displayed
881 display function, it will result in the video being displayed
860 in the frontend.
882 in the frontend.
861
883
862 Parameters
884 Parameters
863 ----------
885 ----------
864 data : unicode, str or bytes
886 data : unicode, str or bytes
865 The raw video data or a URL or filename to load the data from.
887 The raw video data or a URL or filename to load the data from.
866 Raw data will require passing `embed=True`.
888 Raw data will require passing `embed=True`.
867 url : unicode
889 url : unicode
868 A URL for the video. If you specify `url=`,
890 A URL for the video. If you specify `url=`,
869 the image data will not be embedded.
891 the image data will not be embedded.
870 filename : unicode
892 filename : unicode
871 Path to a local file containing the video.
893 Path to a local file containing the video.
872 Will be interpreted as a local URL unless `embed=True`.
894 Will be interpreted as a local URL unless `embed=True`.
873 embed : bool
895 embed : bool
874 Should the video be embedded using a data URI (True) or be
896 Should the video be embedded using a data URI (True) or be
875 loaded using a <video> tag (False).
897 loaded using a <video> tag (False).
876
898
877 Since videos are large, embedding them should be avoided, if possible.
899 Since videos are large, embedding them should be avoided, if possible.
878 You must confirm embedding as your intention by passing `embed=True`.
900 You must confirm embedding as your intention by passing `embed=True`.
879
901
880 Local files can be displayed with URLs without embedding the content, via::
902 Local files can be displayed with URLs without embedding the content, via::
881
903
882 Video('./video.mp4')
904 Video('./video.mp4')
883
905
884 mimetype: unicode
906 mimetype: unicode
885 Specify the mimetype for embedded videos.
907 Specify the mimetype for embedded videos.
886 Default will be guessed from file extension, if available.
908 Default will be guessed from file extension, if available.
887
909
888 Examples
910 Examples
889 --------
911 --------
890
912
891 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
913 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
892 Video('path/to/video.mp4')
914 Video('path/to/video.mp4')
893 Video('path/to/video.mp4', embed=True)
915 Video('path/to/video.mp4', embed=True)
894 Video(b'raw-videodata', embed=True)
916 Video(b'raw-videodata', embed=True)
895 """
917 """
896 if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')):
918 if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')):
897 url = data
919 url = data
898 data = None
920 data = None
899 elif os.path.exists(data):
921 elif os.path.exists(data):
900 filename = data
922 filename = data
901 data = None
923 data = None
902
924
903 if data and not embed:
925 if data and not embed:
904 msg = ''.join([
926 msg = ''.join([
905 "To embed videos, you must pass embed=True ",
927 "To embed videos, you must pass embed=True ",
906 "(this may make your notebook files huge)\n",
928 "(this may make your notebook files huge)\n",
907 "Consider passing Video(url='...')",
929 "Consider passing Video(url='...')",
908 ])
930 ])
909 raise ValueError(msg)
931 raise ValueError(msg)
910
932
911 self.mimetype = mimetype
933 self.mimetype = mimetype
912 self.embed = embed
934 self.embed = embed
913 super(Video, self).__init__(data=data, url=url, filename=filename)
935 super(Video, self).__init__(data=data, url=url, filename=filename)
914
936
915 def _repr_html_(self):
937 def _repr_html_(self):
916 # External URLs and potentially local files are not embedded into the
938 # External URLs and potentially local files are not embedded into the
917 # notebook output.
939 # notebook output.
918 if not self.embed:
940 if not self.embed:
919 url = self.url if self.url is not None else self.filename
941 url = self.url if self.url is not None else self.filename
920 output = """<video src="{0}" controls>
942 output = """<video src="{0}" controls>
921 Your browser does not support the <code>video</code> element.
943 Your browser does not support the <code>video</code> element.
922 </video>""".format(url)
944 </video>""".format(url)
923 return output
945 return output
924
946
925 # Embedded videos are base64-encoded.
947 # Embedded videos are base64-encoded.
926 mimetype = self.mimetype
948 mimetype = self.mimetype
927 if self.filename is not None:
949 if self.filename is not None:
928 if not mimetype:
950 if not mimetype:
929 mimetype, _ = mimetypes.guess_type(self.filename)
951 mimetype, _ = mimetypes.guess_type(self.filename)
930
952
931 with open(self.filename, 'rb') as f:
953 with open(self.filename, 'rb') as f:
932 video = f.read()
954 video = f.read()
933 else:
955 else:
934 video = self.data
956 video = self.data
935 if isinstance(video, unicode_type):
957 if isinstance(video, unicode_type):
936 # unicode input is already b64-encoded
958 # unicode input is already b64-encoded
937 b64_video = video
959 b64_video = video
938 else:
960 else:
939 b64_video = base64_encode(video).decode('ascii').rstrip()
961 b64_video = base64_encode(video).decode('ascii').rstrip()
940
962
941 output = """<video controls>
963 output = """<video controls>
942 <source src="data:{0};base64,{1}" type="{0}">
964 <source src="data:{0};base64,{1}" type="{0}">
943 Your browser does not support the video tag.
965 Your browser does not support the video tag.
944 </video>""".format(mimetype, b64_video)
966 </video>""".format(mimetype, b64_video)
945 return output
967 return output
946
968
947 def reload(self):
969 def reload(self):
948 # TODO
970 # TODO
949 pass
971 pass
950
972
951 def _repr_png_(self):
973 def _repr_png_(self):
952 # TODO
974 # TODO
953 pass
975 pass
954 def _repr_jpeg_(self):
976 def _repr_jpeg_(self):
955 # TODO
977 # TODO
956 pass
978 pass
957
979
958 def clear_output(wait=False):
980 def clear_output(wait=False):
959 """Clear the output of the current cell receiving output.
981 """Clear the output of the current cell receiving output.
960
982
961 Parameters
983 Parameters
962 ----------
984 ----------
963 wait : bool [default: false]
985 wait : bool [default: false]
964 Wait to clear the output until new output is available to replace it."""
986 Wait to clear the output until new output is available to replace it."""
965 from IPython.core.interactiveshell import InteractiveShell
987 from IPython.core.interactiveshell import InteractiveShell
966 if InteractiveShell.initialized():
988 if InteractiveShell.initialized():
967 InteractiveShell.instance().display_pub.clear_output(wait)
989 InteractiveShell.instance().display_pub.clear_output(wait)
968 else:
990 else:
969 print('\033[2K\r', end='')
991 print('\033[2K\r', end='')
970 sys.stdout.flush()
992 sys.stdout.flush()
971 print('\033[2K\r', end='')
993 print('\033[2K\r', end='')
972 sys.stderr.flush()
994 sys.stderr.flush()
973
995
974
996
975 @skip_doctest
997 @skip_doctest
976 def set_matplotlib_formats(*formats, **kwargs):
998 def set_matplotlib_formats(*formats, **kwargs):
977 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
999 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
978
1000
979 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1001 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
980
1002
981 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1003 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
982
1004
983 To set this in your config files use the following::
1005 To set this in your config files use the following::
984
1006
985 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1007 c.InlineBackend.figure_formats = {'png', 'jpeg'}
986 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1008 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
987
1009
988 Parameters
1010 Parameters
989 ----------
1011 ----------
990 *formats : strs
1012 *formats : strs
991 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1013 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
992 **kwargs :
1014 **kwargs :
993 Keyword args will be relayed to ``figure.canvas.print_figure``.
1015 Keyword args will be relayed to ``figure.canvas.print_figure``.
994 """
1016 """
995 from IPython.core.interactiveshell import InteractiveShell
1017 from IPython.core.interactiveshell import InteractiveShell
996 from IPython.core.pylabtools import select_figure_formats
1018 from IPython.core.pylabtools import select_figure_formats
997 # build kwargs, starting with InlineBackend config
1019 # build kwargs, starting with InlineBackend config
998 kw = {}
1020 kw = {}
999 from ipykernel.pylab.config import InlineBackend
1021 from ipykernel.pylab.config import InlineBackend
1000 cfg = InlineBackend.instance()
1022 cfg = InlineBackend.instance()
1001 kw.update(cfg.print_figure_kwargs)
1023 kw.update(cfg.print_figure_kwargs)
1002 kw.update(**kwargs)
1024 kw.update(**kwargs)
1003 shell = InteractiveShell.instance()
1025 shell = InteractiveShell.instance()
1004 select_figure_formats(shell, formats, **kw)
1026 select_figure_formats(shell, formats, **kw)
1005
1027
1006 @skip_doctest
1028 @skip_doctest
1007 def set_matplotlib_close(close=True):
1029 def set_matplotlib_close(close=True):
1008 """Set whether the inline backend closes all figures automatically or not.
1030 """Set whether the inline backend closes all figures automatically or not.
1009
1031
1010 By default, the inline backend used in the IPython Notebook will close all
1032 By default, the inline backend used in the IPython Notebook will close all
1011 matplotlib figures automatically after each cell is run. This means that
1033 matplotlib figures automatically after each cell is run. This means that
1012 plots in different cells won't interfere. Sometimes, you may want to make
1034 plots in different cells won't interfere. Sometimes, you may want to make
1013 a plot in one cell and then refine it in later cells. This can be accomplished
1035 a plot in one cell and then refine it in later cells. This can be accomplished
1014 by::
1036 by::
1015
1037
1016 In [1]: set_matplotlib_close(False)
1038 In [1]: set_matplotlib_close(False)
1017
1039
1018 To set this in your config files use the following::
1040 To set this in your config files use the following::
1019
1041
1020 c.InlineBackend.close_figures = False
1042 c.InlineBackend.close_figures = False
1021
1043
1022 Parameters
1044 Parameters
1023 ----------
1045 ----------
1024 close : bool
1046 close : bool
1025 Should all matplotlib figures be automatically closed after each cell is
1047 Should all matplotlib figures be automatically closed after each cell is
1026 run?
1048 run?
1027 """
1049 """
1028 from ipykernel.pylab.config import InlineBackend
1050 from ipykernel.pylab.config import InlineBackend
1029 cfg = InlineBackend.instance()
1051 cfg = InlineBackend.instance()
1030 cfg.close_figures = close
1052 cfg.close_figures = close
@@ -1,116 +1,116 b''
1 """An interface for publishing rich data to frontends.
1 """An interface for publishing rich data to frontends.
2
2
3 There are two components of the display system:
3 There are two components of the display system:
4
4
5 * Display formatters, which take a Python object and compute the
5 * Display formatters, which take a Python object and compute the
6 representation of the object in various formats (text, HTML, SVG, etc.).
6 representation of the object in various formats (text, HTML, SVG, etc.).
7 * The display publisher that is used to send the representation data to the
7 * The display publisher that is used to send the representation data to the
8 various frontends.
8 various frontends.
9
9
10 This module defines the logic display publishing. The display publisher uses
10 This module defines the logic display publishing. The display publisher uses
11 the ``display_data`` message type that is defined in the IPython messaging
11 the ``display_data`` message type that is defined in the IPython messaging
12 spec.
12 spec.
13 """
13 """
14
14
15 # Copyright (c) IPython Development Team.
15 # Copyright (c) IPython Development Team.
16 # Distributed under the terms of the Modified BSD License.
16 # Distributed under the terms of the Modified BSD License.
17
17
18
18
19 import sys
19 import sys
20
20
21 from traitlets.config.configurable import Configurable
21 from traitlets.config.configurable import Configurable
22 from traitlets import List
22 from traitlets import List
23
23
24 # This used to be defined here - it is imported for backwards compatibility
24 # This used to be defined here - it is imported for backwards compatibility
25 from .display import publish_display_data
25 from .display import publish_display_data
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Main payload class
28 # Main payload class
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 class DisplayPublisher(Configurable):
31 class DisplayPublisher(Configurable):
32 """A traited class that publishes display data to frontends.
32 """A traited class that publishes display data to frontends.
33
33
34 Instances of this class are created by the main IPython object and should
34 Instances of this class are created by the main IPython object and should
35 be accessed there.
35 be accessed there.
36 """
36 """
37
37
38 def _validate_data(self, data, metadata=None):
38 def _validate_data(self, data, metadata=None):
39 """Validate the display data.
39 """Validate the display data.
40
40
41 Parameters
41 Parameters
42 ----------
42 ----------
43 data : dict
43 data : dict
44 The formata data dictionary.
44 The formata data dictionary.
45 metadata : dict
45 metadata : dict
46 Any metadata for the data.
46 Any metadata for the data.
47 """
47 """
48
48
49 if not isinstance(data, dict):
49 if not isinstance(data, dict):
50 raise TypeError('data must be a dict, got: %r' % data)
50 raise TypeError('data must be a dict, got: %r' % data)
51 if metadata is not None:
51 if metadata is not None:
52 if not isinstance(metadata, dict):
52 if not isinstance(metadata, dict):
53 raise TypeError('metadata must be a dict, got: %r' % data)
53 raise TypeError('metadata must be a dict, got: %r' % data)
54
54
55 def publish(self, data, metadata=None, source=None):
55 def publish(self, data, metadata=None, source=None, **kwargs):
56 """Publish data and metadata to all frontends.
56 """Publish data and metadata to all frontends.
57
57
58 See the ``display_data`` message in the messaging documentation for
58 See the ``display_data`` message in the messaging documentation for
59 more details about this message type.
59 more details about this message type.
60
60
61 The following MIME types are currently implemented:
61 The following MIME types are currently implemented:
62
62
63 * text/plain
63 * text/plain
64 * text/html
64 * text/html
65 * text/markdown
65 * text/markdown
66 * text/latex
66 * text/latex
67 * application/json
67 * application/json
68 * application/javascript
68 * application/javascript
69 * image/png
69 * image/png
70 * image/jpeg
70 * image/jpeg
71 * image/svg+xml
71 * image/svg+xml
72
72
73 Parameters
73 Parameters
74 ----------
74 ----------
75 data : dict
75 data : dict
76 A dictionary having keys that are valid MIME types (like
76 A dictionary having keys that are valid MIME types (like
77 'text/plain' or 'image/svg+xml') and values that are the data for
77 'text/plain' or 'image/svg+xml') and values that are the data for
78 that MIME type. The data itself must be a JSON'able data
78 that MIME type. The data itself must be a JSON'able data
79 structure. Minimally all data should have the 'text/plain' data,
79 structure. Minimally all data should have the 'text/plain' data,
80 which can be displayed by all frontends. If more than the plain
80 which can be displayed by all frontends. If more than the plain
81 text is given, it is up to the frontend to decide which
81 text is given, it is up to the frontend to decide which
82 representation to use.
82 representation to use.
83 metadata : dict
83 metadata : dict
84 A dictionary for metadata related to the data. This can contain
84 A dictionary for metadata related to the data. This can contain
85 arbitrary key, value pairs that frontends can use to interpret
85 arbitrary key, value pairs that frontends can use to interpret
86 the data. Metadata specific to each mime-type can be specified
86 the data. Metadata specific to each mime-type can be specified
87 in the metadata dict with the same mime-type keys as
87 in the metadata dict with the same mime-type keys as
88 the data itself.
88 the data itself.
89 source : str, deprecated
89 source : str, deprecated
90 Unused.
90 Unused.
91 """
91 """
92
92
93 # The default is to simply write the plain text data using sys.stdout.
93 # The default is to simply write the plain text data using sys.stdout.
94 if 'text/plain' in data:
94 if 'text/plain' in data:
95 print(data['text/plain'])
95 print(data['text/plain'])
96
96
97 def clear_output(self, wait=False):
97 def clear_output(self, wait=False):
98 """Clear the output of the cell receiving output."""
98 """Clear the output of the cell receiving output."""
99 print('\033[2K\r', end='')
99 print('\033[2K\r', end='')
100 sys.stdout.flush()
100 sys.stdout.flush()
101 print('\033[2K\r', end='')
101 print('\033[2K\r', end='')
102 sys.stderr.flush()
102 sys.stderr.flush()
103
103
104
104
105 class CapturingDisplayPublisher(DisplayPublisher):
105 class CapturingDisplayPublisher(DisplayPublisher):
106 """A DisplayPublisher that stores"""
106 """A DisplayPublisher that stores"""
107 outputs = List()
107 outputs = List()
108
108
109 def publish(self, data, metadata=None, source=None):
109 def publish(self, data, metadata=None, source=None):
110 self.outputs.append((data, metadata))
110 self.outputs.append((data, metadata))
111
111
112 def clear_output(self, wait=False):
112 def clear_output(self, wait=False):
113 super(CapturingDisplayPublisher, self).clear_output(wait)
113 super(CapturingDisplayPublisher, self).clear_output(wait)
114
114
115 # empty the list, *do not* reassign a new list
115 # empty the list, *do not* reassign a new list
116 del self.outputs[:]
116 del self.outputs[:]
General Comments 0
You need to be logged in to leave comments. Login now