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