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