##// END OF EJS Templates
Ensure import * includes the progressbar
Marius van Niekerk -
Show More
@@ -1,1386 +1,1387 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, b2a_base64, hexlify
8 from binascii import b2a_hex, b2a_base64, hexlify
9 import json
9 import json
10 import mimetypes
10 import mimetypes
11 import os
11 import os
12 import struct
12 import struct
13 import sys
13 import sys
14 import warnings
14 import warnings
15 from copy import deepcopy
15 from copy import deepcopy
16
16
17 from IPython.utils.py3compat import cast_unicode
17 from IPython.utils.py3compat import cast_unicode
18 from IPython.testing.skipdoctest import skip_doctest
18 from IPython.testing.skipdoctest import skip_doctest
19
19
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'GeoJSON', 'Javascript',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
24 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
24 'GeoJSON', 'Javascript', 'Image', 'clear_output', 'set_matplotlib_formats',
25 'publish_display_data', 'update_display', 'DisplayHandle', 'Video']
25 'set_matplotlib_close', 'publish_display_data', 'update_display', 'DisplayHandle',
26 'Video']
26
27
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28 # utility functions
29 # utility functions
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30
31
31 def _safe_exists(path):
32 def _safe_exists(path):
32 """Check path, but don't let exceptions raise"""
33 """Check path, but don't let exceptions raise"""
33 try:
34 try:
34 return os.path.exists(path)
35 return os.path.exists(path)
35 except Exception:
36 except Exception:
36 return False
37 return False
37
38
38 def _merge(d1, d2):
39 def _merge(d1, d2):
39 """Like update, but merges sub-dicts instead of clobbering at the top level.
40 """Like update, but merges sub-dicts instead of clobbering at the top level.
40
41
41 Updates d1 in-place
42 Updates d1 in-place
42 """
43 """
43
44
44 if not isinstance(d2, dict) or not isinstance(d1, dict):
45 if not isinstance(d2, dict) or not isinstance(d1, dict):
45 return d2
46 return d2
46 for key, value in d2.items():
47 for key, value in d2.items():
47 d1[key] = _merge(d1.get(key), value)
48 d1[key] = _merge(d1.get(key), value)
48 return d1
49 return d1
49
50
50 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
51 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
51 """internal implementation of all display_foo methods
52 """internal implementation of all display_foo methods
52
53
53 Parameters
54 Parameters
54 ----------
55 ----------
55 mimetype : str
56 mimetype : str
56 The mimetype to be published (e.g. 'image/png')
57 The mimetype to be published (e.g. 'image/png')
57 objs : tuple of objects
58 objs : tuple of objects
58 The Python objects to display, or if raw=True raw text data to
59 The Python objects to display, or if raw=True raw text data to
59 display.
60 display.
60 raw : bool
61 raw : bool
61 Are the data objects raw data or Python objects that need to be
62 Are the data objects raw data or Python objects that need to be
62 formatted before display? [default: False]
63 formatted before display? [default: False]
63 metadata : dict (optional)
64 metadata : dict (optional)
64 Metadata to be associated with the specific mimetype output.
65 Metadata to be associated with the specific mimetype output.
65 """
66 """
66 if metadata:
67 if metadata:
67 metadata = {mimetype: metadata}
68 metadata = {mimetype: metadata}
68 if raw:
69 if raw:
69 # turn list of pngdata into list of { 'image/png': pngdata }
70 # turn list of pngdata into list of { 'image/png': pngdata }
70 objs = [ {mimetype: obj} for obj in objs ]
71 objs = [ {mimetype: obj} for obj in objs ]
71 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
72 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
72
73
73 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
74 # Main functions
75 # Main functions
75 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
76
77
77 # use * to indicate transient is keyword-only
78 # use * to indicate transient is keyword-only
78 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
79 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
79 """Publish data and metadata to all frontends.
80 """Publish data and metadata to all frontends.
80
81
81 See the ``display_data`` message in the messaging documentation for
82 See the ``display_data`` message in the messaging documentation for
82 more details about this message type.
83 more details about this message type.
83
84
84 Keys of data and metadata can be any mime-type.
85 Keys of data and metadata can be any mime-type.
85
86
86 Parameters
87 Parameters
87 ----------
88 ----------
88 data : dict
89 data : dict
89 A dictionary having keys that are valid MIME types (like
90 A dictionary having keys that are valid MIME types (like
90 'text/plain' or 'image/svg+xml') and values that are the data for
91 'text/plain' or 'image/svg+xml') and values that are the data for
91 that MIME type. The data itself must be a JSON'able data
92 that MIME type. The data itself must be a JSON'able data
92 structure. Minimally all data should have the 'text/plain' data,
93 structure. Minimally all data should have the 'text/plain' data,
93 which can be displayed by all frontends. If more than the plain
94 which can be displayed by all frontends. If more than the plain
94 text is given, it is up to the frontend to decide which
95 text is given, it is up to the frontend to decide which
95 representation to use.
96 representation to use.
96 metadata : dict
97 metadata : dict
97 A dictionary for metadata related to the data. This can contain
98 A dictionary for metadata related to the data. This can contain
98 arbitrary key, value pairs that frontends can use to interpret
99 arbitrary key, value pairs that frontends can use to interpret
99 the data. mime-type keys matching those in data can be used
100 the data. mime-type keys matching those in data can be used
100 to specify metadata about particular representations.
101 to specify metadata about particular representations.
101 source : str, deprecated
102 source : str, deprecated
102 Unused.
103 Unused.
103 transient : dict, keyword-only
104 transient : dict, keyword-only
104 A dictionary of transient data, such as display_id.
105 A dictionary of transient data, such as display_id.
105 """
106 """
106 from IPython.core.interactiveshell import InteractiveShell
107 from IPython.core.interactiveshell import InteractiveShell
107
108
108 display_pub = InteractiveShell.instance().display_pub
109 display_pub = InteractiveShell.instance().display_pub
109
110
110 # only pass transient if supplied,
111 # only pass transient if supplied,
111 # to avoid errors with older ipykernel.
112 # to avoid errors with older ipykernel.
112 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
113 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
113 if transient:
114 if transient:
114 kwargs['transient'] = transient
115 kwargs['transient'] = transient
115
116
116 display_pub.publish(
117 display_pub.publish(
117 data=data,
118 data=data,
118 metadata=metadata,
119 metadata=metadata,
119 **kwargs
120 **kwargs
120 )
121 )
121
122
122
123
123 def _new_id():
124 def _new_id():
124 """Generate a new random text id with urandom"""
125 """Generate a new random text id with urandom"""
125 return b2a_hex(os.urandom(16)).decode('ascii')
126 return b2a_hex(os.urandom(16)).decode('ascii')
126
127
127
128
128 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
129 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
129 """Display a Python object in all frontends.
130 """Display a Python object in all frontends.
130
131
131 By default all representations will be computed and sent to the frontends.
132 By default all representations will be computed and sent to the frontends.
132 Frontends can decide which representation is used and how.
133 Frontends can decide which representation is used and how.
133
134
134 In terminal IPython this will be similar to using :func:`print`, for use in richer
135 In terminal IPython this will be similar to using :func:`print`, for use in richer
135 frontends see Jupyter notebook examples with rich display logic.
136 frontends see Jupyter notebook examples with rich display logic.
136
137
137 Parameters
138 Parameters
138 ----------
139 ----------
139 objs : tuple of objects
140 objs : tuple of objects
140 The Python objects to display.
141 The Python objects to display.
141 raw : bool, optional
142 raw : bool, optional
142 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
143 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
143 or Python objects that need to be formatted before display? [default: False]
144 or Python objects that need to be formatted before display? [default: False]
144 include : list, tuple or set, optional
145 include : list, tuple or set, optional
145 A list of format type strings (MIME types) to include in the
146 A list of format type strings (MIME types) to include in the
146 format data dict. If this is set *only* the format types included
147 format data dict. If this is set *only* the format types included
147 in this list will be computed.
148 in this list will be computed.
148 exclude : list, tuple or set, optional
149 exclude : list, tuple or set, optional
149 A list of format type strings (MIME types) to exclude in the format
150 A list of format type strings (MIME types) to exclude in the format
150 data dict. If this is set all format types will be computed,
151 data dict. If this is set all format types will be computed,
151 except for those included in this argument.
152 except for those included in this argument.
152 metadata : dict, optional
153 metadata : dict, optional
153 A dictionary of metadata to associate with the output.
154 A dictionary of metadata to associate with the output.
154 mime-type keys in this dictionary will be associated with the individual
155 mime-type keys in this dictionary will be associated with the individual
155 representation formats, if they exist.
156 representation formats, if they exist.
156 transient : dict, optional
157 transient : dict, optional
157 A dictionary of transient data to associate with the output.
158 A dictionary of transient data to associate with the output.
158 Data in this dict should not be persisted to files (e.g. notebooks).
159 Data in this dict should not be persisted to files (e.g. notebooks).
159 display_id : str, bool optional
160 display_id : str, bool optional
160 Set an id for the display.
161 Set an id for the display.
161 This id can be used for updating this display area later via update_display.
162 This id can be used for updating this display area later via update_display.
162 If given as `True`, generate a new `display_id`
163 If given as `True`, generate a new `display_id`
163 kwargs: additional keyword-args, optional
164 kwargs: additional keyword-args, optional
164 Additional keyword-arguments are passed through to the display publisher.
165 Additional keyword-arguments are passed through to the display publisher.
165
166
166 Returns
167 Returns
167 -------
168 -------
168
169
169 handle: DisplayHandle
170 handle: DisplayHandle
170 Returns a handle on updatable displays for use with :func:`update_display`,
171 Returns a handle on updatable displays for use with :func:`update_display`,
171 if `display_id` is given. Returns :any:`None` if no `display_id` is given
172 if `display_id` is given. Returns :any:`None` if no `display_id` is given
172 (default).
173 (default).
173
174
174 Examples
175 Examples
175 --------
176 --------
176
177
177 >>> class Json(object):
178 >>> class Json(object):
178 ... def __init__(self, json):
179 ... def __init__(self, json):
179 ... self.json = json
180 ... self.json = json
180 ... def _repr_pretty_(self, pp, cycle):
181 ... def _repr_pretty_(self, pp, cycle):
181 ... import json
182 ... import json
182 ... pp.text(json.dumps(self.json, indent=2))
183 ... pp.text(json.dumps(self.json, indent=2))
183 ... def __repr__(self):
184 ... def __repr__(self):
184 ... return str(self.json)
185 ... return str(self.json)
185 ...
186 ...
186
187
187 >>> d = Json({1:2, 3: {4:5}})
188 >>> d = Json({1:2, 3: {4:5}})
188
189
189 >>> print(d)
190 >>> print(d)
190 {1: 2, 3: {4: 5}}
191 {1: 2, 3: {4: 5}}
191
192
192 >>> display(d)
193 >>> display(d)
193 {
194 {
194 "1": 2,
195 "1": 2,
195 "3": {
196 "3": {
196 "4": 5
197 "4": 5
197 }
198 }
198 }
199 }
199
200
200 >>> def int_formatter(integer, pp, cycle):
201 >>> def int_formatter(integer, pp, cycle):
201 ... pp.text('I'*integer)
202 ... pp.text('I'*integer)
202
203
203 >>> plain = get_ipython().display_formatter.formatters['text/plain']
204 >>> plain = get_ipython().display_formatter.formatters['text/plain']
204 >>> plain.for_type(int, int_formatter)
205 >>> plain.for_type(int, int_formatter)
205 <function _repr_pprint at 0x...>
206 <function _repr_pprint at 0x...>
206 >>> display(7-5)
207 >>> display(7-5)
207 II
208 II
208
209
209 >>> del plain.type_printers[int]
210 >>> del plain.type_printers[int]
210 >>> display(7-5)
211 >>> display(7-5)
211 2
212 2
212
213
213 See Also
214 See Also
214 --------
215 --------
215
216
216 :func:`update_display`
217 :func:`update_display`
217
218
218 Notes
219 Notes
219 -----
220 -----
220
221
221 In Python, objects can declare their textual representation using the
222 In Python, objects can declare their textual representation using the
222 `__repr__` method. IPython expands on this idea and allows objects to declare
223 `__repr__` method. IPython expands on this idea and allows objects to declare
223 other, rich representations including:
224 other, rich representations including:
224
225
225 - HTML
226 - HTML
226 - JSON
227 - JSON
227 - PNG
228 - PNG
228 - JPEG
229 - JPEG
229 - SVG
230 - SVG
230 - LaTeX
231 - LaTeX
231
232
232 A single object can declare some or all of these representations; all are
233 A single object can declare some or all of these representations; all are
233 handled by IPython's display system.
234 handled by IPython's display system.
234
235
235 The main idea of the first approach is that you have to implement special
236 The main idea of the first approach is that you have to implement special
236 display methods when you define your class, one for each representation you
237 display methods when you define your class, one for each representation you
237 want to use. Here is a list of the names of the special methods and the
238 want to use. Here is a list of the names of the special methods and the
238 values they must return:
239 values they must return:
239
240
240 - `_repr_html_`: return raw HTML as a string
241 - `_repr_html_`: return raw HTML as a string
241 - `_repr_json_`: return a JSONable dict
242 - `_repr_json_`: return a JSONable dict
242 - `_repr_jpeg_`: return raw JPEG data
243 - `_repr_jpeg_`: return raw JPEG data
243 - `_repr_png_`: return raw PNG data
244 - `_repr_png_`: return raw PNG data
244 - `_repr_svg_`: return raw SVG data as a string
245 - `_repr_svg_`: return raw SVG data as a string
245 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
246 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
246 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
247 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
247 from all mimetypes to data.
248 from all mimetypes to data.
248 Use this for any mime-type not listed above.
249 Use this for any mime-type not listed above.
249
250
250 When you are directly writing your own classes, you can adapt them for
251 When you are directly writing your own classes, you can adapt them for
251 display in IPython by following the above approach. But in practice, you
252 display in IPython by following the above approach. But in practice, you
252 often need to work with existing classes that you can't easily modify.
253 often need to work with existing classes that you can't easily modify.
253
254
254 You can refer to the documentation on IPython display formatters in order to
255 You can refer to the documentation on IPython display formatters in order to
255 register custom formatters for already existing types.
256 register custom formatters for already existing types.
256
257
257 .. versionadded:: 5.4 display available without import
258 .. versionadded:: 5.4 display available without import
258 .. versionadded:: 6.1 display available without import
259 .. versionadded:: 6.1 display available without import
259
260
260 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
261 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
261 the user without import. If you are using display in a document that might
262 the user without import. If you are using display in a document that might
262 be used in a pure python context or with older version of IPython, use the
263 be used in a pure python context or with older version of IPython, use the
263 following import at the top of your file::
264 following import at the top of your file::
264
265
265 from IPython.display import display
266 from IPython.display import display
266
267
267 """
268 """
268 from IPython.core.interactiveshell import InteractiveShell
269 from IPython.core.interactiveshell import InteractiveShell
269
270
270 if not InteractiveShell.initialized():
271 if not InteractiveShell.initialized():
271 # Directly print objects.
272 # Directly print objects.
272 print(*objs)
273 print(*objs)
273 return
274 return
274
275
275 raw = kwargs.pop('raw', False)
276 raw = kwargs.pop('raw', False)
276 if transient is None:
277 if transient is None:
277 transient = {}
278 transient = {}
278 if metadata is None:
279 if metadata is None:
279 metadata={}
280 metadata={}
280 if display_id:
281 if display_id:
281 if display_id is True:
282 if display_id is True:
282 display_id = _new_id()
283 display_id = _new_id()
283 transient['display_id'] = display_id
284 transient['display_id'] = display_id
284 if kwargs.get('update') and 'display_id' not in transient:
285 if kwargs.get('update') and 'display_id' not in transient:
285 raise TypeError('display_id required for update_display')
286 raise TypeError('display_id required for update_display')
286 if transient:
287 if transient:
287 kwargs['transient'] = transient
288 kwargs['transient'] = transient
288
289
289 if not raw:
290 if not raw:
290 format = InteractiveShell.instance().display_formatter.format
291 format = InteractiveShell.instance().display_formatter.format
291
292
292 for obj in objs:
293 for obj in objs:
293 if raw:
294 if raw:
294 publish_display_data(data=obj, metadata=metadata, **kwargs)
295 publish_display_data(data=obj, metadata=metadata, **kwargs)
295 else:
296 else:
296 format_dict, md_dict = format(obj, include=include, exclude=exclude)
297 format_dict, md_dict = format(obj, include=include, exclude=exclude)
297 if not format_dict:
298 if not format_dict:
298 # nothing to display (e.g. _ipython_display_ took over)
299 # nothing to display (e.g. _ipython_display_ took over)
299 continue
300 continue
300 if metadata:
301 if metadata:
301 # kwarg-specified metadata gets precedence
302 # kwarg-specified metadata gets precedence
302 _merge(md_dict, metadata)
303 _merge(md_dict, metadata)
303 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
304 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
304 if display_id:
305 if display_id:
305 return DisplayHandle(display_id)
306 return DisplayHandle(display_id)
306
307
307
308
308 # use * for keyword-only display_id arg
309 # use * for keyword-only display_id arg
309 def update_display(obj, *, display_id, **kwargs):
310 def update_display(obj, *, display_id, **kwargs):
310 """Update an existing display by id
311 """Update an existing display by id
311
312
312 Parameters
313 Parameters
313 ----------
314 ----------
314
315
315 obj:
316 obj:
316 The object with which to update the display
317 The object with which to update the display
317 display_id: keyword-only
318 display_id: keyword-only
318 The id of the display to update
319 The id of the display to update
319
320
320 See Also
321 See Also
321 --------
322 --------
322
323
323 :func:`display`
324 :func:`display`
324 """
325 """
325 kwargs['update'] = True
326 kwargs['update'] = True
326 display(obj, display_id=display_id, **kwargs)
327 display(obj, display_id=display_id, **kwargs)
327
328
328
329
329 class DisplayHandle(object):
330 class DisplayHandle(object):
330 """A handle on an updatable display
331 """A handle on an updatable display
331
332
332 Call `.update(obj)` to display a new object.
333 Call `.update(obj)` to display a new object.
333
334
334 Call `.display(obj`) to add a new instance of this display,
335 Call `.display(obj`) to add a new instance of this display,
335 and update existing instances.
336 and update existing instances.
336
337
337 See Also
338 See Also
338 --------
339 --------
339
340
340 :func:`display`, :func:`update_display`
341 :func:`display`, :func:`update_display`
341
342
342 """
343 """
343
344
344 def __init__(self, display_id=None):
345 def __init__(self, display_id=None):
345 if display_id is None:
346 if display_id is None:
346 display_id = _new_id()
347 display_id = _new_id()
347 self.display_id = display_id
348 self.display_id = display_id
348
349
349 def __repr__(self):
350 def __repr__(self):
350 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
351 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
351
352
352 def display(self, obj, **kwargs):
353 def display(self, obj, **kwargs):
353 """Make a new display with my id, updating existing instances.
354 """Make a new display with my id, updating existing instances.
354
355
355 Parameters
356 Parameters
356 ----------
357 ----------
357
358
358 obj:
359 obj:
359 object to display
360 object to display
360 **kwargs:
361 **kwargs:
361 additional keyword arguments passed to display
362 additional keyword arguments passed to display
362 """
363 """
363 display(obj, display_id=self.display_id, **kwargs)
364 display(obj, display_id=self.display_id, **kwargs)
364
365
365 def update(self, obj, **kwargs):
366 def update(self, obj, **kwargs):
366 """Update existing displays with my id
367 """Update existing displays with my id
367
368
368 Parameters
369 Parameters
369 ----------
370 ----------
370
371
371 obj:
372 obj:
372 object to display
373 object to display
373 **kwargs:
374 **kwargs:
374 additional keyword arguments passed to update_display
375 additional keyword arguments passed to update_display
375 """
376 """
376 update_display(obj, display_id=self.display_id, **kwargs)
377 update_display(obj, display_id=self.display_id, **kwargs)
377
378
378
379
379 def display_pretty(*objs, **kwargs):
380 def display_pretty(*objs, **kwargs):
380 """Display the pretty (default) representation of an object.
381 """Display the pretty (default) representation of an object.
381
382
382 Parameters
383 Parameters
383 ----------
384 ----------
384 objs : tuple of objects
385 objs : tuple of objects
385 The Python objects to display, or if raw=True raw text data to
386 The Python objects to display, or if raw=True raw text data to
386 display.
387 display.
387 raw : bool
388 raw : bool
388 Are the data objects raw data or Python objects that need to be
389 Are the data objects raw data or Python objects that need to be
389 formatted before display? [default: False]
390 formatted before display? [default: False]
390 metadata : dict (optional)
391 metadata : dict (optional)
391 Metadata to be associated with the specific mimetype output.
392 Metadata to be associated with the specific mimetype output.
392 """
393 """
393 _display_mimetype('text/plain', objs, **kwargs)
394 _display_mimetype('text/plain', objs, **kwargs)
394
395
395
396
396 def display_html(*objs, **kwargs):
397 def display_html(*objs, **kwargs):
397 """Display the HTML representation of an object.
398 """Display the HTML representation of an object.
398
399
399 Note: If raw=False and the object does not have a HTML
400 Note: If raw=False and the object does not have a HTML
400 representation, no HTML will be shown.
401 representation, no HTML will be shown.
401
402
402 Parameters
403 Parameters
403 ----------
404 ----------
404 objs : tuple of objects
405 objs : tuple of objects
405 The Python objects to display, or if raw=True raw HTML data to
406 The Python objects to display, or if raw=True raw HTML data to
406 display.
407 display.
407 raw : bool
408 raw : bool
408 Are the data objects raw data or Python objects that need to be
409 Are the data objects raw data or Python objects that need to be
409 formatted before display? [default: False]
410 formatted before display? [default: False]
410 metadata : dict (optional)
411 metadata : dict (optional)
411 Metadata to be associated with the specific mimetype output.
412 Metadata to be associated with the specific mimetype output.
412 """
413 """
413 _display_mimetype('text/html', objs, **kwargs)
414 _display_mimetype('text/html', objs, **kwargs)
414
415
415
416
416 def display_markdown(*objs, **kwargs):
417 def display_markdown(*objs, **kwargs):
417 """Displays the Markdown representation of an object.
418 """Displays the Markdown representation of an object.
418
419
419 Parameters
420 Parameters
420 ----------
421 ----------
421 objs : tuple of objects
422 objs : tuple of objects
422 The Python objects to display, or if raw=True raw markdown data to
423 The Python objects to display, or if raw=True raw markdown data to
423 display.
424 display.
424 raw : bool
425 raw : bool
425 Are the data objects raw data or Python objects that need to be
426 Are the data objects raw data or Python objects that need to be
426 formatted before display? [default: False]
427 formatted before display? [default: False]
427 metadata : dict (optional)
428 metadata : dict (optional)
428 Metadata to be associated with the specific mimetype output.
429 Metadata to be associated with the specific mimetype output.
429 """
430 """
430
431
431 _display_mimetype('text/markdown', objs, **kwargs)
432 _display_mimetype('text/markdown', objs, **kwargs)
432
433
433
434
434 def display_svg(*objs, **kwargs):
435 def display_svg(*objs, **kwargs):
435 """Display the SVG representation of an object.
436 """Display the SVG representation of an object.
436
437
437 Parameters
438 Parameters
438 ----------
439 ----------
439 objs : tuple of objects
440 objs : tuple of objects
440 The Python objects to display, or if raw=True raw svg data to
441 The Python objects to display, or if raw=True raw svg data to
441 display.
442 display.
442 raw : bool
443 raw : bool
443 Are the data objects raw data or Python objects that need to be
444 Are the data objects raw data or Python objects that need to be
444 formatted before display? [default: False]
445 formatted before display? [default: False]
445 metadata : dict (optional)
446 metadata : dict (optional)
446 Metadata to be associated with the specific mimetype output.
447 Metadata to be associated with the specific mimetype output.
447 """
448 """
448 _display_mimetype('image/svg+xml', objs, **kwargs)
449 _display_mimetype('image/svg+xml', objs, **kwargs)
449
450
450
451
451 def display_png(*objs, **kwargs):
452 def display_png(*objs, **kwargs):
452 """Display the PNG representation of an object.
453 """Display the PNG representation of an object.
453
454
454 Parameters
455 Parameters
455 ----------
456 ----------
456 objs : tuple of objects
457 objs : tuple of objects
457 The Python objects to display, or if raw=True raw png data to
458 The Python objects to display, or if raw=True raw png data to
458 display.
459 display.
459 raw : bool
460 raw : bool
460 Are the data objects raw data or Python objects that need to be
461 Are the data objects raw data or Python objects that need to be
461 formatted before display? [default: False]
462 formatted before display? [default: False]
462 metadata : dict (optional)
463 metadata : dict (optional)
463 Metadata to be associated with the specific mimetype output.
464 Metadata to be associated with the specific mimetype output.
464 """
465 """
465 _display_mimetype('image/png', objs, **kwargs)
466 _display_mimetype('image/png', objs, **kwargs)
466
467
467
468
468 def display_jpeg(*objs, **kwargs):
469 def display_jpeg(*objs, **kwargs):
469 """Display the JPEG representation of an object.
470 """Display the JPEG representation of an object.
470
471
471 Parameters
472 Parameters
472 ----------
473 ----------
473 objs : tuple of objects
474 objs : tuple of objects
474 The Python objects to display, or if raw=True raw JPEG data to
475 The Python objects to display, or if raw=True raw JPEG data to
475 display.
476 display.
476 raw : bool
477 raw : bool
477 Are the data objects raw data or Python objects that need to be
478 Are the data objects raw data or Python objects that need to be
478 formatted before display? [default: False]
479 formatted before display? [default: False]
479 metadata : dict (optional)
480 metadata : dict (optional)
480 Metadata to be associated with the specific mimetype output.
481 Metadata to be associated with the specific mimetype output.
481 """
482 """
482 _display_mimetype('image/jpeg', objs, **kwargs)
483 _display_mimetype('image/jpeg', objs, **kwargs)
483
484
484
485
485 def display_latex(*objs, **kwargs):
486 def display_latex(*objs, **kwargs):
486 """Display the LaTeX representation of an object.
487 """Display the LaTeX representation of an object.
487
488
488 Parameters
489 Parameters
489 ----------
490 ----------
490 objs : tuple of objects
491 objs : tuple of objects
491 The Python objects to display, or if raw=True raw latex data to
492 The Python objects to display, or if raw=True raw latex data to
492 display.
493 display.
493 raw : bool
494 raw : bool
494 Are the data objects raw data or Python objects that need to be
495 Are the data objects raw data or Python objects that need to be
495 formatted before display? [default: False]
496 formatted before display? [default: False]
496 metadata : dict (optional)
497 metadata : dict (optional)
497 Metadata to be associated with the specific mimetype output.
498 Metadata to be associated with the specific mimetype output.
498 """
499 """
499 _display_mimetype('text/latex', objs, **kwargs)
500 _display_mimetype('text/latex', objs, **kwargs)
500
501
501
502
502 def display_json(*objs, **kwargs):
503 def display_json(*objs, **kwargs):
503 """Display the JSON representation of an object.
504 """Display the JSON representation of an object.
504
505
505 Note that not many frontends support displaying JSON.
506 Note that not many frontends support displaying JSON.
506
507
507 Parameters
508 Parameters
508 ----------
509 ----------
509 objs : tuple of objects
510 objs : tuple of objects
510 The Python objects to display, or if raw=True raw json data to
511 The Python objects to display, or if raw=True raw json data to
511 display.
512 display.
512 raw : bool
513 raw : bool
513 Are the data objects raw data or Python objects that need to be
514 Are the data objects raw data or Python objects that need to be
514 formatted before display? [default: False]
515 formatted before display? [default: False]
515 metadata : dict (optional)
516 metadata : dict (optional)
516 Metadata to be associated with the specific mimetype output.
517 Metadata to be associated with the specific mimetype output.
517 """
518 """
518 _display_mimetype('application/json', objs, **kwargs)
519 _display_mimetype('application/json', objs, **kwargs)
519
520
520
521
521 def display_javascript(*objs, **kwargs):
522 def display_javascript(*objs, **kwargs):
522 """Display the Javascript representation of an object.
523 """Display the Javascript representation of an object.
523
524
524 Parameters
525 Parameters
525 ----------
526 ----------
526 objs : tuple of objects
527 objs : tuple of objects
527 The Python objects to display, or if raw=True raw javascript data to
528 The Python objects to display, or if raw=True raw javascript data to
528 display.
529 display.
529 raw : bool
530 raw : bool
530 Are the data objects raw data or Python objects that need to be
531 Are the data objects raw data or Python objects that need to be
531 formatted before display? [default: False]
532 formatted before display? [default: False]
532 metadata : dict (optional)
533 metadata : dict (optional)
533 Metadata to be associated with the specific mimetype output.
534 Metadata to be associated with the specific mimetype output.
534 """
535 """
535 _display_mimetype('application/javascript', objs, **kwargs)
536 _display_mimetype('application/javascript', objs, **kwargs)
536
537
537
538
538 def display_pdf(*objs, **kwargs):
539 def display_pdf(*objs, **kwargs):
539 """Display the PDF representation of an object.
540 """Display the PDF representation of an object.
540
541
541 Parameters
542 Parameters
542 ----------
543 ----------
543 objs : tuple of objects
544 objs : tuple of objects
544 The Python objects to display, or if raw=True raw javascript data to
545 The Python objects to display, or if raw=True raw javascript data to
545 display.
546 display.
546 raw : bool
547 raw : bool
547 Are the data objects raw data or Python objects that need to be
548 Are the data objects raw data or Python objects that need to be
548 formatted before display? [default: False]
549 formatted before display? [default: False]
549 metadata : dict (optional)
550 metadata : dict (optional)
550 Metadata to be associated with the specific mimetype output.
551 Metadata to be associated with the specific mimetype output.
551 """
552 """
552 _display_mimetype('application/pdf', objs, **kwargs)
553 _display_mimetype('application/pdf', objs, **kwargs)
553
554
554
555
555 #-----------------------------------------------------------------------------
556 #-----------------------------------------------------------------------------
556 # Smart classes
557 # Smart classes
557 #-----------------------------------------------------------------------------
558 #-----------------------------------------------------------------------------
558
559
559
560
560 class DisplayObject(object):
561 class DisplayObject(object):
561 """An object that wraps data to be displayed."""
562 """An object that wraps data to be displayed."""
562
563
563 _read_flags = 'r'
564 _read_flags = 'r'
564 _show_mem_addr = False
565 _show_mem_addr = False
565 metadata = None
566 metadata = None
566
567
567 def __init__(self, data=None, url=None, filename=None, metadata=None):
568 def __init__(self, data=None, url=None, filename=None, metadata=None):
568 """Create a display object given raw data.
569 """Create a display object given raw data.
569
570
570 When this object is returned by an expression or passed to the
571 When this object is returned by an expression or passed to the
571 display function, it will result in the data being displayed
572 display function, it will result in the data being displayed
572 in the frontend. The MIME type of the data should match the
573 in the frontend. The MIME type of the data should match the
573 subclasses used, so the Png subclass should be used for 'image/png'
574 subclasses used, so the Png subclass should be used for 'image/png'
574 data. If the data is a URL, the data will first be downloaded
575 data. If the data is a URL, the data will first be downloaded
575 and then displayed. If
576 and then displayed. If
576
577
577 Parameters
578 Parameters
578 ----------
579 ----------
579 data : unicode, str or bytes
580 data : unicode, str or bytes
580 The raw data or a URL or file to load the data from
581 The raw data or a URL or file to load the data from
581 url : unicode
582 url : unicode
582 A URL to download the data from.
583 A URL to download the data from.
583 filename : unicode
584 filename : unicode
584 Path to a local file to load the data from.
585 Path to a local file to load the data from.
585 metadata : dict
586 metadata : dict
586 Dict of metadata associated to be the object when displayed
587 Dict of metadata associated to be the object when displayed
587 """
588 """
588 if data is not None and isinstance(data, str):
589 if data is not None and isinstance(data, str):
589 if data.startswith('http') and url is None:
590 if data.startswith('http') and url is None:
590 url = data
591 url = data
591 filename = None
592 filename = None
592 data = None
593 data = None
593 elif _safe_exists(data) and filename is None:
594 elif _safe_exists(data) and filename is None:
594 url = None
595 url = None
595 filename = data
596 filename = data
596 data = None
597 data = None
597
598
598 self.data = data
599 self.data = data
599 self.url = url
600 self.url = url
600 self.filename = filename
601 self.filename = filename
601
602
602 if metadata is not None:
603 if metadata is not None:
603 self.metadata = metadata
604 self.metadata = metadata
604 elif self.metadata is None:
605 elif self.metadata is None:
605 self.metadata = {}
606 self.metadata = {}
606
607
607 self.reload()
608 self.reload()
608 self._check_data()
609 self._check_data()
609
610
610 def __repr__(self):
611 def __repr__(self):
611 if not self._show_mem_addr:
612 if not self._show_mem_addr:
612 cls = self.__class__
613 cls = self.__class__
613 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
614 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
614 else:
615 else:
615 r = super(DisplayObject, self).__repr__()
616 r = super(DisplayObject, self).__repr__()
616 return r
617 return r
617
618
618 def _check_data(self):
619 def _check_data(self):
619 """Override in subclasses if there's something to check."""
620 """Override in subclasses if there's something to check."""
620 pass
621 pass
621
622
622 def _data_and_metadata(self):
623 def _data_and_metadata(self):
623 """shortcut for returning metadata with shape information, if defined"""
624 """shortcut for returning metadata with shape information, if defined"""
624 if self.metadata:
625 if self.metadata:
625 return self.data, deepcopy(self.metadata)
626 return self.data, deepcopy(self.metadata)
626 else:
627 else:
627 return self.data
628 return self.data
628
629
629 def reload(self):
630 def reload(self):
630 """Reload the raw data from file or URL."""
631 """Reload the raw data from file or URL."""
631 if self.filename is not None:
632 if self.filename is not None:
632 with open(self.filename, self._read_flags) as f:
633 with open(self.filename, self._read_flags) as f:
633 self.data = f.read()
634 self.data = f.read()
634 elif self.url is not None:
635 elif self.url is not None:
635 try:
636 try:
636 # Deferred import
637 # Deferred import
637 from urllib.request import urlopen
638 from urllib.request import urlopen
638 response = urlopen(self.url)
639 response = urlopen(self.url)
639 self.data = response.read()
640 self.data = response.read()
640 # extract encoding from header, if there is one:
641 # extract encoding from header, if there is one:
641 encoding = None
642 encoding = None
642 for sub in response.headers['content-type'].split(';'):
643 for sub in response.headers['content-type'].split(';'):
643 sub = sub.strip()
644 sub = sub.strip()
644 if sub.startswith('charset'):
645 if sub.startswith('charset'):
645 encoding = sub.split('=')[-1].strip()
646 encoding = sub.split('=')[-1].strip()
646 break
647 break
647 # decode data, if an encoding was specified
648 # decode data, if an encoding was specified
648 if encoding:
649 if encoding:
649 self.data = self.data.decode(encoding, 'replace')
650 self.data = self.data.decode(encoding, 'replace')
650 except:
651 except:
651 self.data = None
652 self.data = None
652
653
653 class TextDisplayObject(DisplayObject):
654 class TextDisplayObject(DisplayObject):
654 """Validate that display data is text"""
655 """Validate that display data is text"""
655 def _check_data(self):
656 def _check_data(self):
656 if self.data is not None and not isinstance(self.data, str):
657 if self.data is not None and not isinstance(self.data, str):
657 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
658 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
658
659
659 class Pretty(TextDisplayObject):
660 class Pretty(TextDisplayObject):
660
661
661 def _repr_pretty_(self, pp, cycle):
662 def _repr_pretty_(self, pp, cycle):
662 return pp.text(self.data)
663 return pp.text(self.data)
663
664
664
665
665 class HTML(TextDisplayObject):
666 class HTML(TextDisplayObject):
666
667
667 def _repr_html_(self):
668 def _repr_html_(self):
668 return self.data
669 return self.data
669
670
670 def __html__(self):
671 def __html__(self):
671 """
672 """
672 This method exists to inform other HTML-using modules (e.g. Markupsafe,
673 This method exists to inform other HTML-using modules (e.g. Markupsafe,
673 htmltag, etc) that this object is HTML and does not need things like
674 htmltag, etc) that this object is HTML and does not need things like
674 special characters (<>&) escaped.
675 special characters (<>&) escaped.
675 """
676 """
676 return self._repr_html_()
677 return self._repr_html_()
677
678
678
679
679 class Markdown(TextDisplayObject):
680 class Markdown(TextDisplayObject):
680
681
681 def _repr_markdown_(self):
682 def _repr_markdown_(self):
682 return self.data
683 return self.data
683
684
684
685
685 class Math(TextDisplayObject):
686 class Math(TextDisplayObject):
686
687
687 def _repr_latex_(self):
688 def _repr_latex_(self):
688 s = self.data.strip('$')
689 s = self.data.strip('$')
689 return "$$%s$$" % s
690 return "$$%s$$" % s
690
691
691
692
692 class Latex(TextDisplayObject):
693 class Latex(TextDisplayObject):
693
694
694 def _repr_latex_(self):
695 def _repr_latex_(self):
695 return self.data
696 return self.data
696
697
697
698
698 class SVG(DisplayObject):
699 class SVG(DisplayObject):
699
700
700 _read_flags = 'rb'
701 _read_flags = 'rb'
701 # wrap data in a property, which extracts the <svg> tag, discarding
702 # wrap data in a property, which extracts the <svg> tag, discarding
702 # document headers
703 # document headers
703 _data = None
704 _data = None
704
705
705 @property
706 @property
706 def data(self):
707 def data(self):
707 return self._data
708 return self._data
708
709
709 @data.setter
710 @data.setter
710 def data(self, svg):
711 def data(self, svg):
711 if svg is None:
712 if svg is None:
712 self._data = None
713 self._data = None
713 return
714 return
714 # parse into dom object
715 # parse into dom object
715 from xml.dom import minidom
716 from xml.dom import minidom
716 x = minidom.parseString(svg)
717 x = minidom.parseString(svg)
717 # get svg tag (should be 1)
718 # get svg tag (should be 1)
718 found_svg = x.getElementsByTagName('svg')
719 found_svg = x.getElementsByTagName('svg')
719 if found_svg:
720 if found_svg:
720 svg = found_svg[0].toxml()
721 svg = found_svg[0].toxml()
721 else:
722 else:
722 # fallback on the input, trust the user
723 # fallback on the input, trust the user
723 # but this is probably an error.
724 # but this is probably an error.
724 pass
725 pass
725 svg = cast_unicode(svg)
726 svg = cast_unicode(svg)
726 self._data = svg
727 self._data = svg
727
728
728 def _repr_svg_(self):
729 def _repr_svg_(self):
729 return self._data_and_metadata()
730 return self._data_and_metadata()
730
731
731 class ProgressBar(DisplayObject):
732 class ProgressBar(DisplayObject):
732 """Progressbar supports displaying a progressbar like element
733 """Progressbar supports displaying a progressbar like element
733 """
734 """
734 def __init__(self, total):
735 def __init__(self, total):
735 """Creates a new progressbar
736 """Creates a new progressbar
736
737
737 Parameters
738 Parameters
738 ----------
739 ----------
739 total : int
740 total : int
740 maximnum size of the progressbar
741 maximum size of the progressbar
741 """
742 """
742 self._display_id = hexlify(os.urandom(8)).decode('ascii')
743 self._display_id = hexlify(os.urandom(8)).decode('ascii')
743 self.total = total
744 self.total = total
744 self._progress = 0
745 self._progress = 0
745
746
746 def _repr_html_(self):
747 def _repr_html_(self):
747 return "<progress style='width:100%' max='{}' value='{}'></progress>".format(self.total, self.progress)
748 return "<progress style='width:100%' max='{}' value='{}'></progress>".format(self.total, self.progress)
748
749
749 def display(self):
750 def display(self):
750 display(self, display_id=self._display_id)
751 display(self, display_id=self._display_id)
751
752
752 def update(self):
753 def update(self):
753 display(self, display_id=self._display_id, update=True)
754 display(self, display_id=self._display_id, update=True)
754
755
755 @property
756 @property
756 def progress(self):
757 def progress(self):
757 return self._progress
758 return self._progress
758
759
759 @progress.setter
760 @progress.setter
760 def progress(self, value):
761 def progress(self, value):
761 self._progress = value
762 self._progress = value
762 self.update()
763 self.update()
763
764
764 class JSON(DisplayObject):
765 class JSON(DisplayObject):
765 """JSON expects a JSON-able dict or list
766 """JSON expects a JSON-able dict or list
766
767
767 not an already-serialized JSON string.
768 not an already-serialized JSON string.
768
769
769 Scalar types (None, number, string) are not allowed, only dict or list containers.
770 Scalar types (None, number, string) are not allowed, only dict or list containers.
770 """
771 """
771 # wrap data in a property, which warns about passing already-serialized JSON
772 # wrap data in a property, which warns about passing already-serialized JSON
772 _data = None
773 _data = None
773 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, **kwargs):
774 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, **kwargs):
774 """Create a JSON display object given raw data.
775 """Create a JSON display object given raw data.
775
776
776 Parameters
777 Parameters
777 ----------
778 ----------
778 data : dict or list
779 data : dict or list
779 JSON data to display. Not an already-serialized JSON string.
780 JSON data to display. Not an already-serialized JSON string.
780 Scalar types (None, number, string) are not allowed, only dict
781 Scalar types (None, number, string) are not allowed, only dict
781 or list containers.
782 or list containers.
782 url : unicode
783 url : unicode
783 A URL to download the data from.
784 A URL to download the data from.
784 filename : unicode
785 filename : unicode
785 Path to a local file to load the data from.
786 Path to a local file to load the data from.
786 expanded : boolean
787 expanded : boolean
787 Metadata to control whether a JSON display component is expanded.
788 Metadata to control whether a JSON display component is expanded.
788 metadata: dict
789 metadata: dict
789 Specify extra metadata to attach to the json display object.
790 Specify extra metadata to attach to the json display object.
790 """
791 """
791 self.metadata = {'expanded': expanded}
792 self.metadata = {'expanded': expanded}
792 if metadata:
793 if metadata:
793 self.metadata.update(metadata)
794 self.metadata.update(metadata)
794 if kwargs:
795 if kwargs:
795 self.metadata.update(kwargs)
796 self.metadata.update(kwargs)
796 super(JSON, self).__init__(data=data, url=url, filename=filename)
797 super(JSON, self).__init__(data=data, url=url, filename=filename)
797
798
798 def _check_data(self):
799 def _check_data(self):
799 if self.data is not None and not isinstance(self.data, (dict, list)):
800 if self.data is not None and not isinstance(self.data, (dict, list)):
800 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
801 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
801
802
802 @property
803 @property
803 def data(self):
804 def data(self):
804 return self._data
805 return self._data
805
806
806 @data.setter
807 @data.setter
807 def data(self, data):
808 def data(self, data):
808 if isinstance(data, str):
809 if isinstance(data, str):
809 if getattr(self, 'filename', None) is None:
810 if getattr(self, 'filename', None) is None:
810 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
811 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
811 data = json.loads(data)
812 data = json.loads(data)
812 self._data = data
813 self._data = data
813
814
814 def _data_and_metadata(self):
815 def _data_and_metadata(self):
815 return self.data, self.metadata
816 return self.data, self.metadata
816
817
817 def _repr_json_(self):
818 def _repr_json_(self):
818 return self._data_and_metadata()
819 return self._data_and_metadata()
819
820
820 _css_t = """$("head").append($("<link/>").attr({
821 _css_t = """$("head").append($("<link/>").attr({
821 rel: "stylesheet",
822 rel: "stylesheet",
822 type: "text/css",
823 type: "text/css",
823 href: "%s"
824 href: "%s"
824 }));
825 }));
825 """
826 """
826
827
827 _lib_t1 = """$.getScript("%s", function () {
828 _lib_t1 = """$.getScript("%s", function () {
828 """
829 """
829 _lib_t2 = """});
830 _lib_t2 = """});
830 """
831 """
831
832
832 class GeoJSON(JSON):
833 class GeoJSON(JSON):
833 """GeoJSON expects JSON-able dict
834 """GeoJSON expects JSON-able dict
834
835
835 not an already-serialized JSON string.
836 not an already-serialized JSON string.
836
837
837 Scalar types (None, number, string) are not allowed, only dict containers.
838 Scalar types (None, number, string) are not allowed, only dict containers.
838 """
839 """
839
840
840 def __init__(self, *args, **kwargs):
841 def __init__(self, *args, **kwargs):
841 """Create a GeoJSON display object given raw data.
842 """Create a GeoJSON display object given raw data.
842
843
843 Parameters
844 Parameters
844 ----------
845 ----------
845 data : dict or list
846 data : dict or list
846 VegaLite data. Not an already-serialized JSON string.
847 VegaLite data. Not an already-serialized JSON string.
847 Scalar types (None, number, string) are not allowed, only dict
848 Scalar types (None, number, string) are not allowed, only dict
848 or list containers.
849 or list containers.
849 url_template : string
850 url_template : string
850 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
851 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
851 layer_options : dict
852 layer_options : dict
852 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
853 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
853 url : unicode
854 url : unicode
854 A URL to download the data from.
855 A URL to download the data from.
855 filename : unicode
856 filename : unicode
856 Path to a local file to load the data from.
857 Path to a local file to load the data from.
857 metadata: dict
858 metadata: dict
858 Specify extra metadata to attach to the json display object.
859 Specify extra metadata to attach to the json display object.
859
860
860 Examples
861 Examples
861 --------
862 --------
862
863
863 The following will display an interactive map of Mars with a point of
864 The following will display an interactive map of Mars with a point of
864 interest on frontend that do support GeoJSON display.
865 interest on frontend that do support GeoJSON display.
865
866
866 >>> from IPython.display import GeoJSON
867 >>> from IPython.display import GeoJSON
867
868
868 >>> GeoJSON(data={
869 >>> GeoJSON(data={
869 ... "type": "Feature",
870 ... "type": "Feature",
870 ... "geometry": {
871 ... "geometry": {
871 ... "type": "Point",
872 ... "type": "Point",
872 ... "coordinates": [-81.327, 296.038]
873 ... "coordinates": [-81.327, 296.038]
873 ... }
874 ... }
874 ... },
875 ... },
875 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
876 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
876 ... layer_options={
877 ... layer_options={
877 ... "basemap_id": "celestia_mars-shaded-16k_global",
878 ... "basemap_id": "celestia_mars-shaded-16k_global",
878 ... "attribution" : "Celestia/praesepe",
879 ... "attribution" : "Celestia/praesepe",
879 ... "minZoom" : 0,
880 ... "minZoom" : 0,
880 ... "maxZoom" : 18,
881 ... "maxZoom" : 18,
881 ... })
882 ... })
882 <IPython.core.display.GeoJSON object>
883 <IPython.core.display.GeoJSON object>
883
884
884 In the terminal IPython, you will only see the text representation of
885 In the terminal IPython, you will only see the text representation of
885 the GeoJSON object.
886 the GeoJSON object.
886
887
887 """
888 """
888
889
889 super(GeoJSON, self).__init__(*args, **kwargs)
890 super(GeoJSON, self).__init__(*args, **kwargs)
890
891
891
892
892 def _ipython_display_(self):
893 def _ipython_display_(self):
893 bundle = {
894 bundle = {
894 'application/geo+json': self.data,
895 'application/geo+json': self.data,
895 'text/plain': '<IPython.display.GeoJSON object>'
896 'text/plain': '<IPython.display.GeoJSON object>'
896 }
897 }
897 metadata = {
898 metadata = {
898 'application/geo+json': self.metadata
899 'application/geo+json': self.metadata
899 }
900 }
900 display(bundle, metadata=metadata, raw=True)
901 display(bundle, metadata=metadata, raw=True)
901
902
902 class Javascript(TextDisplayObject):
903 class Javascript(TextDisplayObject):
903
904
904 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
905 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
905 """Create a Javascript display object given raw data.
906 """Create a Javascript display object given raw data.
906
907
907 When this object is returned by an expression or passed to the
908 When this object is returned by an expression or passed to the
908 display function, it will result in the data being displayed
909 display function, it will result in the data being displayed
909 in the frontend. If the data is a URL, the data will first be
910 in the frontend. If the data is a URL, the data will first be
910 downloaded and then displayed.
911 downloaded and then displayed.
911
912
912 In the Notebook, the containing element will be available as `element`,
913 In the Notebook, the containing element will be available as `element`,
913 and jQuery will be available. Content appended to `element` will be
914 and jQuery will be available. Content appended to `element` will be
914 visible in the output area.
915 visible in the output area.
915
916
916 Parameters
917 Parameters
917 ----------
918 ----------
918 data : unicode, str or bytes
919 data : unicode, str or bytes
919 The Javascript source code or a URL to download it from.
920 The Javascript source code or a URL to download it from.
920 url : unicode
921 url : unicode
921 A URL to download the data from.
922 A URL to download the data from.
922 filename : unicode
923 filename : unicode
923 Path to a local file to load the data from.
924 Path to a local file to load the data from.
924 lib : list or str
925 lib : list or str
925 A sequence of Javascript library URLs to load asynchronously before
926 A sequence of Javascript library URLs to load asynchronously before
926 running the source code. The full URLs of the libraries should
927 running the source code. The full URLs of the libraries should
927 be given. A single Javascript library URL can also be given as a
928 be given. A single Javascript library URL can also be given as a
928 string.
929 string.
929 css: : list or str
930 css: : list or str
930 A sequence of css files to load before running the source code.
931 A sequence of css files to load before running the source code.
931 The full URLs of the css files should be given. A single css URL
932 The full URLs of the css files should be given. A single css URL
932 can also be given as a string.
933 can also be given as a string.
933 """
934 """
934 if isinstance(lib, str):
935 if isinstance(lib, str):
935 lib = [lib]
936 lib = [lib]
936 elif lib is None:
937 elif lib is None:
937 lib = []
938 lib = []
938 if isinstance(css, str):
939 if isinstance(css, str):
939 css = [css]
940 css = [css]
940 elif css is None:
941 elif css is None:
941 css = []
942 css = []
942 if not isinstance(lib, (list,tuple)):
943 if not isinstance(lib, (list,tuple)):
943 raise TypeError('expected sequence, got: %r' % lib)
944 raise TypeError('expected sequence, got: %r' % lib)
944 if not isinstance(css, (list,tuple)):
945 if not isinstance(css, (list,tuple)):
945 raise TypeError('expected sequence, got: %r' % css)
946 raise TypeError('expected sequence, got: %r' % css)
946 self.lib = lib
947 self.lib = lib
947 self.css = css
948 self.css = css
948 super(Javascript, self).__init__(data=data, url=url, filename=filename)
949 super(Javascript, self).__init__(data=data, url=url, filename=filename)
949
950
950 def _repr_javascript_(self):
951 def _repr_javascript_(self):
951 r = ''
952 r = ''
952 for c in self.css:
953 for c in self.css:
953 r += _css_t % c
954 r += _css_t % c
954 for l in self.lib:
955 for l in self.lib:
955 r += _lib_t1 % l
956 r += _lib_t1 % l
956 r += self.data
957 r += self.data
957 r += _lib_t2*len(self.lib)
958 r += _lib_t2*len(self.lib)
958 return r
959 return r
959
960
960 # constants for identifying png/jpeg data
961 # constants for identifying png/jpeg data
961 _PNG = b'\x89PNG\r\n\x1a\n'
962 _PNG = b'\x89PNG\r\n\x1a\n'
962 _JPEG = b'\xff\xd8'
963 _JPEG = b'\xff\xd8'
963
964
964 def _pngxy(data):
965 def _pngxy(data):
965 """read the (width, height) from a PNG header"""
966 """read the (width, height) from a PNG header"""
966 ihdr = data.index(b'IHDR')
967 ihdr = data.index(b'IHDR')
967 # next 8 bytes are width/height
968 # next 8 bytes are width/height
968 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
969 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
969
970
970 def _jpegxy(data):
971 def _jpegxy(data):
971 """read the (width, height) from a JPEG header"""
972 """read the (width, height) from a JPEG header"""
972 # adapted from http://www.64lines.com/jpeg-width-height
973 # adapted from http://www.64lines.com/jpeg-width-height
973
974
974 idx = 4
975 idx = 4
975 while True:
976 while True:
976 block_size = struct.unpack('>H', data[idx:idx+2])[0]
977 block_size = struct.unpack('>H', data[idx:idx+2])[0]
977 idx = idx + block_size
978 idx = idx + block_size
978 if data[idx:idx+2] == b'\xFF\xC0':
979 if data[idx:idx+2] == b'\xFF\xC0':
979 # found Start of Frame
980 # found Start of Frame
980 iSOF = idx
981 iSOF = idx
981 break
982 break
982 else:
983 else:
983 # read another block
984 # read another block
984 idx += 2
985 idx += 2
985
986
986 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
987 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
987 return w, h
988 return w, h
988
989
989 def _gifxy(data):
990 def _gifxy(data):
990 """read the (width, height) from a GIF header"""
991 """read the (width, height) from a GIF header"""
991 return struct.unpack('<HH', data[6:10])
992 return struct.unpack('<HH', data[6:10])
992
993
993
994
994 class Image(DisplayObject):
995 class Image(DisplayObject):
995
996
996 _read_flags = 'rb'
997 _read_flags = 'rb'
997 _FMT_JPEG = u'jpeg'
998 _FMT_JPEG = u'jpeg'
998 _FMT_PNG = u'png'
999 _FMT_PNG = u'png'
999 _FMT_GIF = u'gif'
1000 _FMT_GIF = u'gif'
1000 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1001 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1001 _MIMETYPES = {
1002 _MIMETYPES = {
1002 _FMT_PNG: 'image/png',
1003 _FMT_PNG: 'image/png',
1003 _FMT_JPEG: 'image/jpeg',
1004 _FMT_JPEG: 'image/jpeg',
1004 _FMT_GIF: 'image/gif',
1005 _FMT_GIF: 'image/gif',
1005 }
1006 }
1006
1007
1007 def __init__(self, data=None, url=None, filename=None, format=None,
1008 def __init__(self, data=None, url=None, filename=None, format=None,
1008 embed=None, width=None, height=None, retina=False,
1009 embed=None, width=None, height=None, retina=False,
1009 unconfined=False, metadata=None):
1010 unconfined=False, metadata=None):
1010 """Create a PNG/JPEG/GIF image object given raw data.
1011 """Create a PNG/JPEG/GIF image object given raw data.
1011
1012
1012 When this object is returned by an input cell or passed to the
1013 When this object is returned by an input cell or passed to the
1013 display function, it will result in the image being displayed
1014 display function, it will result in the image being displayed
1014 in the frontend.
1015 in the frontend.
1015
1016
1016 Parameters
1017 Parameters
1017 ----------
1018 ----------
1018 data : unicode, str or bytes
1019 data : unicode, str or bytes
1019 The raw image data or a URL or filename to load the data from.
1020 The raw image data or a URL or filename to load the data from.
1020 This always results in embedded image data.
1021 This always results in embedded image data.
1021 url : unicode
1022 url : unicode
1022 A URL to download the data from. If you specify `url=`,
1023 A URL to download the data from. If you specify `url=`,
1023 the image data will not be embedded unless you also specify `embed=True`.
1024 the image data will not be embedded unless you also specify `embed=True`.
1024 filename : unicode
1025 filename : unicode
1025 Path to a local file to load the data from.
1026 Path to a local file to load the data from.
1026 Images from a file are always embedded.
1027 Images from a file are always embedded.
1027 format : unicode
1028 format : unicode
1028 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
1029 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
1029 for format will be inferred from the filename extension.
1030 for format will be inferred from the filename extension.
1030 embed : bool
1031 embed : bool
1031 Should the image data be embedded using a data URI (True) or be
1032 Should the image data be embedded using a data URI (True) or be
1032 loaded using an <img> tag. Set this to True if you want the image
1033 loaded using an <img> tag. Set this to True if you want the image
1033 to be viewable later with no internet connection in the notebook.
1034 to be viewable later with no internet connection in the notebook.
1034
1035
1035 Default is `True`, unless the keyword argument `url` is set, then
1036 Default is `True`, unless the keyword argument `url` is set, then
1036 default value is `False`.
1037 default value is `False`.
1037
1038
1038 Note that QtConsole is not able to display images if `embed` is set to `False`
1039 Note that QtConsole is not able to display images if `embed` is set to `False`
1039 width : int
1040 width : int
1040 Width in pixels to which to constrain the image in html
1041 Width in pixels to which to constrain the image in html
1041 height : int
1042 height : int
1042 Height in pixels to which to constrain the image in html
1043 Height in pixels to which to constrain the image in html
1043 retina : bool
1044 retina : bool
1044 Automatically set the width and height to half of the measured
1045 Automatically set the width and height to half of the measured
1045 width and height.
1046 width and height.
1046 This only works for embedded images because it reads the width/height
1047 This only works for embedded images because it reads the width/height
1047 from image data.
1048 from image data.
1048 For non-embedded images, you can just set the desired display width
1049 For non-embedded images, you can just set the desired display width
1049 and height directly.
1050 and height directly.
1050 unconfined: bool
1051 unconfined: bool
1051 Set unconfined=True to disable max-width confinement of the image.
1052 Set unconfined=True to disable max-width confinement of the image.
1052 metadata: dict
1053 metadata: dict
1053 Specify extra metadata to attach to the image.
1054 Specify extra metadata to attach to the image.
1054
1055
1055 Examples
1056 Examples
1056 --------
1057 --------
1057 # embedded image data, works in qtconsole and notebook
1058 # embedded image data, works in qtconsole and notebook
1058 # when passed positionally, the first arg can be any of raw image data,
1059 # when passed positionally, the first arg can be any of raw image data,
1059 # a URL, or a filename from which to load image data.
1060 # a URL, or a filename from which to load image data.
1060 # The result is always embedding image data for inline images.
1061 # The result is always embedding image data for inline images.
1061 Image('http://www.google.fr/images/srpr/logo3w.png')
1062 Image('http://www.google.fr/images/srpr/logo3w.png')
1062 Image('/path/to/image.jpg')
1063 Image('/path/to/image.jpg')
1063 Image(b'RAW_PNG_DATA...')
1064 Image(b'RAW_PNG_DATA...')
1064
1065
1065 # Specifying Image(url=...) does not embed the image data,
1066 # Specifying Image(url=...) does not embed the image data,
1066 # it only generates `<img>` tag with a link to the source.
1067 # it only generates `<img>` tag with a link to the source.
1067 # This will not work in the qtconsole or offline.
1068 # This will not work in the qtconsole or offline.
1068 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1069 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1069
1070
1070 """
1071 """
1071 if filename is not None:
1072 if filename is not None:
1072 ext = self._find_ext(filename)
1073 ext = self._find_ext(filename)
1073 elif url is not None:
1074 elif url is not None:
1074 ext = self._find_ext(url)
1075 ext = self._find_ext(url)
1075 elif data is None:
1076 elif data is None:
1076 raise ValueError("No image data found. Expecting filename, url, or data.")
1077 raise ValueError("No image data found. Expecting filename, url, or data.")
1077 elif isinstance(data, str) and (
1078 elif isinstance(data, str) and (
1078 data.startswith('http') or _safe_exists(data)
1079 data.startswith('http') or _safe_exists(data)
1079 ):
1080 ):
1080 ext = self._find_ext(data)
1081 ext = self._find_ext(data)
1081 else:
1082 else:
1082 ext = None
1083 ext = None
1083
1084
1084 if format is None:
1085 if format is None:
1085 if ext is not None:
1086 if ext is not None:
1086 if ext == u'jpg' or ext == u'jpeg':
1087 if ext == u'jpg' or ext == u'jpeg':
1087 format = self._FMT_JPEG
1088 format = self._FMT_JPEG
1088 if ext == u'png':
1089 if ext == u'png':
1089 format = self._FMT_PNG
1090 format = self._FMT_PNG
1090 if ext == u'gif':
1091 if ext == u'gif':
1091 format = self._FMT_GIF
1092 format = self._FMT_GIF
1092 else:
1093 else:
1093 format = ext.lower()
1094 format = ext.lower()
1094 elif isinstance(data, bytes):
1095 elif isinstance(data, bytes):
1095 # infer image type from image data header,
1096 # infer image type from image data header,
1096 # only if format has not been specified.
1097 # only if format has not been specified.
1097 if data[:2] == _JPEG:
1098 if data[:2] == _JPEG:
1098 format = self._FMT_JPEG
1099 format = self._FMT_JPEG
1099
1100
1100 # failed to detect format, default png
1101 # failed to detect format, default png
1101 if format is None:
1102 if format is None:
1102 format = self._FMT_PNG
1103 format = self._FMT_PNG
1103
1104
1104 if format.lower() == 'jpg':
1105 if format.lower() == 'jpg':
1105 # jpg->jpeg
1106 # jpg->jpeg
1106 format = self._FMT_JPEG
1107 format = self._FMT_JPEG
1107
1108
1108 self.format = format.lower()
1109 self.format = format.lower()
1109 self.embed = embed if embed is not None else (url is None)
1110 self.embed = embed if embed is not None else (url is None)
1110
1111
1111 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1112 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1112 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1113 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1113 if self.embed:
1114 if self.embed:
1114 self._mimetype = self._MIMETYPES.get(self.format)
1115 self._mimetype = self._MIMETYPES.get(self.format)
1115
1116
1116 self.width = width
1117 self.width = width
1117 self.height = height
1118 self.height = height
1118 self.retina = retina
1119 self.retina = retina
1119 self.unconfined = unconfined
1120 self.unconfined = unconfined
1120 super(Image, self).__init__(data=data, url=url, filename=filename,
1121 super(Image, self).__init__(data=data, url=url, filename=filename,
1121 metadata=metadata)
1122 metadata=metadata)
1122
1123
1123 if self.width is None and self.metadata.get('width', {}):
1124 if self.width is None and self.metadata.get('width', {}):
1124 self.width = metadata['width']
1125 self.width = metadata['width']
1125
1126
1126 if self.height is None and self.metadata.get('height', {}):
1127 if self.height is None and self.metadata.get('height', {}):
1127 self.height = metadata['height']
1128 self.height = metadata['height']
1128
1129
1129 if retina:
1130 if retina:
1130 self._retina_shape()
1131 self._retina_shape()
1131
1132
1132
1133
1133 def _retina_shape(self):
1134 def _retina_shape(self):
1134 """load pixel-doubled width and height from image data"""
1135 """load pixel-doubled width and height from image data"""
1135 if not self.embed:
1136 if not self.embed:
1136 return
1137 return
1137 if self.format == self._FMT_PNG:
1138 if self.format == self._FMT_PNG:
1138 w, h = _pngxy(self.data)
1139 w, h = _pngxy(self.data)
1139 elif self.format == self._FMT_JPEG:
1140 elif self.format == self._FMT_JPEG:
1140 w, h = _jpegxy(self.data)
1141 w, h = _jpegxy(self.data)
1141 elif self.format == self._FMT_GIF:
1142 elif self.format == self._FMT_GIF:
1142 w, h = _gifxy(self.data)
1143 w, h = _gifxy(self.data)
1143 else:
1144 else:
1144 # retina only supports png
1145 # retina only supports png
1145 return
1146 return
1146 self.width = w // 2
1147 self.width = w // 2
1147 self.height = h // 2
1148 self.height = h // 2
1148
1149
1149 def reload(self):
1150 def reload(self):
1150 """Reload the raw data from file or URL."""
1151 """Reload the raw data from file or URL."""
1151 if self.embed:
1152 if self.embed:
1152 super(Image,self).reload()
1153 super(Image,self).reload()
1153 if self.retina:
1154 if self.retina:
1154 self._retina_shape()
1155 self._retina_shape()
1155
1156
1156 def _repr_html_(self):
1157 def _repr_html_(self):
1157 if not self.embed:
1158 if not self.embed:
1158 width = height = klass = ''
1159 width = height = klass = ''
1159 if self.width:
1160 if self.width:
1160 width = ' width="%d"' % self.width
1161 width = ' width="%d"' % self.width
1161 if self.height:
1162 if self.height:
1162 height = ' height="%d"' % self.height
1163 height = ' height="%d"' % self.height
1163 if self.unconfined:
1164 if self.unconfined:
1164 klass = ' class="unconfined"'
1165 klass = ' class="unconfined"'
1165 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1166 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1166 url=self.url,
1167 url=self.url,
1167 width=width,
1168 width=width,
1168 height=height,
1169 height=height,
1169 klass=klass,
1170 klass=klass,
1170 )
1171 )
1171
1172
1172 def _repr_mimebundle_(self, include=None, exclude=None):
1173 def _repr_mimebundle_(self, include=None, exclude=None):
1173 """Return the image as a mimebundle
1174 """Return the image as a mimebundle
1174
1175
1175 Any new mimetype support should be implemented here.
1176 Any new mimetype support should be implemented here.
1176 """
1177 """
1177 if self.embed:
1178 if self.embed:
1178 mimetype = self._mimetype
1179 mimetype = self._mimetype
1179 data, metadata = self._data_and_metadata(always_both=True)
1180 data, metadata = self._data_and_metadata(always_both=True)
1180 if metadata:
1181 if metadata:
1181 metadata = {mimetype: metadata}
1182 metadata = {mimetype: metadata}
1182 return {mimetype: data}, metadata
1183 return {mimetype: data}, metadata
1183 else:
1184 else:
1184 return {'text/html': self._repr_html_()}
1185 return {'text/html': self._repr_html_()}
1185
1186
1186 def _data_and_metadata(self, always_both=False):
1187 def _data_and_metadata(self, always_both=False):
1187 """shortcut for returning metadata with shape information, if defined"""
1188 """shortcut for returning metadata with shape information, if defined"""
1188 b64_data = b2a_base64(self.data).decode('ascii')
1189 b64_data = b2a_base64(self.data).decode('ascii')
1189 md = {}
1190 md = {}
1190 if self.metadata:
1191 if self.metadata:
1191 md.update(self.metadata)
1192 md.update(self.metadata)
1192 if self.width:
1193 if self.width:
1193 md['width'] = self.width
1194 md['width'] = self.width
1194 if self.height:
1195 if self.height:
1195 md['height'] = self.height
1196 md['height'] = self.height
1196 if self.unconfined:
1197 if self.unconfined:
1197 md['unconfined'] = self.unconfined
1198 md['unconfined'] = self.unconfined
1198 if md or always_both:
1199 if md or always_both:
1199 return b64_data, md
1200 return b64_data, md
1200 else:
1201 else:
1201 return b64_data
1202 return b64_data
1202
1203
1203 def _repr_png_(self):
1204 def _repr_png_(self):
1204 if self.embed and self.format == self._FMT_PNG:
1205 if self.embed and self.format == self._FMT_PNG:
1205 return self._data_and_metadata()
1206 return self._data_and_metadata()
1206
1207
1207 def _repr_jpeg_(self):
1208 def _repr_jpeg_(self):
1208 if self.embed and self.format == self._FMT_JPEG:
1209 if self.embed and self.format == self._FMT_JPEG:
1209 return self._data_and_metadata()
1210 return self._data_and_metadata()
1210
1211
1211 def _find_ext(self, s):
1212 def _find_ext(self, s):
1212 return s.split('.')[-1].lower()
1213 return s.split('.')[-1].lower()
1213
1214
1214
1215
1215 class Video(DisplayObject):
1216 class Video(DisplayObject):
1216
1217
1217 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
1218 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
1218 """Create a video object given raw data or an URL.
1219 """Create a video object given raw data or an URL.
1219
1220
1220 When this object is returned by an input cell or passed to the
1221 When this object is returned by an input cell or passed to the
1221 display function, it will result in the video being displayed
1222 display function, it will result in the video being displayed
1222 in the frontend.
1223 in the frontend.
1223
1224
1224 Parameters
1225 Parameters
1225 ----------
1226 ----------
1226 data : unicode, str or bytes
1227 data : unicode, str or bytes
1227 The raw video data or a URL or filename to load the data from.
1228 The raw video data or a URL or filename to load the data from.
1228 Raw data will require passing `embed=True`.
1229 Raw data will require passing `embed=True`.
1229 url : unicode
1230 url : unicode
1230 A URL for the video. If you specify `url=`,
1231 A URL for the video. If you specify `url=`,
1231 the image data will not be embedded.
1232 the image data will not be embedded.
1232 filename : unicode
1233 filename : unicode
1233 Path to a local file containing the video.
1234 Path to a local file containing the video.
1234 Will be interpreted as a local URL unless `embed=True`.
1235 Will be interpreted as a local URL unless `embed=True`.
1235 embed : bool
1236 embed : bool
1236 Should the video be embedded using a data URI (True) or be
1237 Should the video be embedded using a data URI (True) or be
1237 loaded using a <video> tag (False).
1238 loaded using a <video> tag (False).
1238
1239
1239 Since videos are large, embedding them should be avoided, if possible.
1240 Since videos are large, embedding them should be avoided, if possible.
1240 You must confirm embedding as your intention by passing `embed=True`.
1241 You must confirm embedding as your intention by passing `embed=True`.
1241
1242
1242 Local files can be displayed with URLs without embedding the content, via::
1243 Local files can be displayed with URLs without embedding the content, via::
1243
1244
1244 Video('./video.mp4')
1245 Video('./video.mp4')
1245
1246
1246 mimetype: unicode
1247 mimetype: unicode
1247 Specify the mimetype for embedded videos.
1248 Specify the mimetype for embedded videos.
1248 Default will be guessed from file extension, if available.
1249 Default will be guessed from file extension, if available.
1249
1250
1250 Examples
1251 Examples
1251 --------
1252 --------
1252
1253
1253 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1254 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1254 Video('path/to/video.mp4')
1255 Video('path/to/video.mp4')
1255 Video('path/to/video.mp4', embed=True)
1256 Video('path/to/video.mp4', embed=True)
1256 Video(b'raw-videodata', embed=True)
1257 Video(b'raw-videodata', embed=True)
1257 """
1258 """
1258 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1259 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1259 url = data
1260 url = data
1260 data = None
1261 data = None
1261 elif os.path.exists(data):
1262 elif os.path.exists(data):
1262 filename = data
1263 filename = data
1263 data = None
1264 data = None
1264
1265
1265 if data and not embed:
1266 if data and not embed:
1266 msg = ''.join([
1267 msg = ''.join([
1267 "To embed videos, you must pass embed=True ",
1268 "To embed videos, you must pass embed=True ",
1268 "(this may make your notebook files huge)\n",
1269 "(this may make your notebook files huge)\n",
1269 "Consider passing Video(url='...')",
1270 "Consider passing Video(url='...')",
1270 ])
1271 ])
1271 raise ValueError(msg)
1272 raise ValueError(msg)
1272
1273
1273 self.mimetype = mimetype
1274 self.mimetype = mimetype
1274 self.embed = embed
1275 self.embed = embed
1275 super(Video, self).__init__(data=data, url=url, filename=filename)
1276 super(Video, self).__init__(data=data, url=url, filename=filename)
1276
1277
1277 def _repr_html_(self):
1278 def _repr_html_(self):
1278 # External URLs and potentially local files are not embedded into the
1279 # External URLs and potentially local files are not embedded into the
1279 # notebook output.
1280 # notebook output.
1280 if not self.embed:
1281 if not self.embed:
1281 url = self.url if self.url is not None else self.filename
1282 url = self.url if self.url is not None else self.filename
1282 output = """<video src="{0}" controls>
1283 output = """<video src="{0}" controls>
1283 Your browser does not support the <code>video</code> element.
1284 Your browser does not support the <code>video</code> element.
1284 </video>""".format(url)
1285 </video>""".format(url)
1285 return output
1286 return output
1286
1287
1287 # Embedded videos are base64-encoded.
1288 # Embedded videos are base64-encoded.
1288 mimetype = self.mimetype
1289 mimetype = self.mimetype
1289 if self.filename is not None:
1290 if self.filename is not None:
1290 if not mimetype:
1291 if not mimetype:
1291 mimetype, _ = mimetypes.guess_type(self.filename)
1292 mimetype, _ = mimetypes.guess_type(self.filename)
1292
1293
1293 with open(self.filename, 'rb') as f:
1294 with open(self.filename, 'rb') as f:
1294 video = f.read()
1295 video = f.read()
1295 else:
1296 else:
1296 video = self.data
1297 video = self.data
1297 if isinstance(video, str):
1298 if isinstance(video, str):
1298 # unicode input is already b64-encoded
1299 # unicode input is already b64-encoded
1299 b64_video = video
1300 b64_video = video
1300 else:
1301 else:
1301 b64_video = b2a_base64(video).decode('ascii').rstrip()
1302 b64_video = b2a_base64(video).decode('ascii').rstrip()
1302
1303
1303 output = """<video controls>
1304 output = """<video controls>
1304 <source src="data:{0};base64,{1}" type="{0}">
1305 <source src="data:{0};base64,{1}" type="{0}">
1305 Your browser does not support the video tag.
1306 Your browser does not support the video tag.
1306 </video>""".format(mimetype, b64_video)
1307 </video>""".format(mimetype, b64_video)
1307 return output
1308 return output
1308
1309
1309 def reload(self):
1310 def reload(self):
1310 # TODO
1311 # TODO
1311 pass
1312 pass
1312
1313
1313
1314
1314 def clear_output(wait=False):
1315 def clear_output(wait=False):
1315 """Clear the output of the current cell receiving output.
1316 """Clear the output of the current cell receiving output.
1316
1317
1317 Parameters
1318 Parameters
1318 ----------
1319 ----------
1319 wait : bool [default: false]
1320 wait : bool [default: false]
1320 Wait to clear the output until new output is available to replace it."""
1321 Wait to clear the output until new output is available to replace it."""
1321 from IPython.core.interactiveshell import InteractiveShell
1322 from IPython.core.interactiveshell import InteractiveShell
1322 if InteractiveShell.initialized():
1323 if InteractiveShell.initialized():
1323 InteractiveShell.instance().display_pub.clear_output(wait)
1324 InteractiveShell.instance().display_pub.clear_output(wait)
1324 else:
1325 else:
1325 print('\033[2K\r', end='')
1326 print('\033[2K\r', end='')
1326 sys.stdout.flush()
1327 sys.stdout.flush()
1327 print('\033[2K\r', end='')
1328 print('\033[2K\r', end='')
1328 sys.stderr.flush()
1329 sys.stderr.flush()
1329
1330
1330
1331
1331 @skip_doctest
1332 @skip_doctest
1332 def set_matplotlib_formats(*formats, **kwargs):
1333 def set_matplotlib_formats(*formats, **kwargs):
1333 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1334 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1334
1335
1335 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1336 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1336
1337
1337 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1338 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1338
1339
1339 To set this in your config files use the following::
1340 To set this in your config files use the following::
1340
1341
1341 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1342 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1342 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1343 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1343
1344
1344 Parameters
1345 Parameters
1345 ----------
1346 ----------
1346 *formats : strs
1347 *formats : strs
1347 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1348 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1348 **kwargs :
1349 **kwargs :
1349 Keyword args will be relayed to ``figure.canvas.print_figure``.
1350 Keyword args will be relayed to ``figure.canvas.print_figure``.
1350 """
1351 """
1351 from IPython.core.interactiveshell import InteractiveShell
1352 from IPython.core.interactiveshell import InteractiveShell
1352 from IPython.core.pylabtools import select_figure_formats
1353 from IPython.core.pylabtools import select_figure_formats
1353 # build kwargs, starting with InlineBackend config
1354 # build kwargs, starting with InlineBackend config
1354 kw = {}
1355 kw = {}
1355 from ipykernel.pylab.config import InlineBackend
1356 from ipykernel.pylab.config import InlineBackend
1356 cfg = InlineBackend.instance()
1357 cfg = InlineBackend.instance()
1357 kw.update(cfg.print_figure_kwargs)
1358 kw.update(cfg.print_figure_kwargs)
1358 kw.update(**kwargs)
1359 kw.update(**kwargs)
1359 shell = InteractiveShell.instance()
1360 shell = InteractiveShell.instance()
1360 select_figure_formats(shell, formats, **kw)
1361 select_figure_formats(shell, formats, **kw)
1361
1362
1362 @skip_doctest
1363 @skip_doctest
1363 def set_matplotlib_close(close=True):
1364 def set_matplotlib_close(close=True):
1364 """Set whether the inline backend closes all figures automatically or not.
1365 """Set whether the inline backend closes all figures automatically or not.
1365
1366
1366 By default, the inline backend used in the IPython Notebook will close all
1367 By default, the inline backend used in the IPython Notebook will close all
1367 matplotlib figures automatically after each cell is run. This means that
1368 matplotlib figures automatically after each cell is run. This means that
1368 plots in different cells won't interfere. Sometimes, you may want to make
1369 plots in different cells won't interfere. Sometimes, you may want to make
1369 a plot in one cell and then refine it in later cells. This can be accomplished
1370 a plot in one cell and then refine it in later cells. This can be accomplished
1370 by::
1371 by::
1371
1372
1372 In [1]: set_matplotlib_close(False)
1373 In [1]: set_matplotlib_close(False)
1373
1374
1374 To set this in your config files use the following::
1375 To set this in your config files use the following::
1375
1376
1376 c.InlineBackend.close_figures = False
1377 c.InlineBackend.close_figures = False
1377
1378
1378 Parameters
1379 Parameters
1379 ----------
1380 ----------
1380 close : bool
1381 close : bool
1381 Should all matplotlib figures be automatically closed after each cell is
1382 Should all matplotlib figures be automatically closed after each cell is
1382 run?
1383 run?
1383 """
1384 """
1384 from ipykernel.pylab.config import InlineBackend
1385 from ipykernel.pylab.config import InlineBackend
1385 cfg = InlineBackend.instance()
1386 cfg = InlineBackend.instance()
1386 cfg.close_figures = close
1387 cfg.close_figures = close
General Comments 0
You need to be logged in to leave comments. Login now