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