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