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