| | |
| | """Top-level display functions for displaying object in different formats.""" |
| |
|
| | |
| | |
| |
|
| |
|
| | from binascii import b2a_base64, hexlify |
| | import html |
| | import json |
| | import mimetypes |
| | import os |
| | import struct |
| | import warnings |
| | from copy import deepcopy |
| | from os.path import splitext |
| | from pathlib import Path, PurePath |
| |
|
| | from IPython.utils.py3compat import cast_unicode |
| | from IPython.testing.skipdoctest import skip_doctest |
| | from . import display_functions |
| |
|
| |
|
| | __all__ = ['display_pretty', 'display_html', 'display_markdown', |
| | 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json', |
| | 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject', |
| | 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON', |
| | 'GeoJSON', 'Javascript', 'Image', 'set_matplotlib_formats', |
| | 'set_matplotlib_close', |
| | 'Video'] |
| |
|
| | _deprecated_names = ["display", "clear_output", "publish_display_data", "update_display", "DisplayHandle"] |
| |
|
| | __all__ = __all__ + _deprecated_names |
| |
|
| |
|
| | |
| |
|
| | from warnings import warn |
| |
|
| |
|
| | def __getattr__(name): |
| | if name in _deprecated_names: |
| | warn(f"Importing {name} from IPython.core.display is deprecated since IPython 7.14, please import from IPython display", DeprecationWarning, stacklevel=2) |
| | return getattr(display_functions, name) |
| |
|
| | if name in globals().keys(): |
| | return globals()[name] |
| | else: |
| | raise AttributeError(f"module {__name__} has no attribute {name}") |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | def _safe_exists(path): |
| | """Check path, but don't let exceptions raise""" |
| | try: |
| | return os.path.exists(path) |
| | except Exception: |
| | return False |
| |
|
| |
|
| | def _display_mimetype(mimetype, objs, raw=False, metadata=None): |
| | """internal implementation of all display_foo methods |
| | |
| | Parameters |
| | ---------- |
| | mimetype : str |
| | The mimetype to be published (e.g. 'image/png') |
| | *objs : object |
| | The Python objects to display, or if raw=True raw text data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | if metadata: |
| | metadata = {mimetype: metadata} |
| | if raw: |
| | |
| | objs = [ {mimetype: obj} for obj in objs ] |
| | display_functions.display(*objs, raw=raw, metadata=metadata, include=[mimetype]) |
| |
|
| | |
| | |
| | |
| |
|
| |
|
| | def display_pretty(*objs, **kwargs): |
| | """Display the pretty (default) representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw text data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('text/plain', objs, **kwargs) |
| |
|
| |
|
| | def display_html(*objs, **kwargs): |
| | """Display the HTML representation of an object. |
| | |
| | Note: If raw=False and the object does not have a HTML |
| | representation, no HTML will be shown. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw HTML data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('text/html', objs, **kwargs) |
| |
|
| |
|
| | def display_markdown(*objs, **kwargs): |
| | """Displays the Markdown representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw markdown data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| |
|
| | _display_mimetype('text/markdown', objs, **kwargs) |
| |
|
| |
|
| | def display_svg(*objs, **kwargs): |
| | """Display the SVG representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw svg data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('image/svg+xml', objs, **kwargs) |
| |
|
| |
|
| | def display_png(*objs, **kwargs): |
| | """Display the PNG representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw png data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('image/png', objs, **kwargs) |
| |
|
| |
|
| | def display_jpeg(*objs, **kwargs): |
| | """Display the JPEG representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw JPEG data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('image/jpeg', objs, **kwargs) |
| |
|
| |
|
| | def display_latex(*objs, **kwargs): |
| | """Display the LaTeX representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw latex data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('text/latex', objs, **kwargs) |
| |
|
| |
|
| | def display_json(*objs, **kwargs): |
| | """Display the JSON representation of an object. |
| | |
| | Note that not many frontends support displaying JSON. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw json data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('application/json', objs, **kwargs) |
| |
|
| |
|
| | def display_javascript(*objs, **kwargs): |
| | """Display the Javascript representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw javascript data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('application/javascript', objs, **kwargs) |
| |
|
| |
|
| | def display_pdf(*objs, **kwargs): |
| | """Display the PDF representation of an object. |
| | |
| | Parameters |
| | ---------- |
| | *objs : object |
| | The Python objects to display, or if raw=True raw javascript data to |
| | display. |
| | raw : bool |
| | Are the data objects raw data or Python objects that need to be |
| | formatted before display? [default: False] |
| | metadata : dict (optional) |
| | Metadata to be associated with the specific mimetype output. |
| | """ |
| | _display_mimetype('application/pdf', objs, **kwargs) |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| |
|
| | class DisplayObject(object): |
| | """An object that wraps data to be displayed.""" |
| |
|
| | _read_flags = 'r' |
| | _show_mem_addr = False |
| | metadata = None |
| |
|
| | def __init__(self, data=None, url=None, filename=None, metadata=None): |
| | """Create a display object given raw data. |
| | |
| | When this object is returned by an expression or passed to the |
| | display function, it will result in the data being displayed |
| | in the frontend. The MIME type of the data should match the |
| | subclasses used, so the Png subclass should be used for 'image/png' |
| | data. If the data is a URL, the data will first be downloaded |
| | and then displayed. If |
| | |
| | Parameters |
| | ---------- |
| | data : unicode, str or bytes |
| | The raw data or a URL or file to load the data from |
| | url : unicode |
| | A URL to download the data from. |
| | filename : unicode |
| | Path to a local file to load the data from. |
| | metadata : dict |
| | Dict of metadata associated to be the object when displayed |
| | """ |
| | if isinstance(data, (Path, PurePath)): |
| | data = str(data) |
| |
|
| | if data is not None and isinstance(data, str): |
| | if data.startswith('http') and url is None: |
| | url = data |
| | filename = None |
| | data = None |
| | elif _safe_exists(data) and filename is None: |
| | url = None |
| | filename = data |
| | data = None |
| |
|
| | self.url = url |
| | self.filename = filename |
| | |
| | |
| | |
| | self.data = data |
| |
|
| | if metadata is not None: |
| | self.metadata = metadata |
| | elif self.metadata is None: |
| | self.metadata = {} |
| |
|
| | self.reload() |
| | self._check_data() |
| |
|
| | def __repr__(self): |
| | if not self._show_mem_addr: |
| | cls = self.__class__ |
| | r = "<%s.%s object>" % (cls.__module__, cls.__name__) |
| | else: |
| | r = super(DisplayObject, self).__repr__() |
| | return r |
| |
|
| | def _check_data(self): |
| | """Override in subclasses if there's something to check.""" |
| | pass |
| |
|
| | def _data_and_metadata(self): |
| | """shortcut for returning metadata with shape information, if defined""" |
| | if self.metadata: |
| | return self.data, deepcopy(self.metadata) |
| | else: |
| | return self.data |
| |
|
| | def reload(self): |
| | """Reload the raw data from file or URL.""" |
| | if self.filename is not None: |
| | encoding = None if "b" in self._read_flags else "utf-8" |
| | with open(self.filename, self._read_flags, encoding=encoding) as f: |
| | self.data = f.read() |
| | elif self.url is not None: |
| | |
| | from urllib.request import urlopen |
| | response = urlopen(self.url) |
| | data = response.read() |
| | |
| | encoding = None |
| | if 'content-type' in response.headers: |
| | for sub in response.headers['content-type'].split(';'): |
| | sub = sub.strip() |
| | if sub.startswith('charset'): |
| | encoding = sub.split('=')[-1].strip() |
| | break |
| | if 'content-encoding' in response.headers: |
| | |
| | if 'gzip' in response.headers['content-encoding']: |
| | import gzip |
| | from io import BytesIO |
| |
|
| | |
| | with gzip.open( |
| | BytesIO(data), "rt", encoding=encoding or "utf-8" |
| | ) as fp: |
| | encoding = None |
| | data = fp.read() |
| |
|
| | |
| | |
| | |
| | |
| | if encoding: |
| | self.data = data.decode(encoding, 'replace') |
| | else: |
| | self.data = data |
| |
|
| |
|
| | class TextDisplayObject(DisplayObject): |
| | """Create a text display object given raw data. |
| | |
| | Parameters |
| | ---------- |
| | data : str or unicode |
| | The raw data or a URL or file to load the data from. |
| | url : unicode |
| | A URL to download the data from. |
| | filename : unicode |
| | Path to a local file to load the data from. |
| | metadata : dict |
| | Dict of metadata associated to be the object when displayed |
| | """ |
| | def _check_data(self): |
| | if self.data is not None and not isinstance(self.data, str): |
| | raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data)) |
| |
|
| | class Pretty(TextDisplayObject): |
| |
|
| | def _repr_pretty_(self, pp, cycle): |
| | return pp.text(self.data) |
| |
|
| |
|
| | class HTML(TextDisplayObject): |
| |
|
| | def __init__(self, data=None, url=None, filename=None, metadata=None): |
| | def warn(): |
| | if not data: |
| | return False |
| |
|
| | |
| | |
| | |
| | |
| | prefix = data[:10].lower() |
| | suffix = data[-10:].lower() |
| | return prefix.startswith("<iframe ") and suffix.endswith("</iframe>") |
| |
|
| | if warn(): |
| | warnings.warn("Consider using IPython.display.IFrame instead") |
| | super(HTML, self).__init__(data=data, url=url, filename=filename, metadata=metadata) |
| |
|
| | def _repr_html_(self): |
| | return self._data_and_metadata() |
| |
|
| | def __html__(self): |
| | """ |
| | This method exists to inform other HTML-using modules (e.g. Markupsafe, |
| | htmltag, etc) that this object is HTML and does not need things like |
| | special characters (<>&) escaped. |
| | """ |
| | return self._repr_html_() |
| |
|
| |
|
| | class Markdown(TextDisplayObject): |
| |
|
| | def _repr_markdown_(self): |
| | return self._data_and_metadata() |
| |
|
| |
|
| | class Math(TextDisplayObject): |
| |
|
| | def _repr_latex_(self): |
| | s = r"$\displaystyle %s$" % self.data.strip('$') |
| | if self.metadata: |
| | return s, deepcopy(self.metadata) |
| | else: |
| | return s |
| |
|
| |
|
| | class Latex(TextDisplayObject): |
| |
|
| | def _repr_latex_(self): |
| | return self._data_and_metadata() |
| |
|
| |
|
| | class SVG(DisplayObject): |
| | """Embed an SVG into the display. |
| | |
| | Note if you just want to view a svg image via a URL use `:class:Image` with |
| | a url=URL keyword argument. |
| | """ |
| |
|
| | _read_flags = 'rb' |
| | |
| | |
| | _data = None |
| |
|
| | @property |
| | def data(self): |
| | return self._data |
| |
|
| | @data.setter |
| | def data(self, svg): |
| | if svg is None: |
| | self._data = None |
| | return |
| | |
| | from xml.dom import minidom |
| | x = minidom.parseString(svg) |
| | |
| | found_svg = x.getElementsByTagName('svg') |
| | if found_svg: |
| | svg = found_svg[0].toxml() |
| | else: |
| | |
| | |
| | pass |
| | svg = cast_unicode(svg) |
| | self._data = svg |
| |
|
| | def _repr_svg_(self): |
| | return self._data_and_metadata() |
| |
|
| | class ProgressBar(DisplayObject): |
| | """Progressbar supports displaying a progressbar like element |
| | """ |
| | def __init__(self, total): |
| | """Creates a new progressbar |
| | |
| | Parameters |
| | ---------- |
| | total : int |
| | maximum size of the progressbar |
| | """ |
| | self.total = total |
| | self._progress = 0 |
| | self.html_width = '60ex' |
| | self.text_width = 60 |
| | self._display_id = hexlify(os.urandom(8)).decode('ascii') |
| |
|
| | def __repr__(self): |
| | fraction = self.progress / self.total |
| | filled = '=' * int(fraction * self.text_width) |
| | rest = ' ' * (self.text_width - len(filled)) |
| | return '[{}{}] {}/{}'.format( |
| | filled, rest, |
| | self.progress, self.total, |
| | ) |
| |
|
| | def _repr_html_(self): |
| | return "<progress style='width:{}' max='{}' value='{}'></progress>".format( |
| | self.html_width, self.total, self.progress) |
| |
|
| | def display(self): |
| | display_functions.display(self, display_id=self._display_id) |
| |
|
| | def update(self): |
| | display_functions.display(self, display_id=self._display_id, update=True) |
| |
|
| | @property |
| | def progress(self): |
| | return self._progress |
| |
|
| | @progress.setter |
| | def progress(self, value): |
| | self._progress = value |
| | self.update() |
| |
|
| | def __iter__(self): |
| | self.display() |
| | self._progress = -1 |
| | return self |
| |
|
| | def __next__(self): |
| | """Returns current value and increments display by one.""" |
| | self.progress += 1 |
| | if self.progress < self.total: |
| | return self.progress |
| | else: |
| | raise StopIteration() |
| |
|
| | class JSON(DisplayObject): |
| | """JSON expects a JSON-able dict or list |
| | |
| | not an already-serialized JSON string. |
| | |
| | Scalar types (None, number, string) are not allowed, only dict or list containers. |
| | """ |
| | |
| | _data = None |
| | def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs): |
| | """Create a JSON display object given raw data. |
| | |
| | Parameters |
| | ---------- |
| | data : dict or list |
| | JSON data to display. Not an already-serialized JSON string. |
| | Scalar types (None, number, string) are not allowed, only dict |
| | or list containers. |
| | url : unicode |
| | A URL to download the data from. |
| | filename : unicode |
| | Path to a local file to load the data from. |
| | expanded : boolean |
| | Metadata to control whether a JSON display component is expanded. |
| | metadata : dict |
| | Specify extra metadata to attach to the json display object. |
| | root : str |
| | The name of the root element of the JSON tree |
| | """ |
| | self.metadata = { |
| | 'expanded': expanded, |
| | 'root': root, |
| | } |
| | if metadata: |
| | self.metadata.update(metadata) |
| | if kwargs: |
| | self.metadata.update(kwargs) |
| | super(JSON, self).__init__(data=data, url=url, filename=filename) |
| |
|
| | def _check_data(self): |
| | if self.data is not None and not isinstance(self.data, (dict, list)): |
| | raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data)) |
| |
|
| | @property |
| | def data(self): |
| | return self._data |
| |
|
| | @data.setter |
| | def data(self, data): |
| | if isinstance(data, (Path, PurePath)): |
| | data = str(data) |
| |
|
| | if isinstance(data, str): |
| | if self.filename is None and self.url is None: |
| | warnings.warn("JSON expects JSONable dict or list, not JSON strings") |
| | data = json.loads(data) |
| | self._data = data |
| |
|
| | def _data_and_metadata(self): |
| | return self.data, self.metadata |
| |
|
| | def _repr_json_(self): |
| | return self._data_and_metadata() |
| |
|
| |
|
| | _css_t = """var link = document.createElement("link"); |
| | link.rel = "stylesheet"; |
| | link.type = "text/css"; |
| | link.href = "%s"; |
| | document.head.appendChild(link); |
| | """ |
| |
|
| | _lib_t1 = """new Promise(function(resolve, reject) { |
| | var script = document.createElement("script"); |
| | script.onload = resolve; |
| | script.onerror = reject; |
| | script.src = "%s"; |
| | document.head.appendChild(script); |
| | }).then(() => { |
| | """ |
| |
|
| | _lib_t2 = """ |
| | });""" |
| |
|
| | class GeoJSON(JSON): |
| | """GeoJSON expects JSON-able dict |
| | |
| | not an already-serialized JSON string. |
| | |
| | Scalar types (None, number, string) are not allowed, only dict containers. |
| | """ |
| |
|
| | def __init__(self, *args, **kwargs): |
| | """Create a GeoJSON display object given raw data. |
| | |
| | Parameters |
| | ---------- |
| | data : dict or list |
| | VegaLite data. Not an already-serialized JSON string. |
| | Scalar types (None, number, string) are not allowed, only dict |
| | or list containers. |
| | url_template : string |
| | Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template |
| | layer_options : dict |
| | Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options |
| | url : unicode |
| | A URL to download the data from. |
| | filename : unicode |
| | Path to a local file to load the data from. |
| | metadata : dict |
| | Specify extra metadata to attach to the json display object. |
| | |
| | Examples |
| | -------- |
| | The following will display an interactive map of Mars with a point of |
| | interest on frontend that do support GeoJSON display. |
| | |
| | >>> from IPython.display import GeoJSON |
| | |
| | >>> GeoJSON(data={ |
| | ... "type": "Feature", |
| | ... "geometry": { |
| | ... "type": "Point", |
| | ... "coordinates": [-81.327, 296.038] |
| | ... } |
| | ... }, |
| | ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png", |
| | ... layer_options={ |
| | ... "basemap_id": "celestia_mars-shaded-16k_global", |
| | ... "attribution" : "Celestia/praesepe", |
| | ... "minZoom" : 0, |
| | ... "maxZoom" : 18, |
| | ... }) |
| | <IPython.core.display.GeoJSON object> |
| | |
| | In the terminal IPython, you will only see the text representation of |
| | the GeoJSON object. |
| | |
| | """ |
| |
|
| | super(GeoJSON, self).__init__(*args, **kwargs) |
| |
|
| |
|
| | def _ipython_display_(self): |
| | bundle = { |
| | 'application/geo+json': self.data, |
| | 'text/plain': '<IPython.display.GeoJSON object>' |
| | } |
| | metadata = { |
| | 'application/geo+json': self.metadata |
| | } |
| | display_functions.display(bundle, metadata=metadata, raw=True) |
| |
|
| | class Javascript(TextDisplayObject): |
| |
|
| | def __init__(self, data=None, url=None, filename=None, lib=None, css=None): |
| | """Create a Javascript display object given raw data. |
| | |
| | When this object is returned by an expression or passed to the |
| | display function, it will result in the data being displayed |
| | in the frontend. If the data is a URL, the data will first be |
| | downloaded and then displayed. |
| | |
| | In the Notebook, the containing element will be available as `element`, |
| | and jQuery will be available. Content appended to `element` will be |
| | visible in the output area. |
| | |
| | Parameters |
| | ---------- |
| | data : unicode, str or bytes |
| | The Javascript source code or a URL to download it from. |
| | url : unicode |
| | A URL to download the data from. |
| | filename : unicode |
| | Path to a local file to load the data from. |
| | lib : list or str |
| | A sequence of Javascript library URLs to load asynchronously before |
| | running the source code. The full URLs of the libraries should |
| | be given. A single Javascript library URL can also be given as a |
| | string. |
| | css : list or str |
| | A sequence of css files to load before running the source code. |
| | The full URLs of the css files should be given. A single css URL |
| | can also be given as a string. |
| | """ |
| | if isinstance(lib, str): |
| | lib = [lib] |
| | elif lib is None: |
| | lib = [] |
| | if isinstance(css, str): |
| | css = [css] |
| | elif css is None: |
| | css = [] |
| | if not isinstance(lib, (list,tuple)): |
| | raise TypeError('expected sequence, got: %r' % lib) |
| | if not isinstance(css, (list,tuple)): |
| | raise TypeError('expected sequence, got: %r' % css) |
| | self.lib = lib |
| | self.css = css |
| | super(Javascript, self).__init__(data=data, url=url, filename=filename) |
| |
|
| | def _repr_javascript_(self): |
| | r = '' |
| | for c in self.css: |
| | r += _css_t % c |
| | for l in self.lib: |
| | r += _lib_t1 % l |
| | r += self.data |
| | r += _lib_t2*len(self.lib) |
| | return r |
| |
|
| | |
| | _PNG = b'\x89PNG\r\n\x1a\n' |
| | _JPEG = b'\xff\xd8' |
| |
|
| | def _pngxy(data): |
| | """read the (width, height) from a PNG header""" |
| | ihdr = data.index(b'IHDR') |
| | |
| | return struct.unpack('>ii', data[ihdr+4:ihdr+12]) |
| |
|
| | def _jpegxy(data): |
| | """read the (width, height) from a JPEG header""" |
| | |
| |
|
| | idx = 4 |
| | while True: |
| | block_size = struct.unpack('>H', data[idx:idx+2])[0] |
| | idx = idx + block_size |
| | if data[idx:idx+2] == b'\xFF\xC0': |
| | |
| | iSOF = idx |
| | break |
| | else: |
| | |
| | idx += 2 |
| |
|
| | h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9]) |
| | return w, h |
| |
|
| | def _gifxy(data): |
| | """read the (width, height) from a GIF header""" |
| | return struct.unpack('<HH', data[6:10]) |
| |
|
| |
|
| | class Image(DisplayObject): |
| |
|
| | _read_flags = 'rb' |
| | _FMT_JPEG = u'jpeg' |
| | _FMT_PNG = u'png' |
| | _FMT_GIF = u'gif' |
| | _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF] |
| | _MIMETYPES = { |
| | _FMT_PNG: 'image/png', |
| | _FMT_JPEG: 'image/jpeg', |
| | _FMT_GIF: 'image/gif', |
| | } |
| |
|
| | def __init__( |
| | self, |
| | data=None, |
| | url=None, |
| | filename=None, |
| | format=None, |
| | embed=None, |
| | width=None, |
| | height=None, |
| | retina=False, |
| | unconfined=False, |
| | metadata=None, |
| | alt=None, |
| | ): |
| | """Create a PNG/JPEG/GIF image object given raw data. |
| | |
| | When this object is returned by an input cell or passed to the |
| | display function, it will result in the image being displayed |
| | in the frontend. |
| | |
| | Parameters |
| | ---------- |
| | data : unicode, str or bytes |
| | The raw image data or a URL or filename to load the data from. |
| | This always results in embedded image data. |
| | |
| | url : unicode |
| | A URL to download the data from. If you specify `url=`, |
| | the image data will not be embedded unless you also specify `embed=True`. |
| | |
| | filename : unicode |
| | Path to a local file to load the data from. |
| | Images from a file are always embedded. |
| | |
| | format : unicode |
| | The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given |
| | for format will be inferred from the filename extension. |
| | |
| | embed : bool |
| | Should the image data be embedded using a data URI (True) or be |
| | loaded using an <img> tag. Set this to True if you want the image |
| | to be viewable later with no internet connection in the notebook. |
| | |
| | Default is `True`, unless the keyword argument `url` is set, then |
| | default value is `False`. |
| | |
| | Note that QtConsole is not able to display images if `embed` is set to `False` |
| | |
| | width : int |
| | Width in pixels to which to constrain the image in html |
| | |
| | height : int |
| | Height in pixels to which to constrain the image in html |
| | |
| | retina : bool |
| | Automatically set the width and height to half of the measured |
| | width and height. |
| | This only works for embedded images because it reads the width/height |
| | from image data. |
| | For non-embedded images, you can just set the desired display width |
| | and height directly. |
| | |
| | unconfined : bool |
| | Set unconfined=True to disable max-width confinement of the image. |
| | |
| | metadata : dict |
| | Specify extra metadata to attach to the image. |
| | |
| | alt : unicode |
| | Alternative text for the image, for use by screen readers. |
| | |
| | Examples |
| | -------- |
| | embedded image data, works in qtconsole and notebook |
| | when passed positionally, the first arg can be any of raw image data, |
| | a URL, or a filename from which to load image data. |
| | The result is always embedding image data for inline images. |
| | |
| | >>> Image('https://www.google.fr/images/srpr/logo3w.png') # doctest: +SKIP |
| | <IPython.core.display.Image object> |
| | |
| | >>> Image('/path/to/image.jpg') |
| | <IPython.core.display.Image object> |
| | |
| | >>> Image(b'RAW_PNG_DATA...') |
| | <IPython.core.display.Image object> |
| | |
| | Specifying Image(url=...) does not embed the image data, |
| | it only generates ``<img>`` tag with a link to the source. |
| | This will not work in the qtconsole or offline. |
| | |
| | >>> Image(url='https://www.google.fr/images/srpr/logo3w.png') |
| | <IPython.core.display.Image object> |
| | |
| | """ |
| | if isinstance(data, (Path, PurePath)): |
| | data = str(data) |
| |
|
| | if filename is not None: |
| | ext = self._find_ext(filename) |
| | elif url is not None: |
| | ext = self._find_ext(url) |
| | elif data is None: |
| | raise ValueError("No image data found. Expecting filename, url, or data.") |
| | elif isinstance(data, str) and ( |
| | data.startswith('http') or _safe_exists(data) |
| | ): |
| | ext = self._find_ext(data) |
| | else: |
| | ext = None |
| |
|
| | if format is None: |
| | if ext is not None: |
| | if ext == u'jpg' or ext == u'jpeg': |
| | format = self._FMT_JPEG |
| | elif ext == u'png': |
| | format = self._FMT_PNG |
| | elif ext == u'gif': |
| | format = self._FMT_GIF |
| | else: |
| | format = ext.lower() |
| | elif isinstance(data, bytes): |
| | |
| | |
| | if data[:2] == _JPEG: |
| | format = self._FMT_JPEG |
| |
|
| | |
| | if format is None: |
| | format = self._FMT_PNG |
| |
|
| | if format.lower() == 'jpg': |
| | |
| | format = self._FMT_JPEG |
| |
|
| | self.format = format.lower() |
| | self.embed = embed if embed is not None else (url is None) |
| |
|
| | if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS: |
| | raise ValueError("Cannot embed the '%s' image format" % (self.format)) |
| | if self.embed: |
| | self._mimetype = self._MIMETYPES.get(self.format) |
| |
|
| | self.width = width |
| | self.height = height |
| | self.retina = retina |
| | self.unconfined = unconfined |
| | self.alt = alt |
| | super(Image, self).__init__(data=data, url=url, filename=filename, |
| | metadata=metadata) |
| |
|
| | if self.width is None and self.metadata.get('width', {}): |
| | self.width = metadata['width'] |
| |
|
| | if self.height is None and self.metadata.get('height', {}): |
| | self.height = metadata['height'] |
| |
|
| | if self.alt is None and self.metadata.get("alt", {}): |
| | self.alt = metadata["alt"] |
| |
|
| | if retina: |
| | self._retina_shape() |
| |
|
| |
|
| | def _retina_shape(self): |
| | """load pixel-doubled width and height from image data""" |
| | if not self.embed: |
| | return |
| | if self.format == self._FMT_PNG: |
| | w, h = _pngxy(self.data) |
| | elif self.format == self._FMT_JPEG: |
| | w, h = _jpegxy(self.data) |
| | elif self.format == self._FMT_GIF: |
| | w, h = _gifxy(self.data) |
| | else: |
| | |
| | return |
| | self.width = w // 2 |
| | self.height = h // 2 |
| |
|
| | def reload(self): |
| | """Reload the raw data from file or URL.""" |
| | if self.embed: |
| | super(Image,self).reload() |
| | if self.retina: |
| | self._retina_shape() |
| |
|
| | def _repr_html_(self): |
| | if not self.embed: |
| | width = height = klass = alt = "" |
| | if self.width: |
| | width = ' width="%d"' % self.width |
| | if self.height: |
| | height = ' height="%d"' % self.height |
| | if self.unconfined: |
| | klass = ' class="unconfined"' |
| | if self.alt: |
| | alt = ' alt="%s"' % html.escape(self.alt) |
| | return '<img src="{url}"{width}{height}{klass}{alt}/>'.format( |
| | url=self.url, |
| | width=width, |
| | height=height, |
| | klass=klass, |
| | alt=alt, |
| | ) |
| |
|
| | def _repr_mimebundle_(self, include=None, exclude=None): |
| | """Return the image as a mimebundle |
| | |
| | Any new mimetype support should be implemented here. |
| | """ |
| | if self.embed: |
| | mimetype = self._mimetype |
| | data, metadata = self._data_and_metadata(always_both=True) |
| | if metadata: |
| | metadata = {mimetype: metadata} |
| | return {mimetype: data}, metadata |
| | else: |
| | return {'text/html': self._repr_html_()} |
| |
|
| | def _data_and_metadata(self, always_both=False): |
| | """shortcut for returning metadata with shape information, if defined""" |
| | try: |
| | b64_data = b2a_base64(self.data, newline=False).decode("ascii") |
| | except TypeError as e: |
| | raise FileNotFoundError( |
| | "No such file or directory: '%s'" % (self.data)) from e |
| | md = {} |
| | if self.metadata: |
| | md.update(self.metadata) |
| | if self.width: |
| | md['width'] = self.width |
| | if self.height: |
| | md['height'] = self.height |
| | if self.unconfined: |
| | md['unconfined'] = self.unconfined |
| | if self.alt: |
| | md["alt"] = self.alt |
| | if md or always_both: |
| | return b64_data, md |
| | else: |
| | return b64_data |
| |
|
| | def _repr_png_(self): |
| | if self.embed and self.format == self._FMT_PNG: |
| | return self._data_and_metadata() |
| |
|
| | def _repr_jpeg_(self): |
| | if self.embed and self.format == self._FMT_JPEG: |
| | return self._data_and_metadata() |
| |
|
| | def _find_ext(self, s): |
| | base, ext = splitext(s) |
| |
|
| | if not ext: |
| | return base |
| |
|
| | |
| | return ext[1:].lower() |
| |
|
| |
|
| | class Video(DisplayObject): |
| |
|
| | def __init__(self, data=None, url=None, filename=None, embed=False, |
| | mimetype=None, width=None, height=None, html_attributes="controls"): |
| | """Create a video object given raw data or an URL. |
| | |
| | When this object is returned by an input cell or passed to the |
| | display function, it will result in the video being displayed |
| | in the frontend. |
| | |
| | Parameters |
| | ---------- |
| | data : unicode, str or bytes |
| | The raw video data or a URL or filename to load the data from. |
| | Raw data will require passing ``embed=True``. |
| | |
| | url : unicode |
| | A URL for the video. If you specify ``url=``, |
| | the image data will not be embedded. |
| | |
| | filename : unicode |
| | Path to a local file containing the video. |
| | Will be interpreted as a local URL unless ``embed=True``. |
| | |
| | embed : bool |
| | Should the video be embedded using a data URI (True) or be |
| | loaded using a <video> tag (False). |
| | |
| | Since videos are large, embedding them should be avoided, if possible. |
| | You must confirm embedding as your intention by passing ``embed=True``. |
| | |
| | Local files can be displayed with URLs without embedding the content, via:: |
| | |
| | Video('./video.mp4') |
| | |
| | mimetype : unicode |
| | Specify the mimetype for embedded videos. |
| | Default will be guessed from file extension, if available. |
| | |
| | width : int |
| | Width in pixels to which to constrain the video in HTML. |
| | If not supplied, defaults to the width of the video. |
| | |
| | height : int |
| | Height in pixels to which to constrain the video in html. |
| | If not supplied, defaults to the height of the video. |
| | |
| | html_attributes : str |
| | Attributes for the HTML ``<video>`` block. |
| | Default: ``"controls"`` to get video controls. |
| | Other examples: ``"controls muted"`` for muted video with controls, |
| | ``"loop autoplay"`` for looping autoplaying video without controls. |
| | |
| | Examples |
| | -------- |
| | :: |
| | |
| | Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4') |
| | Video('path/to/video.mp4') |
| | Video('path/to/video.mp4', embed=True) |
| | Video('path/to/video.mp4', embed=True, html_attributes="controls muted autoplay") |
| | Video(b'raw-videodata', embed=True) |
| | """ |
| | if isinstance(data, (Path, PurePath)): |
| | data = str(data) |
| |
|
| | if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')): |
| | url = data |
| | data = None |
| | elif data is not None and os.path.exists(data): |
| | filename = data |
| | data = None |
| |
|
| | if data and not embed: |
| | msg = ''.join([ |
| | "To embed videos, you must pass embed=True ", |
| | "(this may make your notebook files huge)\n", |
| | "Consider passing Video(url='...')", |
| | ]) |
| | raise ValueError(msg) |
| |
|
| | self.mimetype = mimetype |
| | self.embed = embed |
| | self.width = width |
| | self.height = height |
| | self.html_attributes = html_attributes |
| | super(Video, self).__init__(data=data, url=url, filename=filename) |
| |
|
| | def _repr_html_(self): |
| | width = height = '' |
| | if self.width: |
| | width = ' width="%d"' % self.width |
| | if self.height: |
| | height = ' height="%d"' % self.height |
| |
|
| | |
| | |
| | if not self.embed: |
| | url = self.url if self.url is not None else self.filename |
| | output = """<video src="{0}" {1} {2} {3}> |
| | Your browser does not support the <code>video</code> element. |
| | </video>""".format(url, self.html_attributes, width, height) |
| | return output |
| |
|
| | |
| | mimetype = self.mimetype |
| | if self.filename is not None: |
| | if not mimetype: |
| | mimetype, _ = mimetypes.guess_type(self.filename) |
| |
|
| | with open(self.filename, 'rb') as f: |
| | video = f.read() |
| | else: |
| | video = self.data |
| | if isinstance(video, str): |
| | |
| | b64_video = video |
| | else: |
| | b64_video = b2a_base64(video, newline=False).decode("ascii").rstrip() |
| |
|
| | output = """<video {0} {1} {2}> |
| | <source src="data:{3};base64,{4}" type="{3}"> |
| | Your browser does not support the video tag. |
| | </video>""".format(self.html_attributes, width, height, mimetype, b64_video) |
| | return output |
| |
|
| | def reload(self): |
| | |
| | pass |
| |
|
| |
|
| | @skip_doctest |
| | def set_matplotlib_formats(*formats, **kwargs): |
| | """ |
| | .. deprecated:: 7.23 |
| | |
| | use `matplotlib_inline.backend_inline.set_matplotlib_formats()` |
| | |
| | Select figure formats for the inline backend. Optionally pass quality for JPEG. |
| | |
| | For example, this enables PNG and JPEG output with a JPEG quality of 90%:: |
| | |
| | In [1]: set_matplotlib_formats('png', 'jpeg', quality=90) |
| | |
| | To set this in your config files use the following:: |
| | |
| | c.InlineBackend.figure_formats = {'png', 'jpeg'} |
| | c.InlineBackend.print_figure_kwargs.update({'quality' : 90}) |
| | |
| | Parameters |
| | ---------- |
| | *formats : strs |
| | One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. |
| | **kwargs |
| | Keyword args will be relayed to ``figure.canvas.print_figure``. |
| | """ |
| | warnings.warn( |
| | "`set_matplotlib_formats` is deprecated since IPython 7.23, directly " |
| | "use `matplotlib_inline.backend_inline.set_matplotlib_formats()`", |
| | DeprecationWarning, |
| | stacklevel=2, |
| | ) |
| |
|
| | from matplotlib_inline.backend_inline import ( |
| | set_matplotlib_formats as set_matplotlib_formats_orig, |
| | ) |
| |
|
| | set_matplotlib_formats_orig(*formats, **kwargs) |
| |
|
| | @skip_doctest |
| | def set_matplotlib_close(close=True): |
| | """ |
| | .. deprecated:: 7.23 |
| | |
| | use `matplotlib_inline.backend_inline.set_matplotlib_close()` |
| | |
| | Set whether the inline backend closes all figures automatically or not. |
| | |
| | By default, the inline backend used in the IPython Notebook will close all |
| | matplotlib figures automatically after each cell is run. This means that |
| | plots in different cells won't interfere. Sometimes, you may want to make |
| | a plot in one cell and then refine it in later cells. This can be accomplished |
| | by:: |
| | |
| | In [1]: set_matplotlib_close(False) |
| | |
| | To set this in your config files use the following:: |
| | |
| | c.InlineBackend.close_figures = False |
| | |
| | Parameters |
| | ---------- |
| | close : bool |
| | Should all matplotlib figures be automatically closed after each cell is |
| | run? |
| | """ |
| | warnings.warn( |
| | "`set_matplotlib_close` is deprecated since IPython 7.23, directly " |
| | "use `matplotlib_inline.backend_inline.set_matplotlib_close()`", |
| | DeprecationWarning, |
| | stacklevel=2, |
| | ) |
| |
|
| | from matplotlib_inline.backend_inline import ( |
| | set_matplotlib_close as set_matplotlib_close_orig, |
| | ) |
| |
|
| | set_matplotlib_close_orig(close) |
| |
|