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