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