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