##// END OF EJS Templates
fix parent class
Marius van Niekerk -
Show More
@@ -1,1386 +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, 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', '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):
731 class ProgressBar(DisplayObject):
732 """Progressbar supports displaying a progressbar like element
732 """Progressbar supports displaying a progressbar like element
733 """
733 """
734 def __init__(self, total):
734 def __init__(self, total):
735 """Creates a new progressbar
735 """Creates a new progressbar
736
736
737 Parameters
737 Parameters
738 ----------
738 ----------
739 total : int
739 total : int
740 maximnum size of the progressbar
740 maximnum size of the progressbar
741 """
741 """
742 self._display_id = hexlify(os.urandom(8)).decode('ascii')
742 self._display_id = hexlify(os.urandom(8)).decode('ascii')
743 self.total = total
743 self.total = total
744 self._progress = 0
744 self._progress = 0
745
745
746 def _repr_html_(self):
746 def _repr_html_(self):
747 return "<progress style='width:100%' max='{}' value='{}'></progress>".format(self.total, self.progress)
747 return "<progress style='width:100%' max='{}' value='{}'></progress>".format(self.total, self.progress)
748
748
749 def display(self):
749 def display(self):
750 display(self, display_id=self._display_id)
750 display(self, display_id=self._display_id)
751
751
752 def update(self):
752 def update(self):
753 display(self, display_id=self._display_id, update=True)
753 display(self, display_id=self._display_id, update=True)
754
754
755 @property
755 @property
756 def progress(self):
756 def progress(self):
757 return self._progress
757 return self._progress
758
758
759 @progress.setter
759 @progress.setter
760 def progress(self, value):
760 def progress(self, value):
761 self._progress = value
761 self._progress = value
762 self.update()
762 self.update()
763
763
764 class JSON(DisplayObject):
764 class JSON(DisplayObject):
765 """JSON expects a JSON-able dict or list
765 """JSON expects a JSON-able dict or list
766
766
767 not an already-serialized JSON string.
767 not an already-serialized JSON string.
768
768
769 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.
770 """
770 """
771 # 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
772 _data = None
772 _data = None
773 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):
774 """Create a JSON display object given raw data.
774 """Create a JSON display object given raw data.
775
775
776 Parameters
776 Parameters
777 ----------
777 ----------
778 data : dict or list
778 data : dict or list
779 JSON data to display. Not an already-serialized JSON string.
779 JSON data to display. Not an already-serialized JSON string.
780 Scalar types (None, number, string) are not allowed, only dict
780 Scalar types (None, number, string) are not allowed, only dict
781 or list containers.
781 or list containers.
782 url : unicode
782 url : unicode
783 A URL to download the data from.
783 A URL to download the data from.
784 filename : unicode
784 filename : unicode
785 Path to a local file to load the data from.
785 Path to a local file to load the data from.
786 expanded : boolean
786 expanded : boolean
787 Metadata to control whether a JSON display component is expanded.
787 Metadata to control whether a JSON display component is expanded.
788 metadata: dict
788 metadata: dict
789 Specify extra metadata to attach to the json display object.
789 Specify extra metadata to attach to the json display object.
790 """
790 """
791 self.metadata = {'expanded': expanded}
791 self.metadata = {'expanded': expanded}
792 if metadata:
792 if metadata:
793 self.metadata.update(metadata)
793 self.metadata.update(metadata)
794 if kwargs:
794 if kwargs:
795 self.metadata.update(kwargs)
795 self.metadata.update(kwargs)
796 super(JSON, self).__init__(data=data, url=url, filename=filename)
796 super(JSON, self).__init__(data=data, url=url, filename=filename)
797
797
798 def _check_data(self):
798 def _check_data(self):
799 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)):
800 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))
801
801
802 @property
802 @property
803 def data(self):
803 def data(self):
804 return self._data
804 return self._data
805
805
806 @data.setter
806 @data.setter
807 def data(self, data):
807 def data(self, data):
808 if isinstance(data, str):
808 if isinstance(data, str):
809 if getattr(self, 'filename', None) is None:
809 if getattr(self, 'filename', None) is None:
810 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
810 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
811 data = json.loads(data)
811 data = json.loads(data)
812 self._data = data
812 self._data = data
813
813
814 def _data_and_metadata(self):
814 def _data_and_metadata(self):
815 return self.data, self.metadata
815 return self.data, self.metadata
816
816
817 def _repr_json_(self):
817 def _repr_json_(self):
818 return self._data_and_metadata()
818 return self._data_and_metadata()
819
819
820 _css_t = """$("head").append($("<link/>").attr({
820 _css_t = """$("head").append($("<link/>").attr({
821 rel: "stylesheet",
821 rel: "stylesheet",
822 type: "text/css",
822 type: "text/css",
823 href: "%s"
823 href: "%s"
824 }));
824 }));
825 """
825 """
826
826
827 _lib_t1 = """$.getScript("%s", function () {
827 _lib_t1 = """$.getScript("%s", function () {
828 """
828 """
829 _lib_t2 = """});
829 _lib_t2 = """});
830 """
830 """
831
831
832 class GeoJSON(JSON):
832 class GeoJSON(JSON):
833 """GeoJSON expects JSON-able dict
833 """GeoJSON expects JSON-able dict
834
834
835 not an already-serialized JSON string.
835 not an already-serialized JSON string.
836
836
837 Scalar types (None, number, string) are not allowed, only dict containers.
837 Scalar types (None, number, string) are not allowed, only dict containers.
838 """
838 """
839
839
840 def __init__(self, *args, **kwargs):
840 def __init__(self, *args, **kwargs):
841 """Create a GeoJSON display object given raw data.
841 """Create a GeoJSON display object given raw data.
842
842
843 Parameters
843 Parameters
844 ----------
844 ----------
845 data : dict or list
845 data : dict or list
846 VegaLite data. Not an already-serialized JSON string.
846 VegaLite data. Not an already-serialized JSON string.
847 Scalar types (None, number, string) are not allowed, only dict
847 Scalar types (None, number, string) are not allowed, only dict
848 or list containers.
848 or list containers.
849 url_template : string
849 url_template : string
850 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
850 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
851 layer_options : dict
851 layer_options : dict
852 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
852 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
853 url : unicode
853 url : unicode
854 A URL to download the data from.
854 A URL to download the data from.
855 filename : unicode
855 filename : unicode
856 Path to a local file to load the data from.
856 Path to a local file to load the data from.
857 metadata: dict
857 metadata: dict
858 Specify extra metadata to attach to the json display object.
858 Specify extra metadata to attach to the json display object.
859
859
860 Examples
860 Examples
861 --------
861 --------
862
862
863 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
864 interest on frontend that do support GeoJSON display.
864 interest on frontend that do support GeoJSON display.
865
865
866 >>> from IPython.display import GeoJSON
866 >>> from IPython.display import GeoJSON
867
867
868 >>> GeoJSON(data={
868 >>> GeoJSON(data={
869 ... "type": "Feature",
869 ... "type": "Feature",
870 ... "geometry": {
870 ... "geometry": {
871 ... "type": "Point",
871 ... "type": "Point",
872 ... "coordinates": [-81.327, 296.038]
872 ... "coordinates": [-81.327, 296.038]
873 ... }
873 ... }
874 ... },
874 ... },
875 ... 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",
876 ... layer_options={
876 ... layer_options={
877 ... "basemap_id": "celestia_mars-shaded-16k_global",
877 ... "basemap_id": "celestia_mars-shaded-16k_global",
878 ... "attribution" : "Celestia/praesepe",
878 ... "attribution" : "Celestia/praesepe",
879 ... "minZoom" : 0,
879 ... "minZoom" : 0,
880 ... "maxZoom" : 18,
880 ... "maxZoom" : 18,
881 ... })
881 ... })
882 <IPython.core.display.GeoJSON object>
882 <IPython.core.display.GeoJSON object>
883
883
884 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
885 the GeoJSON object.
885 the GeoJSON object.
886
886
887 """
887 """
888
888
889 super(GeoJSON, self).__init__(*args, **kwargs)
889 super(GeoJSON, self).__init__(*args, **kwargs)
890
890
891
891
892 def _ipython_display_(self):
892 def _ipython_display_(self):
893 bundle = {
893 bundle = {
894 'application/geo+json': self.data,
894 'application/geo+json': self.data,
895 'text/plain': '<IPython.display.GeoJSON object>'
895 'text/plain': '<IPython.display.GeoJSON object>'
896 }
896 }
897 metadata = {
897 metadata = {
898 'application/geo+json': self.metadata
898 'application/geo+json': self.metadata
899 }
899 }
900 display(bundle, metadata=metadata, raw=True)
900 display(bundle, metadata=metadata, raw=True)
901
901
902 class Javascript(TextDisplayObject):
902 class Javascript(TextDisplayObject):
903
903
904 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):
905 """Create a Javascript display object given raw data.
905 """Create a Javascript display object given raw data.
906
906
907 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
908 display function, it will result in the data being displayed
908 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
909 in the frontend. If the data is a URL, the data will first be
910 downloaded and then displayed.
910 downloaded and then displayed.
911
911
912 In the Notebook, the containing element will be available as `element`,
912 In the Notebook, the containing element will be available as `element`,
913 and jQuery will be available. Content appended to `element` will be
913 and jQuery will be available. Content appended to `element` will be
914 visible in the output area.
914 visible in the output area.
915
915
916 Parameters
916 Parameters
917 ----------
917 ----------
918 data : unicode, str or bytes
918 data : unicode, str or bytes
919 The Javascript source code or a URL to download it from.
919 The Javascript source code or a URL to download it from.
920 url : unicode
920 url : unicode
921 A URL to download the data from.
921 A URL to download the data from.
922 filename : unicode
922 filename : unicode
923 Path to a local file to load the data from.
923 Path to a local file to load the data from.
924 lib : list or str
924 lib : list or str
925 A sequence of Javascript library URLs to load asynchronously before
925 A sequence of Javascript library URLs to load asynchronously before
926 running the source code. The full URLs of the libraries should
926 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
927 be given. A single Javascript library URL can also be given as a
928 string.
928 string.
929 css: : list or str
929 css: : list or str
930 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.
931 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
932 can also be given as a string.
932 can also be given as a string.
933 """
933 """
934 if isinstance(lib, str):
934 if isinstance(lib, str):
935 lib = [lib]
935 lib = [lib]
936 elif lib is None:
936 elif lib is None:
937 lib = []
937 lib = []
938 if isinstance(css, str):
938 if isinstance(css, str):
939 css = [css]
939 css = [css]
940 elif css is None:
940 elif css is None:
941 css = []
941 css = []
942 if not isinstance(lib, (list,tuple)):
942 if not isinstance(lib, (list,tuple)):
943 raise TypeError('expected sequence, got: %r' % lib)
943 raise TypeError('expected sequence, got: %r' % lib)
944 if not isinstance(css, (list,tuple)):
944 if not isinstance(css, (list,tuple)):
945 raise TypeError('expected sequence, got: %r' % css)
945 raise TypeError('expected sequence, got: %r' % css)
946 self.lib = lib
946 self.lib = lib
947 self.css = css
947 self.css = css
948 super(Javascript, self).__init__(data=data, url=url, filename=filename)
948 super(Javascript, self).__init__(data=data, url=url, filename=filename)
949
949
950 def _repr_javascript_(self):
950 def _repr_javascript_(self):
951 r = ''
951 r = ''
952 for c in self.css:
952 for c in self.css:
953 r += _css_t % c
953 r += _css_t % c
954 for l in self.lib:
954 for l in self.lib:
955 r += _lib_t1 % l
955 r += _lib_t1 % l
956 r += self.data
956 r += self.data
957 r += _lib_t2*len(self.lib)
957 r += _lib_t2*len(self.lib)
958 return r
958 return r
959
959
960 # constants for identifying png/jpeg data
960 # constants for identifying png/jpeg data
961 _PNG = b'\x89PNG\r\n\x1a\n'
961 _PNG = b'\x89PNG\r\n\x1a\n'
962 _JPEG = b'\xff\xd8'
962 _JPEG = b'\xff\xd8'
963
963
964 def _pngxy(data):
964 def _pngxy(data):
965 """read the (width, height) from a PNG header"""
965 """read the (width, height) from a PNG header"""
966 ihdr = data.index(b'IHDR')
966 ihdr = data.index(b'IHDR')
967 # next 8 bytes are width/height
967 # next 8 bytes are width/height
968 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
968 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
969
969
970 def _jpegxy(data):
970 def _jpegxy(data):
971 """read the (width, height) from a JPEG header"""
971 """read the (width, height) from a JPEG header"""
972 # adapted from http://www.64lines.com/jpeg-width-height
972 # adapted from http://www.64lines.com/jpeg-width-height
973
973
974 idx = 4
974 idx = 4
975 while True:
975 while True:
976 block_size = struct.unpack('>H', data[idx:idx+2])[0]
976 block_size = struct.unpack('>H', data[idx:idx+2])[0]
977 idx = idx + block_size
977 idx = idx + block_size
978 if data[idx:idx+2] == b'\xFF\xC0':
978 if data[idx:idx+2] == b'\xFF\xC0':
979 # found Start of Frame
979 # found Start of Frame
980 iSOF = idx
980 iSOF = idx
981 break
981 break
982 else:
982 else:
983 # read another block
983 # read another block
984 idx += 2
984 idx += 2
985
985
986 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
986 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
987 return w, h
987 return w, h
988
988
989 def _gifxy(data):
989 def _gifxy(data):
990 """read the (width, height) from a GIF header"""
990 """read the (width, height) from a GIF header"""
991 return struct.unpack('<HH', data[6:10])
991 return struct.unpack('<HH', data[6:10])
992
992
993
993
994 class Image(DisplayObject):
994 class Image(DisplayObject):
995
995
996 _read_flags = 'rb'
996 _read_flags = 'rb'
997 _FMT_JPEG = u'jpeg'
997 _FMT_JPEG = u'jpeg'
998 _FMT_PNG = u'png'
998 _FMT_PNG = u'png'
999 _FMT_GIF = u'gif'
999 _FMT_GIF = u'gif'
1000 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1000 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1001 _MIMETYPES = {
1001 _MIMETYPES = {
1002 _FMT_PNG: 'image/png',
1002 _FMT_PNG: 'image/png',
1003 _FMT_JPEG: 'image/jpeg',
1003 _FMT_JPEG: 'image/jpeg',
1004 _FMT_GIF: 'image/gif',
1004 _FMT_GIF: 'image/gif',
1005 }
1005 }
1006
1006
1007 def __init__(self, data=None, url=None, filename=None, format=None,
1007 def __init__(self, data=None, url=None, filename=None, format=None,
1008 embed=None, width=None, height=None, retina=False,
1008 embed=None, width=None, height=None, retina=False,
1009 unconfined=False, metadata=None):
1009 unconfined=False, metadata=None):
1010 """Create a PNG/JPEG/GIF image object given raw data.
1010 """Create a PNG/JPEG/GIF image object given raw data.
1011
1011
1012 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
1013 display function, it will result in the image being displayed
1013 display function, it will result in the image being displayed
1014 in the frontend.
1014 in the frontend.
1015
1015
1016 Parameters
1016 Parameters
1017 ----------
1017 ----------
1018 data : unicode, str or bytes
1018 data : unicode, str or bytes
1019 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.
1020 This always results in embedded image data.
1020 This always results in embedded image data.
1021 url : unicode
1021 url : unicode
1022 A URL to download the data from. If you specify `url=`,
1022 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`.
1023 the image data will not be embedded unless you also specify `embed=True`.
1024 filename : unicode
1024 filename : unicode
1025 Path to a local file to load the data from.
1025 Path to a local file to load the data from.
1026 Images from a file are always embedded.
1026 Images from a file are always embedded.
1027 format : unicode
1027 format : unicode
1028 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
1029 for format will be inferred from the filename extension.
1029 for format will be inferred from the filename extension.
1030 embed : bool
1030 embed : bool
1031 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
1032 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
1033 to be viewable later with no internet connection in the notebook.
1033 to be viewable later with no internet connection in the notebook.
1034
1034
1035 Default is `True`, unless the keyword argument `url` is set, then
1035 Default is `True`, unless the keyword argument `url` is set, then
1036 default value is `False`.
1036 default value is `False`.
1037
1037
1038 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`
1039 width : int
1039 width : int
1040 Width in pixels to which to constrain the image in html
1040 Width in pixels to which to constrain the image in html
1041 height : int
1041 height : int
1042 Height in pixels to which to constrain the image in html
1042 Height in pixels to which to constrain the image in html
1043 retina : bool
1043 retina : bool
1044 Automatically set the width and height to half of the measured
1044 Automatically set the width and height to half of the measured
1045 width and height.
1045 width and height.
1046 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
1047 from image data.
1047 from image data.
1048 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
1049 and height directly.
1049 and height directly.
1050 unconfined: bool
1050 unconfined: bool
1051 Set unconfined=True to disable max-width confinement of the image.
1051 Set unconfined=True to disable max-width confinement of the image.
1052 metadata: dict
1052 metadata: dict
1053 Specify extra metadata to attach to the image.
1053 Specify extra metadata to attach to the image.
1054
1054
1055 Examples
1055 Examples
1056 --------
1056 --------
1057 # embedded image data, works in qtconsole and notebook
1057 # embedded image data, works in qtconsole and notebook
1058 # 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,
1059 # a URL, or a filename from which to load image data.
1059 # a URL, or a filename from which to load image data.
1060 # The result is always embedding image data for inline images.
1060 # The result is always embedding image data for inline images.
1061 Image('http://www.google.fr/images/srpr/logo3w.png')
1061 Image('http://www.google.fr/images/srpr/logo3w.png')
1062 Image('/path/to/image.jpg')
1062 Image('/path/to/image.jpg')
1063 Image(b'RAW_PNG_DATA...')
1063 Image(b'RAW_PNG_DATA...')
1064
1064
1065 # Specifying Image(url=...) does not embed the image data,
1065 # Specifying Image(url=...) does not embed the image data,
1066 # it only generates `<img>` tag with a link to the source.
1066 # it only generates `<img>` tag with a link to the source.
1067 # This will not work in the qtconsole or offline.
1067 # This will not work in the qtconsole or offline.
1068 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1068 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1069
1069
1070 """
1070 """
1071 if filename is not None:
1071 if filename is not None:
1072 ext = self._find_ext(filename)
1072 ext = self._find_ext(filename)
1073 elif url is not None:
1073 elif url is not None:
1074 ext = self._find_ext(url)
1074 ext = self._find_ext(url)
1075 elif data is None:
1075 elif data is None:
1076 raise ValueError("No image data found. Expecting filename, url, or data.")
1076 raise ValueError("No image data found. Expecting filename, url, or data.")
1077 elif isinstance(data, str) and (
1077 elif isinstance(data, str) and (
1078 data.startswith('http') or _safe_exists(data)
1078 data.startswith('http') or _safe_exists(data)
1079 ):
1079 ):
1080 ext = self._find_ext(data)
1080 ext = self._find_ext(data)
1081 else:
1081 else:
1082 ext = None
1082 ext = None
1083
1083
1084 if format is None:
1084 if format is None:
1085 if ext is not None:
1085 if ext is not None:
1086 if ext == u'jpg' or ext == u'jpeg':
1086 if ext == u'jpg' or ext == u'jpeg':
1087 format = self._FMT_JPEG
1087 format = self._FMT_JPEG
1088 if ext == u'png':
1088 if ext == u'png':
1089 format = self._FMT_PNG
1089 format = self._FMT_PNG
1090 if ext == u'gif':
1090 if ext == u'gif':
1091 format = self._FMT_GIF
1091 format = self._FMT_GIF
1092 else:
1092 else:
1093 format = ext.lower()
1093 format = ext.lower()
1094 elif isinstance(data, bytes):
1094 elif isinstance(data, bytes):
1095 # infer image type from image data header,
1095 # infer image type from image data header,
1096 # only if format has not been specified.
1096 # only if format has not been specified.
1097 if data[:2] == _JPEG:
1097 if data[:2] == _JPEG:
1098 format = self._FMT_JPEG
1098 format = self._FMT_JPEG
1099
1099
1100 # failed to detect format, default png
1100 # failed to detect format, default png
1101 if format is None:
1101 if format is None:
1102 format = self._FMT_PNG
1102 format = self._FMT_PNG
1103
1103
1104 if format.lower() == 'jpg':
1104 if format.lower() == 'jpg':
1105 # jpg->jpeg
1105 # jpg->jpeg
1106 format = self._FMT_JPEG
1106 format = self._FMT_JPEG
1107
1107
1108 self.format = format.lower()
1108 self.format = format.lower()
1109 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)
1110
1110
1111 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1111 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1112 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1112 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1113 if self.embed:
1113 if self.embed:
1114 self._mimetype = self._MIMETYPES.get(self.format)
1114 self._mimetype = self._MIMETYPES.get(self.format)
1115
1115
1116 self.width = width
1116 self.width = width
1117 self.height = height
1117 self.height = height
1118 self.retina = retina
1118 self.retina = retina
1119 self.unconfined = unconfined
1119 self.unconfined = unconfined
1120 super(Image, self).__init__(data=data, url=url, filename=filename,
1120 super(Image, self).__init__(data=data, url=url, filename=filename,
1121 metadata=metadata)
1121 metadata=metadata)
1122
1122
1123 if self.width is None and self.metadata.get('width', {}):
1123 if self.width is None and self.metadata.get('width', {}):
1124 self.width = metadata['width']
1124 self.width = metadata['width']
1125
1125
1126 if self.height is None and self.metadata.get('height', {}):
1126 if self.height is None and self.metadata.get('height', {}):
1127 self.height = metadata['height']
1127 self.height = metadata['height']
1128
1128
1129 if retina:
1129 if retina:
1130 self._retina_shape()
1130 self._retina_shape()
1131
1131
1132
1132
1133 def _retina_shape(self):
1133 def _retina_shape(self):
1134 """load pixel-doubled width and height from image data"""
1134 """load pixel-doubled width and height from image data"""
1135 if not self.embed:
1135 if not self.embed:
1136 return
1136 return
1137 if self.format == self._FMT_PNG:
1137 if self.format == self._FMT_PNG:
1138 w, h = _pngxy(self.data)
1138 w, h = _pngxy(self.data)
1139 elif self.format == self._FMT_JPEG:
1139 elif self.format == self._FMT_JPEG:
1140 w, h = _jpegxy(self.data)
1140 w, h = _jpegxy(self.data)
1141 elif self.format == self._FMT_GIF:
1141 elif self.format == self._FMT_GIF:
1142 w, h = _gifxy(self.data)
1142 w, h = _gifxy(self.data)
1143 else:
1143 else:
1144 # retina only supports png
1144 # retina only supports png
1145 return
1145 return
1146 self.width = w // 2
1146 self.width = w // 2
1147 self.height = h // 2
1147 self.height = h // 2
1148
1148
1149 def reload(self):
1149 def reload(self):
1150 """Reload the raw data from file or URL."""
1150 """Reload the raw data from file or URL."""
1151 if self.embed:
1151 if self.embed:
1152 super(Image,self).reload()
1152 super(Image,self).reload()
1153 if self.retina:
1153 if self.retina:
1154 self._retina_shape()
1154 self._retina_shape()
1155
1155
1156 def _repr_html_(self):
1156 def _repr_html_(self):
1157 if not self.embed:
1157 if not self.embed:
1158 width = height = klass = ''
1158 width = height = klass = ''
1159 if self.width:
1159 if self.width:
1160 width = ' width="%d"' % self.width
1160 width = ' width="%d"' % self.width
1161 if self.height:
1161 if self.height:
1162 height = ' height="%d"' % self.height
1162 height = ' height="%d"' % self.height
1163 if self.unconfined:
1163 if self.unconfined:
1164 klass = ' class="unconfined"'
1164 klass = ' class="unconfined"'
1165 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1165 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1166 url=self.url,
1166 url=self.url,
1167 width=width,
1167 width=width,
1168 height=height,
1168 height=height,
1169 klass=klass,
1169 klass=klass,
1170 )
1170 )
1171
1171
1172 def _repr_mimebundle_(self, include=None, exclude=None):
1172 def _repr_mimebundle_(self, include=None, exclude=None):
1173 """Return the image as a mimebundle
1173 """Return the image as a mimebundle
1174
1174
1175 Any new mimetype support should be implemented here.
1175 Any new mimetype support should be implemented here.
1176 """
1176 """
1177 if self.embed:
1177 if self.embed:
1178 mimetype = self._mimetype
1178 mimetype = self._mimetype
1179 data, metadata = self._data_and_metadata(always_both=True)
1179 data, metadata = self._data_and_metadata(always_both=True)
1180 if metadata:
1180 if metadata:
1181 metadata = {mimetype: metadata}
1181 metadata = {mimetype: metadata}
1182 return {mimetype: data}, metadata
1182 return {mimetype: data}, metadata
1183 else:
1183 else:
1184 return {'text/html': self._repr_html_()}
1184 return {'text/html': self._repr_html_()}
1185
1185
1186 def _data_and_metadata(self, always_both=False):
1186 def _data_and_metadata(self, always_both=False):
1187 """shortcut for returning metadata with shape information, if defined"""
1187 """shortcut for returning metadata with shape information, if defined"""
1188 b64_data = b2a_base64(self.data).decode('ascii')
1188 b64_data = b2a_base64(self.data).decode('ascii')
1189 md = {}
1189 md = {}
1190 if self.metadata:
1190 if self.metadata:
1191 md.update(self.metadata)
1191 md.update(self.metadata)
1192 if self.width:
1192 if self.width:
1193 md['width'] = self.width
1193 md['width'] = self.width
1194 if self.height:
1194 if self.height:
1195 md['height'] = self.height
1195 md['height'] = self.height
1196 if self.unconfined:
1196 if self.unconfined:
1197 md['unconfined'] = self.unconfined
1197 md['unconfined'] = self.unconfined
1198 if md or always_both:
1198 if md or always_both:
1199 return b64_data, md
1199 return b64_data, md
1200 else:
1200 else:
1201 return b64_data
1201 return b64_data
1202
1202
1203 def _repr_png_(self):
1203 def _repr_png_(self):
1204 if self.embed and self.format == self._FMT_PNG:
1204 if self.embed and self.format == self._FMT_PNG:
1205 return self._data_and_metadata()
1205 return self._data_and_metadata()
1206
1206
1207 def _repr_jpeg_(self):
1207 def _repr_jpeg_(self):
1208 if self.embed and self.format == self._FMT_JPEG:
1208 if self.embed and self.format == self._FMT_JPEG:
1209 return self._data_and_metadata()
1209 return self._data_and_metadata()
1210
1210
1211 def _find_ext(self, s):
1211 def _find_ext(self, s):
1212 return s.split('.')[-1].lower()
1212 return s.split('.')[-1].lower()
1213
1213
1214
1214
1215 class Video(DisplayObject):
1215 class Video(DisplayObject):
1216
1216
1217 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):
1218 """Create a video object given raw data or an URL.
1218 """Create a video object given raw data or an URL.
1219
1219
1220 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
1221 display function, it will result in the video being displayed
1221 display function, it will result in the video being displayed
1222 in the frontend.
1222 in the frontend.
1223
1223
1224 Parameters
1224 Parameters
1225 ----------
1225 ----------
1226 data : unicode, str or bytes
1226 data : unicode, str or bytes
1227 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.
1228 Raw data will require passing `embed=True`.
1228 Raw data will require passing `embed=True`.
1229 url : unicode
1229 url : unicode
1230 A URL for the video. If you specify `url=`,
1230 A URL for the video. If you specify `url=`,
1231 the image data will not be embedded.
1231 the image data will not be embedded.
1232 filename : unicode
1232 filename : unicode
1233 Path to a local file containing the video.
1233 Path to a local file containing the video.
1234 Will be interpreted as a local URL unless `embed=True`.
1234 Will be interpreted as a local URL unless `embed=True`.
1235 embed : bool
1235 embed : bool
1236 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
1237 loaded using a <video> tag (False).
1237 loaded using a <video> tag (False).
1238
1238
1239 Since videos are large, embedding them should be avoided, if possible.
1239 Since videos are large, embedding them should be avoided, if possible.
1240 You must confirm embedding as your intention by passing `embed=True`.
1240 You must confirm embedding as your intention by passing `embed=True`.
1241
1241
1242 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::
1243
1243
1244 Video('./video.mp4')
1244 Video('./video.mp4')
1245
1245
1246 mimetype: unicode
1246 mimetype: unicode
1247 Specify the mimetype for embedded videos.
1247 Specify the mimetype for embedded videos.
1248 Default will be guessed from file extension, if available.
1248 Default will be guessed from file extension, if available.
1249
1249
1250 Examples
1250 Examples
1251 --------
1251 --------
1252
1252
1253 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')
1254 Video('path/to/video.mp4')
1254 Video('path/to/video.mp4')
1255 Video('path/to/video.mp4', embed=True)
1255 Video('path/to/video.mp4', embed=True)
1256 Video(b'raw-videodata', embed=True)
1256 Video(b'raw-videodata', embed=True)
1257 """
1257 """
1258 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:')):
1259 url = data
1259 url = data
1260 data = None
1260 data = None
1261 elif os.path.exists(data):
1261 elif os.path.exists(data):
1262 filename = data
1262 filename = data
1263 data = None
1263 data = None
1264
1264
1265 if data and not embed:
1265 if data and not embed:
1266 msg = ''.join([
1266 msg = ''.join([
1267 "To embed videos, you must pass embed=True ",
1267 "To embed videos, you must pass embed=True ",
1268 "(this may make your notebook files huge)\n",
1268 "(this may make your notebook files huge)\n",
1269 "Consider passing Video(url='...')",
1269 "Consider passing Video(url='...')",
1270 ])
1270 ])
1271 raise ValueError(msg)
1271 raise ValueError(msg)
1272
1272
1273 self.mimetype = mimetype
1273 self.mimetype = mimetype
1274 self.embed = embed
1274 self.embed = embed
1275 super(Video, self).__init__(data=data, url=url, filename=filename)
1275 super(Video, self).__init__(data=data, url=url, filename=filename)
1276
1276
1277 def _repr_html_(self):
1277 def _repr_html_(self):
1278 # External URLs and potentially local files are not embedded into the
1278 # External URLs and potentially local files are not embedded into the
1279 # notebook output.
1279 # notebook output.
1280 if not self.embed:
1280 if not self.embed:
1281 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
1282 output = """<video src="{0}" controls>
1282 output = """<video src="{0}" controls>
1283 Your browser does not support the <code>video</code> element.
1283 Your browser does not support the <code>video</code> element.
1284 </video>""".format(url)
1284 </video>""".format(url)
1285 return output
1285 return output
1286
1286
1287 # Embedded videos are base64-encoded.
1287 # Embedded videos are base64-encoded.
1288 mimetype = self.mimetype
1288 mimetype = self.mimetype
1289 if self.filename is not None:
1289 if self.filename is not None:
1290 if not mimetype:
1290 if not mimetype:
1291 mimetype, _ = mimetypes.guess_type(self.filename)
1291 mimetype, _ = mimetypes.guess_type(self.filename)
1292
1292
1293 with open(self.filename, 'rb') as f:
1293 with open(self.filename, 'rb') as f:
1294 video = f.read()
1294 video = f.read()
1295 else:
1295 else:
1296 video = self.data
1296 video = self.data
1297 if isinstance(video, str):
1297 if isinstance(video, str):
1298 # unicode input is already b64-encoded
1298 # unicode input is already b64-encoded
1299 b64_video = video
1299 b64_video = video
1300 else:
1300 else:
1301 b64_video = b2a_base64(video).decode('ascii').rstrip()
1301 b64_video = b2a_base64(video).decode('ascii').rstrip()
1302
1302
1303 output = """<video controls>
1303 output = """<video controls>
1304 <source src="data:{0};base64,{1}" type="{0}">
1304 <source src="data:{0};base64,{1}" type="{0}">
1305 Your browser does not support the video tag.
1305 Your browser does not support the video tag.
1306 </video>""".format(mimetype, b64_video)
1306 </video>""".format(mimetype, b64_video)
1307 return output
1307 return output
1308
1308
1309 def reload(self):
1309 def reload(self):
1310 # TODO
1310 # TODO
1311 pass
1311 pass
1312
1312
1313
1313
1314 def clear_output(wait=False):
1314 def clear_output(wait=False):
1315 """Clear the output of the current cell receiving output.
1315 """Clear the output of the current cell receiving output.
1316
1316
1317 Parameters
1317 Parameters
1318 ----------
1318 ----------
1319 wait : bool [default: false]
1319 wait : bool [default: false]
1320 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."""
1321 from IPython.core.interactiveshell import InteractiveShell
1321 from IPython.core.interactiveshell import InteractiveShell
1322 if InteractiveShell.initialized():
1322 if InteractiveShell.initialized():
1323 InteractiveShell.instance().display_pub.clear_output(wait)
1323 InteractiveShell.instance().display_pub.clear_output(wait)
1324 else:
1324 else:
1325 print('\033[2K\r', end='')
1325 print('\033[2K\r', end='')
1326 sys.stdout.flush()
1326 sys.stdout.flush()
1327 print('\033[2K\r', end='')
1327 print('\033[2K\r', end='')
1328 sys.stderr.flush()
1328 sys.stderr.flush()
1329
1329
1330
1330
1331 @skip_doctest
1331 @skip_doctest
1332 def set_matplotlib_formats(*formats, **kwargs):
1332 def set_matplotlib_formats(*formats, **kwargs):
1333 """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.
1334
1334
1335 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%::
1336
1336
1337 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1337 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1338
1338
1339 To set this in your config files use the following::
1339 To set this in your config files use the following::
1340
1340
1341 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1341 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1342 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1342 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1343
1343
1344 Parameters
1344 Parameters
1345 ----------
1345 ----------
1346 *formats : strs
1346 *formats : strs
1347 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'.
1348 **kwargs :
1348 **kwargs :
1349 Keyword args will be relayed to ``figure.canvas.print_figure``.
1349 Keyword args will be relayed to ``figure.canvas.print_figure``.
1350 """
1350 """
1351 from IPython.core.interactiveshell import InteractiveShell
1351 from IPython.core.interactiveshell import InteractiveShell
1352 from IPython.core.pylabtools import select_figure_formats
1352 from IPython.core.pylabtools import select_figure_formats
1353 # build kwargs, starting with InlineBackend config
1353 # build kwargs, starting with InlineBackend config
1354 kw = {}
1354 kw = {}
1355 from ipykernel.pylab.config import InlineBackend
1355 from ipykernel.pylab.config import InlineBackend
1356 cfg = InlineBackend.instance()
1356 cfg = InlineBackend.instance()
1357 kw.update(cfg.print_figure_kwargs)
1357 kw.update(cfg.print_figure_kwargs)
1358 kw.update(**kwargs)
1358 kw.update(**kwargs)
1359 shell = InteractiveShell.instance()
1359 shell = InteractiveShell.instance()
1360 select_figure_formats(shell, formats, **kw)
1360 select_figure_formats(shell, formats, **kw)
1361
1361
1362 @skip_doctest
1362 @skip_doctest
1363 def set_matplotlib_close(close=True):
1363 def set_matplotlib_close(close=True):
1364 """Set whether the inline backend closes all figures automatically or not.
1364 """Set whether the inline backend closes all figures automatically or not.
1365
1365
1366 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
1367 matplotlib figures automatically after each cell is run. This means that
1367 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
1368 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
1369 a plot in one cell and then refine it in later cells. This can be accomplished
1370 by::
1370 by::
1371
1371
1372 In [1]: set_matplotlib_close(False)
1372 In [1]: set_matplotlib_close(False)
1373
1373
1374 To set this in your config files use the following::
1374 To set this in your config files use the following::
1375
1375
1376 c.InlineBackend.close_figures = False
1376 c.InlineBackend.close_figures = False
1377
1377
1378 Parameters
1378 Parameters
1379 ----------
1379 ----------
1380 close : bool
1380 close : bool
1381 Should all matplotlib figures be automatically closed after each cell is
1381 Should all matplotlib figures be automatically closed after each cell is
1382 run?
1382 run?
1383 """
1383 """
1384 from ipykernel.pylab.config import InlineBackend
1384 from ipykernel.pylab.config import InlineBackend
1385 cfg = InlineBackend.instance()
1385 cfg = InlineBackend.instance()
1386 cfg.close_figures = close
1386 cfg.close_figures = close
General Comments 0
You need to be logged in to leave comments. Login now