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