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