123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290 |
- # -*- coding: utf-8 -*-
- """Top-level display functions for displaying object in different formats."""
- # Copyright (c) IPython Development Team.
- # Distributed under the terms of the Modified BSD License.
- from __future__ import print_function
- try:
- from base64 import encodebytes as base64_encode
- except ImportError:
- from base64 import encodestring as base64_encode
- from binascii import b2a_hex, hexlify
- import json
- import mimetypes
- import os
- import struct
- import sys
- import warnings
- from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
- unicode_type)
- from IPython.testing.skipdoctest import skip_doctest
- __all__ = ['display', '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', 'Javascript',
- 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
- 'publish_display_data', 'update_display', 'DisplayHandle']
- #-----------------------------------------------------------------------------
- # utility functions
- #-----------------------------------------------------------------------------
- def _safe_exists(path):
- """Check path, but don't let exceptions raise"""
- try:
- return os.path.exists(path)
- except Exception:
- return False
- def _merge(d1, d2):
- """Like update, but merges sub-dicts instead of clobbering at the top level.
- Updates d1 in-place
- """
- if not isinstance(d2, dict) or not isinstance(d1, dict):
- return d2
- for key, value in d2.items():
- d1[key] = _merge(d1.get(key), value)
- return d1
- 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 : tuple of objects
- 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:
- # turn list of pngdata into list of { 'image/png': pngdata }
- objs = [ {mimetype: obj} for obj in objs ]
- display(*objs, raw=raw, metadata=metadata, include=[mimetype])
- #-----------------------------------------------------------------------------
- # Main functions
- #-----------------------------------------------------------------------------
- # use * to indicate transient is keyword-only
- def publish_display_data(data, metadata=None, source=None, **kwargs):
- """Publish data and metadata to all frontends.
- See the ``display_data`` message in the messaging documentation for
- more details about this message type.
- The following MIME types are currently implemented:
- * text/plain
- * text/html
- * text/markdown
- * text/latex
- * application/json
- * application/javascript
- * image/png
- * image/jpeg
- * image/svg+xml
- Parameters
- ----------
- data : dict
- A dictionary having keys that are valid MIME types (like
- 'text/plain' or 'image/svg+xml') and values that are the data for
- that MIME type. The data itself must be a JSON'able data
- structure. Minimally all data should have the 'text/plain' data,
- which can be displayed by all frontends. If more than the plain
- text is given, it is up to the frontend to decide which
- representation to use.
- metadata : dict
- A dictionary for metadata related to the data. This can contain
- arbitrary key, value pairs that frontends can use to interpret
- the data. mime-type keys matching those in data can be used
- to specify metadata about particular representations.
- source : str, deprecated
- Unused.
- transient : dict, keyword-only
- A dictionary of transient data, such as display_id.
- """
- from IPython.core.interactiveshell import InteractiveShell
- display_pub = InteractiveShell.instance().display_pub
- # only pass transient if supplied,
- # to avoid errors with older ipykernel.
- # TODO: We could check for ipykernel version and provide a detailed upgrade message.
- display_pub.publish(
- data=data,
- metadata=metadata,
- **kwargs
- )
- def _new_id():
- """Generate a new random text id with urandom"""
- return b2a_hex(os.urandom(16)).decode('ascii')
- def display(*objs, **kwargs):
- """Display a Python object in all frontends.
- By default all representations will be computed and sent to the frontends.
- Frontends can decide which representation is used and how.
- In terminal IPython this will be similar to using :func:`print`, for use in richer
- frontends see Jupyter notebook examples with rich display logic.
- Parameters
- ----------
- objs : tuple of objects
- The Python objects to display.
- raw : bool, optional
- Are the objects to be displayed already mimetype-keyed dicts of raw display data,
- or Python objects that need to be formatted before display? [default: False]
- include : list, tuple or set, optional
- A list of format type strings (MIME types) to include in the
- format data dict. If this is set *only* the format types included
- in this list will be computed.
- exclude : list, tuple or set, optional
- A list of format type strings (MIME types) to exclude in the format
- data dict. If this is set all format types will be computed,
- except for those included in this argument.
- metadata : dict, optional
- A dictionary of metadata to associate with the output.
- mime-type keys in this dictionary will be associated with the individual
- representation formats, if they exist.
- transient : dict, optional
- A dictionary of transient data to associate with the output.
- Data in this dict should not be persisted to files (e.g. notebooks).
- display_id : str, bool optional
- Set an id for the display.
- This id can be used for updating this display area later via update_display.
- If given as `True`, generate a new `display_id`
- kwargs: additional keyword-args, optional
- Additional keyword-arguments are passed through to the display publisher.
- Returns
- -------
- handle: DisplayHandle
- Returns a handle on updatable displays for use with :func:`update_display`,
- if `display_id` is given. Returns :any:`None` if no `display_id` is given
- (default).
- Examples
- --------
- >>> class Json(object):
- ... def __init__(self, json):
- ... self.json = json
- ... def _repr_pretty_(self, pp, cycle):
- ... import json
- ... pp.text(json.dumps(self.json, indent=2))
- ... def __repr__(self):
- ... return str(self.json)
- ...
- >>> d = Json({1:2, 3: {4:5}})
- >>> print(d)
- {1: 2, 3: {4: 5}}
- >>> display(d)
- {
- "1": 2,
- "3": {
- "4": 5
- }
- }
- >>> def int_formatter(integer, pp, cycle):
- ... pp.text('I'*integer)
- >>> plain = get_ipython().display_formatter.formatters['text/plain']
- >>> plain.for_type(int, int_formatter)
- <function _repr_pprint at 0x...>
- >>> display(7-5)
- II
- >>> del plain.type_printers[int]
- >>> display(7-5)
- 2
- See Also
- --------
- :func:`update_display`
- Notes
- -----
- In Python, objects can declare their textual representation using the
- `__repr__` method. IPython expands on this idea and allows objects to declare
- other, rich representations including:
- - HTML
- - JSON
- - PNG
- - JPEG
- - SVG
- - LaTeX
- A single object can declare some or all of these representations; all are
- handled by IPython's display system.
- The main idea of the first approach is that you have to implement special
- display methods when you define your class, one for each representation you
- want to use. Here is a list of the names of the special methods and the
- values they must return:
- - `_repr_html_`: return raw HTML as a string
- - `_repr_json_`: return a JSONable dict
- - `_repr_jpeg_`: return raw JPEG data
- - `_repr_png_`: return raw PNG data
- - `_repr_svg_`: return raw SVG data as a string
- - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
- - `_repr_mimebundle_`: return a full mimebundle containing the mapping
- from all mimetypes to data
- When you are directly writing your own classes, you can adapt them for
- display in IPython by following the above approach. But in practice, you
- often need to work with existing classes that you can't easily modify.
- You can refer to the documentation on IPython display formatters in order to
- register custom formatters for already existing types.
- .. versionadded:: 5.4 display available without import
- .. versionadded:: 6.1 display available without import
- Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
- the user without import. If you are using display in a document that might
- be used in a pure python context or with older version of IPython, use the
- following import at the top of your file::
- from IPython.display import display
- """
- from IPython.core.interactiveshell import InteractiveShell
-
- if not InteractiveShell.initialized():
- # Directly print objects.
- print(*objs)
- return
-
- raw = kwargs.pop('raw', False)
- include = kwargs.pop('include', None)
- exclude = kwargs.pop('exclude', None)
- metadata = kwargs.pop('metadata', None)
- transient = kwargs.pop('transient', None)
- display_id = kwargs.pop('display_id', None)
- if transient is None:
- transient = {}
- if display_id:
- if display_id is True:
- display_id = _new_id()
- transient['display_id'] = display_id
- if kwargs.get('update') and 'display_id' not in transient:
- raise TypeError('display_id required for update_display')
- if transient:
- kwargs['transient'] = transient
- if not raw:
- format = InteractiveShell.instance().display_formatter.format
- for obj in objs:
- if raw:
- publish_display_data(data=obj, metadata=metadata, **kwargs)
- else:
- format_dict, md_dict = format(obj, include=include, exclude=exclude)
- if not format_dict:
- # nothing to display (e.g. _ipython_display_ took over)
- continue
- if metadata:
- # kwarg-specified metadata gets precedence
- _merge(md_dict, metadata)
- publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
- if display_id:
- return DisplayHandle(display_id)
- # use * for keyword-only display_id arg
- def update_display(obj, **kwargs):
- """Update an existing display by id
- Parameters
- ----------
- obj:
- The object with which to update the display
- display_id: keyword-only
- The id of the display to update
- See Also
- --------
- :func:`display`
- """
- sentinel = object()
- display_id = kwargs.pop('display_id', sentinel)
- if display_id is sentinel:
- raise TypeError("update_display() missing 1 required keyword-only argument: 'display_id'")
- kwargs['update'] = True
- display(obj, display_id=display_id, **kwargs)
- class DisplayHandle(object):
- """A handle on an updatable display
- Call `.update(obj)` to display a new object.
- Call `.display(obj`) to add a new instance of this display,
- and update existing instances.
- See Also
- --------
- :func:`display`, :func:`update_display`
- """
- def __init__(self, display_id=None):
- if display_id is None:
- display_id = _new_id()
- self.display_id = display_id
- def __repr__(self):
- return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
- def display(self, obj, **kwargs):
- """Make a new display with my id, updating existing instances.
-
- Parameters
- ----------
-
- obj:
- object to display
- **kwargs:
- additional keyword arguments passed to display
- """
- display(obj, display_id=self.display_id, **kwargs)
- def update(self, obj, **kwargs):
- """Update existing displays with my id
-
- Parameters
- ----------
-
- obj:
- object to display
- **kwargs:
- additional keyword arguments passed to update_display
- """
- update_display(obj, display_id=self.display_id, **kwargs)
- def display_pretty(*objs, **kwargs):
- """Display the pretty (default) representation of an object.
- Parameters
- ----------
- objs : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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 : tuple of objects
- 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)
- #-----------------------------------------------------------------------------
- # Smart classes
- #-----------------------------------------------------------------------------
- class DisplayObject(object):
- """An object that wraps data to be displayed."""
- _read_flags = 'r'
- _show_mem_addr = False
- def __init__(self, data=None, url=None, filename=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.
- """
- if data is not None and isinstance(data, string_types):
- 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.data = data
- self.url = url
- self.filename = None if filename is None else unicode_type(filename)
- 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 reload(self):
- """Reload the raw data from file or URL."""
- if self.filename is not None:
- with open(self.filename, self._read_flags) as f:
- self.data = f.read()
- elif self.url is not None:
- try:
- try:
- from urllib.request import urlopen # Py3
- except ImportError:
- from urllib2 import urlopen
- response = urlopen(self.url)
- self.data = response.read()
- # extract encoding from header, if there is one:
- encoding = None
- for sub in response.headers['content-type'].split(';'):
- sub = sub.strip()
- if sub.startswith('charset'):
- encoding = sub.split('=')[-1].strip()
- break
- # decode data, if an encoding was specified
- if encoding:
- self.data = self.data.decode(encoding, 'replace')
- except:
- self.data = None
- class TextDisplayObject(DisplayObject):
- """Validate that display data is text"""
- def _check_data(self):
- if self.data is not None and not isinstance(self.data, string_types):
- 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 _repr_html_(self):
- return self.data
- 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
- class Math(TextDisplayObject):
- def _repr_latex_(self):
- s = self.data.strip('$')
- return "$$%s$$" % s
- class Latex(TextDisplayObject):
- def _repr_latex_(self):
- return self.data
- class SVG(DisplayObject):
- _read_flags = 'rb'
- # wrap data in a property, which extracts the <svg> tag, discarding
- # document headers
- _data = None
- @property
- def data(self):
- return self._data
- @data.setter
- def data(self, svg):
- if svg is None:
- self._data = None
- return
- # parse into dom object
- from xml.dom import minidom
- svg = cast_bytes_py2(svg)
- x = minidom.parseString(svg)
- # get svg tag (should be 1)
- found_svg = x.getElementsByTagName('svg')
- if found_svg:
- svg = found_svg[0].toxml()
- else:
- # fallback on the input, trust the user
- # but this is probably an error.
- pass
- svg = cast_unicode(svg)
- self._data = svg
- def _repr_svg_(self):
- return self.data
- 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(self, display_id=self._display_id)
- def update(self):
- 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 # First iteration is 0
- 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()
-
- def next(self):
- """Python 2 compatibility"""
- return self.__next__()
- 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.
- """
- # wrap data in a property, which warns about passing already-serialized JSON
- _data = None
- 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, string_types):
- warnings.warn("JSON expects JSONable dict or list, not JSON strings")
- data = json.loads(data)
- self._data = data
- def _repr_json_(self):
- return self.data
- css_t = """$("head").append($("<link/>").attr({
- rel: "stylesheet",
- type: "text/css",
- href: "%s"
- }));
- """
- lib_t1 = """$.getScript("%s", function () {
- """
- lib_t2 = """});
- """
- 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, string_types):
- lib = [lib]
- elif lib is None:
- lib = []
- if isinstance(css, string_types):
- 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
- # constants for identifying png/jpeg data
- _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')
- # next 8 bytes are width/height
- w4h4 = data[ihdr+4:ihdr+12]
- return struct.unpack('>ii', w4h4)
- def _jpegxy(data):
- """read the (width, height) from a JPEG header"""
- # adapted from http://www.64lines.com/jpeg-width-height
-
- 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':
- # found Start of Frame
- iSOF = idx
- break
- else:
- # read another block
- idx += 2
- h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
- return w, h
- class Image(DisplayObject):
- _read_flags = 'rb'
- _FMT_JPEG = u'jpeg'
- _FMT_PNG = u'png'
- _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
- def __init__(self, data=None, url=None, filename=None, format=None,
- embed=None, width=None, height=None, retina=False,
- unconfined=False, metadata=None):
- """Create a PNG/JPEG 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). 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.
- 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('http://www.google.fr/images/srpr/logo3w.png')
- Image('/path/to/image.jpg')
- Image(b'RAW_PNG_DATA...')
- # 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='http://www.google.fr/images/srpr/logo3w.png')
- """
- 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, string_types) 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
- else:
- format = ext.lower()
- elif isinstance(data, bytes):
- # infer image type from image data header,
- # only if format has not been specified.
- if data[:2] == _JPEG:
- format = self._FMT_JPEG
- # failed to detect format, default png
- if format is None:
- format = 'png'
- if format.lower() == 'jpg':
- # jpg->jpeg
- format = self._FMT_JPEG
- self.format = unicode_type(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))
- self.width = width
- self.height = height
- self.retina = retina
- self.unconfined = unconfined
- self.metadata = metadata
- super(Image, self).__init__(data=data, url=url, filename=filename)
-
- 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 == 'png':
- w, h = _pngxy(self.data)
- elif self.format == 'jpeg':
- w, h = _jpegxy(self.data)
- else:
- # retina only supports png
- 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 = ''
- if self.width:
- width = ' width="%d"' % self.width
- if self.height:
- height = ' height="%d"' % self.height
- if self.unconfined:
- klass = ' class="unconfined"'
- return u'<img src="{url}"{width}{height}{klass}/>'.format(
- url=self.url,
- width=width,
- height=height,
- klass=klass,
- )
- def _data_and_metadata(self):
- """shortcut for returning metadata with shape information, if defined"""
- md = {}
- if self.width:
- md['width'] = self.width
- if self.height:
- md['height'] = self.height
- if self.unconfined:
- md['unconfined'] = self.unconfined
- if self.metadata:
- md.update(self.metadata)
- if md:
- return self.data, md
- else:
- return self.data
- def _repr_png_(self):
- if self.embed and self.format == u'png':
- return self._data_and_metadata()
- def _repr_jpeg_(self):
- if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
- return self._data_and_metadata()
- def _find_ext(self, s):
- return unicode_type(s.split('.')[-1].lower())
- class Video(DisplayObject):
- def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
- """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.
- 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(b'raw-videodata', embed=True)
- """
- if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')):
- url = data
- data = None
- elif 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
- super(Video, self).__init__(data=data, url=url, filename=filename)
- def _repr_html_(self):
- # External URLs and potentially local files are not embedded into the
- # notebook output.
- if not self.embed:
- url = self.url if self.url is not None else self.filename
- output = """<video src="{0}" controls>
- Your browser does not support the <code>video</code> element.
- </video>""".format(url)
- return output
-
- # Embedded videos are base64-encoded.
- 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, unicode_type):
- # unicode input is already b64-encoded
- b64_video = video
- else:
- b64_video = base64_encode(video).decode('ascii').rstrip()
-
- output = """<video controls>
- <source src="data:{0};base64,{1}" type="{0}">
- Your browser does not support the video tag.
- </video>""".format(mimetype, b64_video)
- return output
- def reload(self):
- # TODO
- pass
- def _repr_png_(self):
- # TODO
- pass
- def _repr_jpeg_(self):
- # TODO
- pass
- def clear_output(wait=False):
- """Clear the output of the current cell receiving output.
- Parameters
- ----------
- wait : bool [default: false]
- Wait to clear the output until new output is available to replace it."""
- from IPython.core.interactiveshell import InteractiveShell
- if InteractiveShell.initialized():
- InteractiveShell.instance().display_pub.clear_output(wait)
- else:
- print('\033[2K\r', end='')
- sys.stdout.flush()
- print('\033[2K\r', end='')
- sys.stderr.flush()
- @skip_doctest
- def set_matplotlib_formats(*formats, **kwargs):
- """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``.
- """
- from IPython.core.interactiveshell import InteractiveShell
- from IPython.core.pylabtools import select_figure_formats
- # build kwargs, starting with InlineBackend config
- kw = {}
- from ipykernel.pylab.config import InlineBackend
- cfg = InlineBackend.instance()
- kw.update(cfg.print_figure_kwargs)
- kw.update(**kwargs)
- shell = InteractiveShell.instance()
- select_figure_formats(shell, formats, **kw)
- @skip_doctest
- def set_matplotlib_close(close=True):
- """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?
- """
- from ipykernel.pylab.config import InlineBackend
- cfg = InlineBackend.instance()
- cfg.close_figures = close
|