##// END OF EJS Templates
Fix display import in .core.display
Eric Prestat -
Show More
@@ -1,1272 +1,1272 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(*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 with open(self.filename, self._read_flags) as f:
352 with open(self.filename, self._read_flags) as f:
353 self.data = f.read()
353 self.data = f.read()
354 elif self.url is not None:
354 elif self.url is not None:
355 # Deferred import
355 # Deferred import
356 from urllib.request import urlopen
356 from urllib.request import urlopen
357 response = urlopen(self.url)
357 response = urlopen(self.url)
358 data = response.read()
358 data = response.read()
359 # extract encoding from header, if there is one:
359 # extract encoding from header, if there is one:
360 encoding = None
360 encoding = None
361 if 'content-type' in response.headers:
361 if 'content-type' in response.headers:
362 for sub in response.headers['content-type'].split(';'):
362 for sub in response.headers['content-type'].split(';'):
363 sub = sub.strip()
363 sub = sub.strip()
364 if sub.startswith('charset'):
364 if sub.startswith('charset'):
365 encoding = sub.split('=')[-1].strip()
365 encoding = sub.split('=')[-1].strip()
366 break
366 break
367 if 'content-encoding' in response.headers:
367 if 'content-encoding' in response.headers:
368 # TODO: do deflate?
368 # TODO: do deflate?
369 if 'gzip' in response.headers['content-encoding']:
369 if 'gzip' in response.headers['content-encoding']:
370 import gzip
370 import gzip
371 from io import BytesIO
371 from io import BytesIO
372 with gzip.open(BytesIO(data), 'rt', encoding=encoding) as fp:
372 with gzip.open(BytesIO(data), 'rt', encoding=encoding) as fp:
373 encoding = None
373 encoding = None
374 data = fp.read()
374 data = fp.read()
375
375
376 # decode data, if an encoding was specified
376 # decode data, if an encoding was specified
377 # We only touch self.data once since
377 # We only touch self.data once since
378 # subclasses such as SVG have @data.setter methods
378 # subclasses such as SVG have @data.setter methods
379 # that transform self.data into ... well svg.
379 # that transform self.data into ... well svg.
380 if encoding:
380 if encoding:
381 self.data = data.decode(encoding, 'replace')
381 self.data = data.decode(encoding, 'replace')
382 else:
382 else:
383 self.data = data
383 self.data = data
384
384
385
385
386 class TextDisplayObject(DisplayObject):
386 class TextDisplayObject(DisplayObject):
387 """Validate that display data is text"""
387 """Validate that display data is text"""
388 def _check_data(self):
388 def _check_data(self):
389 if self.data is not None and not isinstance(self.data, str):
389 if self.data is not None and not isinstance(self.data, str):
390 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
390 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
391
391
392 class Pretty(TextDisplayObject):
392 class Pretty(TextDisplayObject):
393
393
394 def _repr_pretty_(self, pp, cycle):
394 def _repr_pretty_(self, pp, cycle):
395 return pp.text(self.data)
395 return pp.text(self.data)
396
396
397
397
398 class HTML(TextDisplayObject):
398 class HTML(TextDisplayObject):
399
399
400 def __init__(self, data=None, url=None, filename=None, metadata=None):
400 def __init__(self, data=None, url=None, filename=None, metadata=None):
401 def warn():
401 def warn():
402 if not data:
402 if not data:
403 return False
403 return False
404
404
405 #
405 #
406 # Avoid calling lower() on the entire data, because it could be a
406 # Avoid calling lower() on the entire data, because it could be a
407 # long string and we're only interested in its beginning and end.
407 # long string and we're only interested in its beginning and end.
408 #
408 #
409 prefix = data[:10].lower()
409 prefix = data[:10].lower()
410 suffix = data[-10:].lower()
410 suffix = data[-10:].lower()
411 return prefix.startswith("<iframe ") and suffix.endswith("</iframe>")
411 return prefix.startswith("<iframe ") and suffix.endswith("</iframe>")
412
412
413 if warn():
413 if warn():
414 warnings.warn("Consider using IPython.display.IFrame instead")
414 warnings.warn("Consider using IPython.display.IFrame instead")
415 super(HTML, self).__init__(data=data, url=url, filename=filename, metadata=metadata)
415 super(HTML, self).__init__(data=data, url=url, filename=filename, metadata=metadata)
416
416
417 def _repr_html_(self):
417 def _repr_html_(self):
418 return self._data_and_metadata()
418 return self._data_and_metadata()
419
419
420 def __html__(self):
420 def __html__(self):
421 """
421 """
422 This method exists to inform other HTML-using modules (e.g. Markupsafe,
422 This method exists to inform other HTML-using modules (e.g. Markupsafe,
423 htmltag, etc) that this object is HTML and does not need things like
423 htmltag, etc) that this object is HTML and does not need things like
424 special characters (<>&) escaped.
424 special characters (<>&) escaped.
425 """
425 """
426 return self._repr_html_()
426 return self._repr_html_()
427
427
428
428
429 class Markdown(TextDisplayObject):
429 class Markdown(TextDisplayObject):
430
430
431 def _repr_markdown_(self):
431 def _repr_markdown_(self):
432 return self._data_and_metadata()
432 return self._data_and_metadata()
433
433
434
434
435 class Math(TextDisplayObject):
435 class Math(TextDisplayObject):
436
436
437 def _repr_latex_(self):
437 def _repr_latex_(self):
438 s = r"$\displaystyle %s$" % self.data.strip('$')
438 s = r"$\displaystyle %s$" % self.data.strip('$')
439 if self.metadata:
439 if self.metadata:
440 return s, deepcopy(self.metadata)
440 return s, deepcopy(self.metadata)
441 else:
441 else:
442 return s
442 return s
443
443
444
444
445 class Latex(TextDisplayObject):
445 class Latex(TextDisplayObject):
446
446
447 def _repr_latex_(self):
447 def _repr_latex_(self):
448 return self._data_and_metadata()
448 return self._data_and_metadata()
449
449
450
450
451 class SVG(DisplayObject):
451 class SVG(DisplayObject):
452 """Embed an SVG into the display.
452 """Embed an SVG into the display.
453
453
454 Note if you just want to view a svg image via a URL use `:class:Image` with
454 Note if you just want to view a svg image via a URL use `:class:Image` with
455 a url=URL keyword argument.
455 a url=URL keyword argument.
456 """
456 """
457
457
458 _read_flags = 'rb'
458 _read_flags = 'rb'
459 # wrap data in a property, which extracts the <svg> tag, discarding
459 # wrap data in a property, which extracts the <svg> tag, discarding
460 # document headers
460 # document headers
461 _data = None
461 _data = None
462
462
463 @property
463 @property
464 def data(self):
464 def data(self):
465 return self._data
465 return self._data
466
466
467 @data.setter
467 @data.setter
468 def data(self, svg):
468 def data(self, svg):
469 if svg is None:
469 if svg is None:
470 self._data = None
470 self._data = None
471 return
471 return
472 # parse into dom object
472 # parse into dom object
473 from xml.dom import minidom
473 from xml.dom import minidom
474 x = minidom.parseString(svg)
474 x = minidom.parseString(svg)
475 # get svg tag (should be 1)
475 # get svg tag (should be 1)
476 found_svg = x.getElementsByTagName('svg')
476 found_svg = x.getElementsByTagName('svg')
477 if found_svg:
477 if found_svg:
478 svg = found_svg[0].toxml()
478 svg = found_svg[0].toxml()
479 else:
479 else:
480 # fallback on the input, trust the user
480 # fallback on the input, trust the user
481 # but this is probably an error.
481 # but this is probably an error.
482 pass
482 pass
483 svg = cast_unicode(svg)
483 svg = cast_unicode(svg)
484 self._data = svg
484 self._data = svg
485
485
486 def _repr_svg_(self):
486 def _repr_svg_(self):
487 return self._data_and_metadata()
487 return self._data_and_metadata()
488
488
489 class ProgressBar(DisplayObject):
489 class ProgressBar(DisplayObject):
490 """Progressbar supports displaying a progressbar like element
490 """Progressbar supports displaying a progressbar like element
491 """
491 """
492 def __init__(self, total):
492 def __init__(self, total):
493 """Creates a new progressbar
493 """Creates a new progressbar
494
494
495 Parameters
495 Parameters
496 ----------
496 ----------
497 total : int
497 total : int
498 maximum size of the progressbar
498 maximum size of the progressbar
499 """
499 """
500 self.total = total
500 self.total = total
501 self._progress = 0
501 self._progress = 0
502 self.html_width = '60ex'
502 self.html_width = '60ex'
503 self.text_width = 60
503 self.text_width = 60
504 self._display_id = hexlify(os.urandom(8)).decode('ascii')
504 self._display_id = hexlify(os.urandom(8)).decode('ascii')
505
505
506 def __repr__(self):
506 def __repr__(self):
507 fraction = self.progress / self.total
507 fraction = self.progress / self.total
508 filled = '=' * int(fraction * self.text_width)
508 filled = '=' * int(fraction * self.text_width)
509 rest = ' ' * (self.text_width - len(filled))
509 rest = ' ' * (self.text_width - len(filled))
510 return '[{}{}] {}/{}'.format(
510 return '[{}{}] {}/{}'.format(
511 filled, rest,
511 filled, rest,
512 self.progress, self.total,
512 self.progress, self.total,
513 )
513 )
514
514
515 def _repr_html_(self):
515 def _repr_html_(self):
516 return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
516 return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
517 self.html_width, self.total, self.progress)
517 self.html_width, self.total, self.progress)
518
518
519 def display(self):
519 def display(self):
520 display(self, display_id=self._display_id)
520 display_functions.display(self, display_id=self._display_id)
521
521
522 def update(self):
522 def update(self):
523 display(self, display_id=self._display_id, update=True)
523 display_functions.display(self, display_id=self._display_id, update=True)
524
524
525 @property
525 @property
526 def progress(self):
526 def progress(self):
527 return self._progress
527 return self._progress
528
528
529 @progress.setter
529 @progress.setter
530 def progress(self, value):
530 def progress(self, value):
531 self._progress = value
531 self._progress = value
532 self.update()
532 self.update()
533
533
534 def __iter__(self):
534 def __iter__(self):
535 self.display()
535 self.display()
536 self._progress = -1 # First iteration is 0
536 self._progress = -1 # First iteration is 0
537 return self
537 return self
538
538
539 def __next__(self):
539 def __next__(self):
540 """Returns current value and increments display by one."""
540 """Returns current value and increments display by one."""
541 self.progress += 1
541 self.progress += 1
542 if self.progress < self.total:
542 if self.progress < self.total:
543 return self.progress
543 return self.progress
544 else:
544 else:
545 raise StopIteration()
545 raise StopIteration()
546
546
547 class JSON(DisplayObject):
547 class JSON(DisplayObject):
548 """JSON expects a JSON-able dict or list
548 """JSON expects a JSON-able dict or list
549
549
550 not an already-serialized JSON string.
550 not an already-serialized JSON string.
551
551
552 Scalar types (None, number, string) are not allowed, only dict or list containers.
552 Scalar types (None, number, string) are not allowed, only dict or list containers.
553 """
553 """
554 # wrap data in a property, which warns about passing already-serialized JSON
554 # wrap data in a property, which warns about passing already-serialized JSON
555 _data = None
555 _data = None
556 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs):
556 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs):
557 """Create a JSON display object given raw data.
557 """Create a JSON display object given raw data.
558
558
559 Parameters
559 Parameters
560 ----------
560 ----------
561 data : dict or list
561 data : dict or list
562 JSON data to display. Not an already-serialized JSON string.
562 JSON data to display. Not an already-serialized JSON string.
563 Scalar types (None, number, string) are not allowed, only dict
563 Scalar types (None, number, string) are not allowed, only dict
564 or list containers.
564 or list containers.
565 url : unicode
565 url : unicode
566 A URL to download the data from.
566 A URL to download the data from.
567 filename : unicode
567 filename : unicode
568 Path to a local file to load the data from.
568 Path to a local file to load the data from.
569 expanded : boolean
569 expanded : boolean
570 Metadata to control whether a JSON display component is expanded.
570 Metadata to control whether a JSON display component is expanded.
571 metadata : dict
571 metadata : dict
572 Specify extra metadata to attach to the json display object.
572 Specify extra metadata to attach to the json display object.
573 root : str
573 root : str
574 The name of the root element of the JSON tree
574 The name of the root element of the JSON tree
575 """
575 """
576 self.metadata = {
576 self.metadata = {
577 'expanded': expanded,
577 'expanded': expanded,
578 'root': root,
578 'root': root,
579 }
579 }
580 if metadata:
580 if metadata:
581 self.metadata.update(metadata)
581 self.metadata.update(metadata)
582 if kwargs:
582 if kwargs:
583 self.metadata.update(kwargs)
583 self.metadata.update(kwargs)
584 super(JSON, self).__init__(data=data, url=url, filename=filename)
584 super(JSON, self).__init__(data=data, url=url, filename=filename)
585
585
586 def _check_data(self):
586 def _check_data(self):
587 if self.data is not None and not isinstance(self.data, (dict, list)):
587 if self.data is not None and not isinstance(self.data, (dict, list)):
588 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
588 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
589
589
590 @property
590 @property
591 def data(self):
591 def data(self):
592 return self._data
592 return self._data
593
593
594 @data.setter
594 @data.setter
595 def data(self, data):
595 def data(self, data):
596 if isinstance(data, (Path, PurePath)):
596 if isinstance(data, (Path, PurePath)):
597 data = str(data)
597 data = str(data)
598
598
599 if isinstance(data, str):
599 if isinstance(data, str):
600 if self.filename is None and self.url is None:
600 if self.filename is None and self.url is None:
601 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
601 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
602 data = json.loads(data)
602 data = json.loads(data)
603 self._data = data
603 self._data = data
604
604
605 def _data_and_metadata(self):
605 def _data_and_metadata(self):
606 return self.data, self.metadata
606 return self.data, self.metadata
607
607
608 def _repr_json_(self):
608 def _repr_json_(self):
609 return self._data_and_metadata()
609 return self._data_and_metadata()
610
610
611 _css_t = """var link = document.createElement("link");
611 _css_t = """var link = document.createElement("link");
612 link.ref = "stylesheet";
612 link.ref = "stylesheet";
613 link.type = "text/css";
613 link.type = "text/css";
614 link.href = "%s";
614 link.href = "%s";
615 document.head.appendChild(link);
615 document.head.appendChild(link);
616 """
616 """
617
617
618 _lib_t1 = """new Promise(function(resolve, reject) {
618 _lib_t1 = """new Promise(function(resolve, reject) {
619 var script = document.createElement("script");
619 var script = document.createElement("script");
620 script.onload = resolve;
620 script.onload = resolve;
621 script.onerror = reject;
621 script.onerror = reject;
622 script.src = "%s";
622 script.src = "%s";
623 document.head.appendChild(script);
623 document.head.appendChild(script);
624 }).then(() => {
624 }).then(() => {
625 """
625 """
626
626
627 _lib_t2 = """
627 _lib_t2 = """
628 });"""
628 });"""
629
629
630 class GeoJSON(JSON):
630 class GeoJSON(JSON):
631 """GeoJSON expects JSON-able dict
631 """GeoJSON expects JSON-able dict
632
632
633 not an already-serialized JSON string.
633 not an already-serialized JSON string.
634
634
635 Scalar types (None, number, string) are not allowed, only dict containers.
635 Scalar types (None, number, string) are not allowed, only dict containers.
636 """
636 """
637
637
638 def __init__(self, *args, **kwargs):
638 def __init__(self, *args, **kwargs):
639 """Create a GeoJSON display object given raw data.
639 """Create a GeoJSON display object given raw data.
640
640
641 Parameters
641 Parameters
642 ----------
642 ----------
643 data : dict or list
643 data : dict or list
644 VegaLite data. Not an already-serialized JSON string.
644 VegaLite data. Not an already-serialized JSON string.
645 Scalar types (None, number, string) are not allowed, only dict
645 Scalar types (None, number, string) are not allowed, only dict
646 or list containers.
646 or list containers.
647 url_template : string
647 url_template : string
648 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
648 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
649 layer_options : dict
649 layer_options : dict
650 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
650 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
651 url : unicode
651 url : unicode
652 A URL to download the data from.
652 A URL to download the data from.
653 filename : unicode
653 filename : unicode
654 Path to a local file to load the data from.
654 Path to a local file to load the data from.
655 metadata : dict
655 metadata : dict
656 Specify extra metadata to attach to the json display object.
656 Specify extra metadata to attach to the json display object.
657
657
658 Examples
658 Examples
659 --------
659 --------
660 The following will display an interactive map of Mars with a point of
660 The following will display an interactive map of Mars with a point of
661 interest on frontend that do support GeoJSON display.
661 interest on frontend that do support GeoJSON display.
662
662
663 >>> from IPython.display import GeoJSON
663 >>> from IPython.display import GeoJSON
664
664
665 >>> GeoJSON(data={
665 >>> GeoJSON(data={
666 ... "type": "Feature",
666 ... "type": "Feature",
667 ... "geometry": {
667 ... "geometry": {
668 ... "type": "Point",
668 ... "type": "Point",
669 ... "coordinates": [-81.327, 296.038]
669 ... "coordinates": [-81.327, 296.038]
670 ... }
670 ... }
671 ... },
671 ... },
672 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
672 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
673 ... layer_options={
673 ... layer_options={
674 ... "basemap_id": "celestia_mars-shaded-16k_global",
674 ... "basemap_id": "celestia_mars-shaded-16k_global",
675 ... "attribution" : "Celestia/praesepe",
675 ... "attribution" : "Celestia/praesepe",
676 ... "minZoom" : 0,
676 ... "minZoom" : 0,
677 ... "maxZoom" : 18,
677 ... "maxZoom" : 18,
678 ... })
678 ... })
679 <IPython.core.display.GeoJSON object>
679 <IPython.core.display.GeoJSON object>
680
680
681 In the terminal IPython, you will only see the text representation of
681 In the terminal IPython, you will only see the text representation of
682 the GeoJSON object.
682 the GeoJSON object.
683
683
684 """
684 """
685
685
686 super(GeoJSON, self).__init__(*args, **kwargs)
686 super(GeoJSON, self).__init__(*args, **kwargs)
687
687
688
688
689 def _ipython_display_(self):
689 def _ipython_display_(self):
690 bundle = {
690 bundle = {
691 'application/geo+json': self.data,
691 'application/geo+json': self.data,
692 'text/plain': '<IPython.display.GeoJSON object>'
692 'text/plain': '<IPython.display.GeoJSON object>'
693 }
693 }
694 metadata = {
694 metadata = {
695 'application/geo+json': self.metadata
695 'application/geo+json': self.metadata
696 }
696 }
697 display(bundle, metadata=metadata, raw=True)
697 display_functions.display(bundle, metadata=metadata, raw=True)
698
698
699 class Javascript(TextDisplayObject):
699 class Javascript(TextDisplayObject):
700
700
701 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
701 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
702 """Create a Javascript display object given raw data.
702 """Create a Javascript display object given raw data.
703
703
704 When this object is returned by an expression or passed to the
704 When this object is returned by an expression or passed to the
705 display function, it will result in the data being displayed
705 display function, it will result in the data being displayed
706 in the frontend. If the data is a URL, the data will first be
706 in the frontend. If the data is a URL, the data will first be
707 downloaded and then displayed.
707 downloaded and then displayed.
708
708
709 In the Notebook, the containing element will be available as `element`,
709 In the Notebook, the containing element will be available as `element`,
710 and jQuery will be available. Content appended to `element` will be
710 and jQuery will be available. Content appended to `element` will be
711 visible in the output area.
711 visible in the output area.
712
712
713 Parameters
713 Parameters
714 ----------
714 ----------
715 data : unicode, str or bytes
715 data : unicode, str or bytes
716 The Javascript source code or a URL to download it from.
716 The Javascript source code or a URL to download it from.
717 url : unicode
717 url : unicode
718 A URL to download the data from.
718 A URL to download the data from.
719 filename : unicode
719 filename : unicode
720 Path to a local file to load the data from.
720 Path to a local file to load the data from.
721 lib : list or str
721 lib : list or str
722 A sequence of Javascript library URLs to load asynchronously before
722 A sequence of Javascript library URLs to load asynchronously before
723 running the source code. The full URLs of the libraries should
723 running the source code. The full URLs of the libraries should
724 be given. A single Javascript library URL can also be given as a
724 be given. A single Javascript library URL can also be given as a
725 string.
725 string.
726 css : list or str
726 css : list or str
727 A sequence of css files to load before running the source code.
727 A sequence of css files to load before running the source code.
728 The full URLs of the css files should be given. A single css URL
728 The full URLs of the css files should be given. A single css URL
729 can also be given as a string.
729 can also be given as a string.
730 """
730 """
731 if isinstance(lib, str):
731 if isinstance(lib, str):
732 lib = [lib]
732 lib = [lib]
733 elif lib is None:
733 elif lib is None:
734 lib = []
734 lib = []
735 if isinstance(css, str):
735 if isinstance(css, str):
736 css = [css]
736 css = [css]
737 elif css is None:
737 elif css is None:
738 css = []
738 css = []
739 if not isinstance(lib, (list,tuple)):
739 if not isinstance(lib, (list,tuple)):
740 raise TypeError('expected sequence, got: %r' % lib)
740 raise TypeError('expected sequence, got: %r' % lib)
741 if not isinstance(css, (list,tuple)):
741 if not isinstance(css, (list,tuple)):
742 raise TypeError('expected sequence, got: %r' % css)
742 raise TypeError('expected sequence, got: %r' % css)
743 self.lib = lib
743 self.lib = lib
744 self.css = css
744 self.css = css
745 super(Javascript, self).__init__(data=data, url=url, filename=filename)
745 super(Javascript, self).__init__(data=data, url=url, filename=filename)
746
746
747 def _repr_javascript_(self):
747 def _repr_javascript_(self):
748 r = ''
748 r = ''
749 for c in self.css:
749 for c in self.css:
750 r += _css_t % c
750 r += _css_t % c
751 for l in self.lib:
751 for l in self.lib:
752 r += _lib_t1 % l
752 r += _lib_t1 % l
753 r += self.data
753 r += self.data
754 r += _lib_t2*len(self.lib)
754 r += _lib_t2*len(self.lib)
755 return r
755 return r
756
756
757 # constants for identifying png/jpeg data
757 # constants for identifying png/jpeg data
758 _PNG = b'\x89PNG\r\n\x1a\n'
758 _PNG = b'\x89PNG\r\n\x1a\n'
759 _JPEG = b'\xff\xd8'
759 _JPEG = b'\xff\xd8'
760
760
761 def _pngxy(data):
761 def _pngxy(data):
762 """read the (width, height) from a PNG header"""
762 """read the (width, height) from a PNG header"""
763 ihdr = data.index(b'IHDR')
763 ihdr = data.index(b'IHDR')
764 # next 8 bytes are width/height
764 # next 8 bytes are width/height
765 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
765 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
766
766
767 def _jpegxy(data):
767 def _jpegxy(data):
768 """read the (width, height) from a JPEG header"""
768 """read the (width, height) from a JPEG header"""
769 # adapted from http://www.64lines.com/jpeg-width-height
769 # adapted from http://www.64lines.com/jpeg-width-height
770
770
771 idx = 4
771 idx = 4
772 while True:
772 while True:
773 block_size = struct.unpack('>H', data[idx:idx+2])[0]
773 block_size = struct.unpack('>H', data[idx:idx+2])[0]
774 idx = idx + block_size
774 idx = idx + block_size
775 if data[idx:idx+2] == b'\xFF\xC0':
775 if data[idx:idx+2] == b'\xFF\xC0':
776 # found Start of Frame
776 # found Start of Frame
777 iSOF = idx
777 iSOF = idx
778 break
778 break
779 else:
779 else:
780 # read another block
780 # read another block
781 idx += 2
781 idx += 2
782
782
783 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
783 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
784 return w, h
784 return w, h
785
785
786 def _gifxy(data):
786 def _gifxy(data):
787 """read the (width, height) from a GIF header"""
787 """read the (width, height) from a GIF header"""
788 return struct.unpack('<HH', data[6:10])
788 return struct.unpack('<HH', data[6:10])
789
789
790
790
791 class Image(DisplayObject):
791 class Image(DisplayObject):
792
792
793 _read_flags = 'rb'
793 _read_flags = 'rb'
794 _FMT_JPEG = u'jpeg'
794 _FMT_JPEG = u'jpeg'
795 _FMT_PNG = u'png'
795 _FMT_PNG = u'png'
796 _FMT_GIF = u'gif'
796 _FMT_GIF = u'gif'
797 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
797 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
798 _MIMETYPES = {
798 _MIMETYPES = {
799 _FMT_PNG: 'image/png',
799 _FMT_PNG: 'image/png',
800 _FMT_JPEG: 'image/jpeg',
800 _FMT_JPEG: 'image/jpeg',
801 _FMT_GIF: 'image/gif',
801 _FMT_GIF: 'image/gif',
802 }
802 }
803
803
804 def __init__(
804 def __init__(
805 self,
805 self,
806 data=None,
806 data=None,
807 url=None,
807 url=None,
808 filename=None,
808 filename=None,
809 format=None,
809 format=None,
810 embed=None,
810 embed=None,
811 width=None,
811 width=None,
812 height=None,
812 height=None,
813 retina=False,
813 retina=False,
814 unconfined=False,
814 unconfined=False,
815 metadata=None,
815 metadata=None,
816 alt=None,
816 alt=None,
817 ):
817 ):
818 """Create a PNG/JPEG/GIF image object given raw data.
818 """Create a PNG/JPEG/GIF image object given raw data.
819
819
820 When this object is returned by an input cell or passed to the
820 When this object is returned by an input cell or passed to the
821 display function, it will result in the image being displayed
821 display function, it will result in the image being displayed
822 in the frontend.
822 in the frontend.
823
823
824 Parameters
824 Parameters
825 ----------
825 ----------
826 data : unicode, str or bytes
826 data : unicode, str or bytes
827 The raw image data or a URL or filename to load the data from.
827 The raw image data or a URL or filename to load the data from.
828 This always results in embedded image data.
828 This always results in embedded image data.
829
829
830 url : unicode
830 url : unicode
831 A URL to download the data from. If you specify `url=`,
831 A URL to download the data from. If you specify `url=`,
832 the image data will not be embedded unless you also specify `embed=True`.
832 the image data will not be embedded unless you also specify `embed=True`.
833
833
834 filename : unicode
834 filename : unicode
835 Path to a local file to load the data from.
835 Path to a local file to load the data from.
836 Images from a file are always embedded.
836 Images from a file are always embedded.
837
837
838 format : unicode
838 format : unicode
839 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
839 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
840 for format will be inferred from the filename extension.
840 for format will be inferred from the filename extension.
841
841
842 embed : bool
842 embed : bool
843 Should the image data be embedded using a data URI (True) or be
843 Should the image data be embedded using a data URI (True) or be
844 loaded using an <img> tag. Set this to True if you want the image
844 loaded using an <img> tag. Set this to True if you want the image
845 to be viewable later with no internet connection in the notebook.
845 to be viewable later with no internet connection in the notebook.
846
846
847 Default is `True`, unless the keyword argument `url` is set, then
847 Default is `True`, unless the keyword argument `url` is set, then
848 default value is `False`.
848 default value is `False`.
849
849
850 Note that QtConsole is not able to display images if `embed` is set to `False`
850 Note that QtConsole is not able to display images if `embed` is set to `False`
851
851
852 width : int
852 width : int
853 Width in pixels to which to constrain the image in html
853 Width in pixels to which to constrain the image in html
854
854
855 height : int
855 height : int
856 Height in pixels to which to constrain the image in html
856 Height in pixels to which to constrain the image in html
857
857
858 retina : bool
858 retina : bool
859 Automatically set the width and height to half of the measured
859 Automatically set the width and height to half of the measured
860 width and height.
860 width and height.
861 This only works for embedded images because it reads the width/height
861 This only works for embedded images because it reads the width/height
862 from image data.
862 from image data.
863 For non-embedded images, you can just set the desired display width
863 For non-embedded images, you can just set the desired display width
864 and height directly.
864 and height directly.
865
865
866 unconfined : bool
866 unconfined : bool
867 Set unconfined=True to disable max-width confinement of the image.
867 Set unconfined=True to disable max-width confinement of the image.
868
868
869 metadata : dict
869 metadata : dict
870 Specify extra metadata to attach to the image.
870 Specify extra metadata to attach to the image.
871
871
872 alt : unicode
872 alt : unicode
873 Alternative text for the image, for use by screen readers.
873 Alternative text for the image, for use by screen readers.
874
874
875 Examples
875 Examples
876 --------
876 --------
877 embedded image data, works in qtconsole and notebook
877 embedded image data, works in qtconsole and notebook
878 when passed positionally, the first arg can be any of raw image data,
878 when passed positionally, the first arg can be any of raw image data,
879 a URL, or a filename from which to load image data.
879 a URL, or a filename from which to load image data.
880 The result is always embedding image data for inline images.
880 The result is always embedding image data for inline images.
881
881
882 >>> Image('http://www.google.fr/images/srpr/logo3w.png')
882 >>> Image('http://www.google.fr/images/srpr/logo3w.png')
883 <IPython.core.display.Image object>
883 <IPython.core.display.Image object>
884
884
885 >>> Image('/path/to/image.jpg')
885 >>> Image('/path/to/image.jpg')
886 <IPython.core.display.Image object>
886 <IPython.core.display.Image object>
887
887
888 >>> Image(b'RAW_PNG_DATA...')
888 >>> Image(b'RAW_PNG_DATA...')
889 <IPython.core.display.Image object>
889 <IPython.core.display.Image object>
890
890
891 Specifying Image(url=...) does not embed the image data,
891 Specifying Image(url=...) does not embed the image data,
892 it only generates ``<img>`` tag with a link to the source.
892 it only generates ``<img>`` tag with a link to the source.
893 This will not work in the qtconsole or offline.
893 This will not work in the qtconsole or offline.
894
894
895 >>> Image(url='http://www.google.fr/images/srpr/logo3w.png')
895 >>> Image(url='http://www.google.fr/images/srpr/logo3w.png')
896 <IPython.core.display.Image object>
896 <IPython.core.display.Image object>
897
897
898 """
898 """
899 if isinstance(data, (Path, PurePath)):
899 if isinstance(data, (Path, PurePath)):
900 data = str(data)
900 data = str(data)
901
901
902 if filename is not None:
902 if filename is not None:
903 ext = self._find_ext(filename)
903 ext = self._find_ext(filename)
904 elif url is not None:
904 elif url is not None:
905 ext = self._find_ext(url)
905 ext = self._find_ext(url)
906 elif data is None:
906 elif data is None:
907 raise ValueError("No image data found. Expecting filename, url, or data.")
907 raise ValueError("No image data found. Expecting filename, url, or data.")
908 elif isinstance(data, str) and (
908 elif isinstance(data, str) and (
909 data.startswith('http') or _safe_exists(data)
909 data.startswith('http') or _safe_exists(data)
910 ):
910 ):
911 ext = self._find_ext(data)
911 ext = self._find_ext(data)
912 else:
912 else:
913 ext = None
913 ext = None
914
914
915 if format is None:
915 if format is None:
916 if ext is not None:
916 if ext is not None:
917 if ext == u'jpg' or ext == u'jpeg':
917 if ext == u'jpg' or ext == u'jpeg':
918 format = self._FMT_JPEG
918 format = self._FMT_JPEG
919 elif ext == u'png':
919 elif ext == u'png':
920 format = self._FMT_PNG
920 format = self._FMT_PNG
921 elif ext == u'gif':
921 elif ext == u'gif':
922 format = self._FMT_GIF
922 format = self._FMT_GIF
923 else:
923 else:
924 format = ext.lower()
924 format = ext.lower()
925 elif isinstance(data, bytes):
925 elif isinstance(data, bytes):
926 # infer image type from image data header,
926 # infer image type from image data header,
927 # only if format has not been specified.
927 # only if format has not been specified.
928 if data[:2] == _JPEG:
928 if data[:2] == _JPEG:
929 format = self._FMT_JPEG
929 format = self._FMT_JPEG
930
930
931 # failed to detect format, default png
931 # failed to detect format, default png
932 if format is None:
932 if format is None:
933 format = self._FMT_PNG
933 format = self._FMT_PNG
934
934
935 if format.lower() == 'jpg':
935 if format.lower() == 'jpg':
936 # jpg->jpeg
936 # jpg->jpeg
937 format = self._FMT_JPEG
937 format = self._FMT_JPEG
938
938
939 self.format = format.lower()
939 self.format = format.lower()
940 self.embed = embed if embed is not None else (url is None)
940 self.embed = embed if embed is not None else (url is None)
941
941
942 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
942 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
943 raise ValueError("Cannot embed the '%s' image format" % (self.format))
943 raise ValueError("Cannot embed the '%s' image format" % (self.format))
944 if self.embed:
944 if self.embed:
945 self._mimetype = self._MIMETYPES.get(self.format)
945 self._mimetype = self._MIMETYPES.get(self.format)
946
946
947 self.width = width
947 self.width = width
948 self.height = height
948 self.height = height
949 self.retina = retina
949 self.retina = retina
950 self.unconfined = unconfined
950 self.unconfined = unconfined
951 self.alt = alt
951 self.alt = alt
952 super(Image, self).__init__(data=data, url=url, filename=filename,
952 super(Image, self).__init__(data=data, url=url, filename=filename,
953 metadata=metadata)
953 metadata=metadata)
954
954
955 if self.width is None and self.metadata.get('width', {}):
955 if self.width is None and self.metadata.get('width', {}):
956 self.width = metadata['width']
956 self.width = metadata['width']
957
957
958 if self.height is None and self.metadata.get('height', {}):
958 if self.height is None and self.metadata.get('height', {}):
959 self.height = metadata['height']
959 self.height = metadata['height']
960
960
961 if self.alt is None and self.metadata.get("alt", {}):
961 if self.alt is None and self.metadata.get("alt", {}):
962 self.alt = metadata["alt"]
962 self.alt = metadata["alt"]
963
963
964 if retina:
964 if retina:
965 self._retina_shape()
965 self._retina_shape()
966
966
967
967
968 def _retina_shape(self):
968 def _retina_shape(self):
969 """load pixel-doubled width and height from image data"""
969 """load pixel-doubled width and height from image data"""
970 if not self.embed:
970 if not self.embed:
971 return
971 return
972 if self.format == self._FMT_PNG:
972 if self.format == self._FMT_PNG:
973 w, h = _pngxy(self.data)
973 w, h = _pngxy(self.data)
974 elif self.format == self._FMT_JPEG:
974 elif self.format == self._FMT_JPEG:
975 w, h = _jpegxy(self.data)
975 w, h = _jpegxy(self.data)
976 elif self.format == self._FMT_GIF:
976 elif self.format == self._FMT_GIF:
977 w, h = _gifxy(self.data)
977 w, h = _gifxy(self.data)
978 else:
978 else:
979 # retina only supports png
979 # retina only supports png
980 return
980 return
981 self.width = w // 2
981 self.width = w // 2
982 self.height = h // 2
982 self.height = h // 2
983
983
984 def reload(self):
984 def reload(self):
985 """Reload the raw data from file or URL."""
985 """Reload the raw data from file or URL."""
986 if self.embed:
986 if self.embed:
987 super(Image,self).reload()
987 super(Image,self).reload()
988 if self.retina:
988 if self.retina:
989 self._retina_shape()
989 self._retina_shape()
990
990
991 def _repr_html_(self):
991 def _repr_html_(self):
992 if not self.embed:
992 if not self.embed:
993 width = height = klass = alt = ""
993 width = height = klass = alt = ""
994 if self.width:
994 if self.width:
995 width = ' width="%d"' % self.width
995 width = ' width="%d"' % self.width
996 if self.height:
996 if self.height:
997 height = ' height="%d"' % self.height
997 height = ' height="%d"' % self.height
998 if self.unconfined:
998 if self.unconfined:
999 klass = ' class="unconfined"'
999 klass = ' class="unconfined"'
1000 if self.alt:
1000 if self.alt:
1001 alt = ' alt="%s"' % html.escape(self.alt)
1001 alt = ' alt="%s"' % html.escape(self.alt)
1002 return '<img src="{url}"{width}{height}{klass}{alt}/>'.format(
1002 return '<img src="{url}"{width}{height}{klass}{alt}/>'.format(
1003 url=self.url,
1003 url=self.url,
1004 width=width,
1004 width=width,
1005 height=height,
1005 height=height,
1006 klass=klass,
1006 klass=klass,
1007 alt=alt,
1007 alt=alt,
1008 )
1008 )
1009
1009
1010 def _repr_mimebundle_(self, include=None, exclude=None):
1010 def _repr_mimebundle_(self, include=None, exclude=None):
1011 """Return the image as a mimebundle
1011 """Return the image as a mimebundle
1012
1012
1013 Any new mimetype support should be implemented here.
1013 Any new mimetype support should be implemented here.
1014 """
1014 """
1015 if self.embed:
1015 if self.embed:
1016 mimetype = self._mimetype
1016 mimetype = self._mimetype
1017 data, metadata = self._data_and_metadata(always_both=True)
1017 data, metadata = self._data_and_metadata(always_both=True)
1018 if metadata:
1018 if metadata:
1019 metadata = {mimetype: metadata}
1019 metadata = {mimetype: metadata}
1020 return {mimetype: data}, metadata
1020 return {mimetype: data}, metadata
1021 else:
1021 else:
1022 return {'text/html': self._repr_html_()}
1022 return {'text/html': self._repr_html_()}
1023
1023
1024 def _data_and_metadata(self, always_both=False):
1024 def _data_and_metadata(self, always_both=False):
1025 """shortcut for returning metadata with shape information, if defined"""
1025 """shortcut for returning metadata with shape information, if defined"""
1026 try:
1026 try:
1027 b64_data = b2a_base64(self.data).decode('ascii')
1027 b64_data = b2a_base64(self.data).decode('ascii')
1028 except TypeError as e:
1028 except TypeError as e:
1029 raise FileNotFoundError(
1029 raise FileNotFoundError(
1030 "No such file or directory: '%s'" % (self.data)) from e
1030 "No such file or directory: '%s'" % (self.data)) from e
1031 md = {}
1031 md = {}
1032 if self.metadata:
1032 if self.metadata:
1033 md.update(self.metadata)
1033 md.update(self.metadata)
1034 if self.width:
1034 if self.width:
1035 md['width'] = self.width
1035 md['width'] = self.width
1036 if self.height:
1036 if self.height:
1037 md['height'] = self.height
1037 md['height'] = self.height
1038 if self.unconfined:
1038 if self.unconfined:
1039 md['unconfined'] = self.unconfined
1039 md['unconfined'] = self.unconfined
1040 if self.alt:
1040 if self.alt:
1041 md["alt"] = self.alt
1041 md["alt"] = self.alt
1042 if md or always_both:
1042 if md or always_both:
1043 return b64_data, md
1043 return b64_data, md
1044 else:
1044 else:
1045 return b64_data
1045 return b64_data
1046
1046
1047 def _repr_png_(self):
1047 def _repr_png_(self):
1048 if self.embed and self.format == self._FMT_PNG:
1048 if self.embed and self.format == self._FMT_PNG:
1049 return self._data_and_metadata()
1049 return self._data_and_metadata()
1050
1050
1051 def _repr_jpeg_(self):
1051 def _repr_jpeg_(self):
1052 if self.embed and self.format == self._FMT_JPEG:
1052 if self.embed and self.format == self._FMT_JPEG:
1053 return self._data_and_metadata()
1053 return self._data_and_metadata()
1054
1054
1055 def _find_ext(self, s):
1055 def _find_ext(self, s):
1056 base, ext = splitext(s)
1056 base, ext = splitext(s)
1057
1057
1058 if not ext:
1058 if not ext:
1059 return base
1059 return base
1060
1060
1061 # `splitext` includes leading period, so we skip it
1061 # `splitext` includes leading period, so we skip it
1062 return ext[1:].lower()
1062 return ext[1:].lower()
1063
1063
1064
1064
1065 class Video(DisplayObject):
1065 class Video(DisplayObject):
1066
1066
1067 def __init__(self, data=None, url=None, filename=None, embed=False,
1067 def __init__(self, data=None, url=None, filename=None, embed=False,
1068 mimetype=None, width=None, height=None, html_attributes="controls"):
1068 mimetype=None, width=None, height=None, html_attributes="controls"):
1069 """Create a video object given raw data or an URL.
1069 """Create a video object given raw data or an URL.
1070
1070
1071 When this object is returned by an input cell or passed to the
1071 When this object is returned by an input cell or passed to the
1072 display function, it will result in the video being displayed
1072 display function, it will result in the video being displayed
1073 in the frontend.
1073 in the frontend.
1074
1074
1075 Parameters
1075 Parameters
1076 ----------
1076 ----------
1077 data : unicode, str or bytes
1077 data : unicode, str or bytes
1078 The raw video data or a URL or filename to load the data from.
1078 The raw video data or a URL or filename to load the data from.
1079 Raw data will require passing ``embed=True``.
1079 Raw data will require passing ``embed=True``.
1080
1080
1081 url : unicode
1081 url : unicode
1082 A URL for the video. If you specify ``url=``,
1082 A URL for the video. If you specify ``url=``,
1083 the image data will not be embedded.
1083 the image data will not be embedded.
1084
1084
1085 filename : unicode
1085 filename : unicode
1086 Path to a local file containing the video.
1086 Path to a local file containing the video.
1087 Will be interpreted as a local URL unless ``embed=True``.
1087 Will be interpreted as a local URL unless ``embed=True``.
1088
1088
1089 embed : bool
1089 embed : bool
1090 Should the video be embedded using a data URI (True) or be
1090 Should the video be embedded using a data URI (True) or be
1091 loaded using a <video> tag (False).
1091 loaded using a <video> tag (False).
1092
1092
1093 Since videos are large, embedding them should be avoided, if possible.
1093 Since videos are large, embedding them should be avoided, if possible.
1094 You must confirm embedding as your intention by passing ``embed=True``.
1094 You must confirm embedding as your intention by passing ``embed=True``.
1095
1095
1096 Local files can be displayed with URLs without embedding the content, via::
1096 Local files can be displayed with URLs without embedding the content, via::
1097
1097
1098 Video('./video.mp4')
1098 Video('./video.mp4')
1099
1099
1100 mimetype : unicode
1100 mimetype : unicode
1101 Specify the mimetype for embedded videos.
1101 Specify the mimetype for embedded videos.
1102 Default will be guessed from file extension, if available.
1102 Default will be guessed from file extension, if available.
1103
1103
1104 width : int
1104 width : int
1105 Width in pixels to which to constrain the video in HTML.
1105 Width in pixels to which to constrain the video in HTML.
1106 If not supplied, defaults to the width of the video.
1106 If not supplied, defaults to the width of the video.
1107
1107
1108 height : int
1108 height : int
1109 Height in pixels to which to constrain the video in html.
1109 Height in pixels to which to constrain the video in html.
1110 If not supplied, defaults to the height of the video.
1110 If not supplied, defaults to the height of the video.
1111
1111
1112 html_attributes : str
1112 html_attributes : str
1113 Attributes for the HTML ``<video>`` block.
1113 Attributes for the HTML ``<video>`` block.
1114 Default: ``"controls"`` to get video controls.
1114 Default: ``"controls"`` to get video controls.
1115 Other examples: ``"controls muted"`` for muted video with controls,
1115 Other examples: ``"controls muted"`` for muted video with controls,
1116 ``"loop autoplay"`` for looping autoplaying video without controls.
1116 ``"loop autoplay"`` for looping autoplaying video without controls.
1117
1117
1118 Examples
1118 Examples
1119 --------
1119 --------
1120 ::
1120 ::
1121
1121
1122 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1122 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1123 Video('path/to/video.mp4')
1123 Video('path/to/video.mp4')
1124 Video('path/to/video.mp4', embed=True)
1124 Video('path/to/video.mp4', embed=True)
1125 Video('path/to/video.mp4', embed=True, html_attributes="controls muted autoplay")
1125 Video('path/to/video.mp4', embed=True, html_attributes="controls muted autoplay")
1126 Video(b'raw-videodata', embed=True)
1126 Video(b'raw-videodata', embed=True)
1127 """
1127 """
1128 if isinstance(data, (Path, PurePath)):
1128 if isinstance(data, (Path, PurePath)):
1129 data = str(data)
1129 data = str(data)
1130
1130
1131 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1131 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1132 url = data
1132 url = data
1133 data = None
1133 data = None
1134 elif data is not None and os.path.exists(data):
1134 elif data is not None and os.path.exists(data):
1135 filename = data
1135 filename = data
1136 data = None
1136 data = None
1137
1137
1138 if data and not embed:
1138 if data and not embed:
1139 msg = ''.join([
1139 msg = ''.join([
1140 "To embed videos, you must pass embed=True ",
1140 "To embed videos, you must pass embed=True ",
1141 "(this may make your notebook files huge)\n",
1141 "(this may make your notebook files huge)\n",
1142 "Consider passing Video(url='...')",
1142 "Consider passing Video(url='...')",
1143 ])
1143 ])
1144 raise ValueError(msg)
1144 raise ValueError(msg)
1145
1145
1146 self.mimetype = mimetype
1146 self.mimetype = mimetype
1147 self.embed = embed
1147 self.embed = embed
1148 self.width = width
1148 self.width = width
1149 self.height = height
1149 self.height = height
1150 self.html_attributes = html_attributes
1150 self.html_attributes = html_attributes
1151 super(Video, self).__init__(data=data, url=url, filename=filename)
1151 super(Video, self).__init__(data=data, url=url, filename=filename)
1152
1152
1153 def _repr_html_(self):
1153 def _repr_html_(self):
1154 width = height = ''
1154 width = height = ''
1155 if self.width:
1155 if self.width:
1156 width = ' width="%d"' % self.width
1156 width = ' width="%d"' % self.width
1157 if self.height:
1157 if self.height:
1158 height = ' height="%d"' % self.height
1158 height = ' height="%d"' % self.height
1159
1159
1160 # External URLs and potentially local files are not embedded into the
1160 # External URLs and potentially local files are not embedded into the
1161 # notebook output.
1161 # notebook output.
1162 if not self.embed:
1162 if not self.embed:
1163 url = self.url if self.url is not None else self.filename
1163 url = self.url if self.url is not None else self.filename
1164 output = """<video src="{0}" {1} {2} {3}>
1164 output = """<video src="{0}" {1} {2} {3}>
1165 Your browser does not support the <code>video</code> element.
1165 Your browser does not support the <code>video</code> element.
1166 </video>""".format(url, self.html_attributes, width, height)
1166 </video>""".format(url, self.html_attributes, width, height)
1167 return output
1167 return output
1168
1168
1169 # Embedded videos are base64-encoded.
1169 # Embedded videos are base64-encoded.
1170 mimetype = self.mimetype
1170 mimetype = self.mimetype
1171 if self.filename is not None:
1171 if self.filename is not None:
1172 if not mimetype:
1172 if not mimetype:
1173 mimetype, _ = mimetypes.guess_type(self.filename)
1173 mimetype, _ = mimetypes.guess_type(self.filename)
1174
1174
1175 with open(self.filename, 'rb') as f:
1175 with open(self.filename, 'rb') as f:
1176 video = f.read()
1176 video = f.read()
1177 else:
1177 else:
1178 video = self.data
1178 video = self.data
1179 if isinstance(video, str):
1179 if isinstance(video, str):
1180 # unicode input is already b64-encoded
1180 # unicode input is already b64-encoded
1181 b64_video = video
1181 b64_video = video
1182 else:
1182 else:
1183 b64_video = b2a_base64(video).decode('ascii').rstrip()
1183 b64_video = b2a_base64(video).decode('ascii').rstrip()
1184
1184
1185 output = """<video {0} {1} {2}>
1185 output = """<video {0} {1} {2}>
1186 <source src="data:{3};base64,{4}" type="{3}">
1186 <source src="data:{3};base64,{4}" type="{3}">
1187 Your browser does not support the video tag.
1187 Your browser does not support the video tag.
1188 </video>""".format(self.html_attributes, width, height, mimetype, b64_video)
1188 </video>""".format(self.html_attributes, width, height, mimetype, b64_video)
1189 return output
1189 return output
1190
1190
1191 def reload(self):
1191 def reload(self):
1192 # TODO
1192 # TODO
1193 pass
1193 pass
1194
1194
1195
1195
1196 @skip_doctest
1196 @skip_doctest
1197 def set_matplotlib_formats(*formats, **kwargs):
1197 def set_matplotlib_formats(*formats, **kwargs):
1198 """
1198 """
1199 .. deprecated:: 7.23
1199 .. deprecated:: 7.23
1200
1200
1201 use `matplotlib_inline.backend_inline.set_matplotlib_formats()`
1201 use `matplotlib_inline.backend_inline.set_matplotlib_formats()`
1202
1202
1203 Select figure formats for the inline backend. Optionally pass quality for JPEG.
1203 Select figure formats for the inline backend. Optionally pass quality for JPEG.
1204
1204
1205 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1205 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1206
1206
1207 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1207 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1208
1208
1209 To set this in your config files use the following::
1209 To set this in your config files use the following::
1210
1210
1211 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1211 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1212 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1212 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1213
1213
1214 Parameters
1214 Parameters
1215 ----------
1215 ----------
1216 *formats : strs
1216 *formats : strs
1217 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1217 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1218 **kwargs
1218 **kwargs
1219 Keyword args will be relayed to ``figure.canvas.print_figure``.
1219 Keyword args will be relayed to ``figure.canvas.print_figure``.
1220 """
1220 """
1221 warnings.warn(
1221 warnings.warn(
1222 "`set_matplotlib_formats` is deprecated since IPython 7.23, directly "
1222 "`set_matplotlib_formats` is deprecated since IPython 7.23, directly "
1223 "use `matplotlib_inline.backend_inline.set_matplotlib_formats()`",
1223 "use `matplotlib_inline.backend_inline.set_matplotlib_formats()`",
1224 DeprecationWarning,
1224 DeprecationWarning,
1225 stacklevel=2,
1225 stacklevel=2,
1226 )
1226 )
1227
1227
1228 from matplotlib_inline.backend_inline import (
1228 from matplotlib_inline.backend_inline import (
1229 set_matplotlib_formats as set_matplotlib_formats_orig,
1229 set_matplotlib_formats as set_matplotlib_formats_orig,
1230 )
1230 )
1231
1231
1232 set_matplotlib_formats_orig(*formats, **kwargs)
1232 set_matplotlib_formats_orig(*formats, **kwargs)
1233
1233
1234 @skip_doctest
1234 @skip_doctest
1235 def set_matplotlib_close(close=True):
1235 def set_matplotlib_close(close=True):
1236 """
1236 """
1237 .. deprecated:: 7.23
1237 .. deprecated:: 7.23
1238
1238
1239 use `matplotlib_inline.backend_inline.set_matplotlib_close()`
1239 use `matplotlib_inline.backend_inline.set_matplotlib_close()`
1240
1240
1241 Set whether the inline backend closes all figures automatically or not.
1241 Set whether the inline backend closes all figures automatically or not.
1242
1242
1243 By default, the inline backend used in the IPython Notebook will close all
1243 By default, the inline backend used in the IPython Notebook will close all
1244 matplotlib figures automatically after each cell is run. This means that
1244 matplotlib figures automatically after each cell is run. This means that
1245 plots in different cells won't interfere. Sometimes, you may want to make
1245 plots in different cells won't interfere. Sometimes, you may want to make
1246 a plot in one cell and then refine it in later cells. This can be accomplished
1246 a plot in one cell and then refine it in later cells. This can be accomplished
1247 by::
1247 by::
1248
1248
1249 In [1]: set_matplotlib_close(False)
1249 In [1]: set_matplotlib_close(False)
1250
1250
1251 To set this in your config files use the following::
1251 To set this in your config files use the following::
1252
1252
1253 c.InlineBackend.close_figures = False
1253 c.InlineBackend.close_figures = False
1254
1254
1255 Parameters
1255 Parameters
1256 ----------
1256 ----------
1257 close : bool
1257 close : bool
1258 Should all matplotlib figures be automatically closed after each cell is
1258 Should all matplotlib figures be automatically closed after each cell is
1259 run?
1259 run?
1260 """
1260 """
1261 warnings.warn(
1261 warnings.warn(
1262 "`set_matplotlib_close` is deprecated since IPython 7.23, directly "
1262 "`set_matplotlib_close` is deprecated since IPython 7.23, directly "
1263 "use `matplotlib_inline.backend_inline.set_matplotlib_close()`",
1263 "use `matplotlib_inline.backend_inline.set_matplotlib_close()`",
1264 DeprecationWarning,
1264 DeprecationWarning,
1265 stacklevel=2,
1265 stacklevel=2,
1266 )
1266 )
1267
1267
1268 from matplotlib_inline.backend_inline import (
1268 from matplotlib_inline.backend_inline import (
1269 set_matplotlib_close as set_matplotlib_close_orig,
1269 set_matplotlib_close as set_matplotlib_close_orig,
1270 )
1270 )
1271
1271
1272 set_matplotlib_close_orig(close)
1272 set_matplotlib_close_orig(close)
General Comments 0
You need to be logged in to leave comments. Login now