display.py 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. # -*- coding: utf-8 -*-
  2. """Top-level display functions for displaying object in different formats."""
  3. # Copyright (c) IPython Development Team.
  4. # Distributed under the terms of the Modified BSD License.
  5. from __future__ import print_function
  6. try:
  7. from base64 import encodebytes as base64_encode
  8. except ImportError:
  9. from base64 import encodestring as base64_encode
  10. import json
  11. import mimetypes
  12. import os
  13. import struct
  14. import sys
  15. import warnings
  16. from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
  17. unicode_type)
  18. from IPython.testing.skipdoctest import skip_doctest
  19. __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
  20. 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
  21. 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
  22. 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
  23. 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
  24. 'publish_display_data']
  25. #-----------------------------------------------------------------------------
  26. # utility functions
  27. #-----------------------------------------------------------------------------
  28. def _safe_exists(path):
  29. """Check path, but don't let exceptions raise"""
  30. try:
  31. return os.path.exists(path)
  32. except Exception:
  33. return False
  34. def _merge(d1, d2):
  35. """Like update, but merges sub-dicts instead of clobbering at the top level.
  36. Updates d1 in-place
  37. """
  38. if not isinstance(d2, dict) or not isinstance(d1, dict):
  39. return d2
  40. for key, value in d2.items():
  41. d1[key] = _merge(d1.get(key), value)
  42. return d1
  43. def _display_mimetype(mimetype, objs, raw=False, metadata=None):
  44. """internal implementation of all display_foo methods
  45. Parameters
  46. ----------
  47. mimetype : str
  48. The mimetype to be published (e.g. 'image/png')
  49. objs : tuple of objects
  50. The Python objects to display, or if raw=True raw text data to
  51. display.
  52. raw : bool
  53. Are the data objects raw data or Python objects that need to be
  54. formatted before display? [default: False]
  55. metadata : dict (optional)
  56. Metadata to be associated with the specific mimetype output.
  57. """
  58. if metadata:
  59. metadata = {mimetype: metadata}
  60. if raw:
  61. # turn list of pngdata into list of { 'image/png': pngdata }
  62. objs = [ {mimetype: obj} for obj in objs ]
  63. display(*objs, raw=raw, metadata=metadata, include=[mimetype])
  64. #-----------------------------------------------------------------------------
  65. # Main functions
  66. #-----------------------------------------------------------------------------
  67. def publish_display_data(data, metadata=None, source=None):
  68. """Publish data and metadata to all frontends.
  69. See the ``display_data`` message in the messaging documentation for
  70. more details about this message type.
  71. The following MIME types are currently implemented:
  72. * text/plain
  73. * text/html
  74. * text/markdown
  75. * text/latex
  76. * application/json
  77. * application/javascript
  78. * image/png
  79. * image/jpeg
  80. * image/svg+xml
  81. Parameters
  82. ----------
  83. data : dict
  84. A dictionary having keys that are valid MIME types (like
  85. 'text/plain' or 'image/svg+xml') and values that are the data for
  86. that MIME type. The data itself must be a JSON'able data
  87. structure. Minimally all data should have the 'text/plain' data,
  88. which can be displayed by all frontends. If more than the plain
  89. text is given, it is up to the frontend to decide which
  90. representation to use.
  91. metadata : dict
  92. A dictionary for metadata related to the data. This can contain
  93. arbitrary key, value pairs that frontends can use to interpret
  94. the data. mime-type keys matching those in data can be used
  95. to specify metadata about particular representations.
  96. source : str, deprecated
  97. Unused.
  98. """
  99. from IPython.core.interactiveshell import InteractiveShell
  100. InteractiveShell.instance().display_pub.publish(
  101. data=data,
  102. metadata=metadata,
  103. )
  104. def display(*objs, **kwargs):
  105. """Display a Python object in all frontends.
  106. By default all representations will be computed and sent to the frontends.
  107. Frontends can decide which representation is used and how.
  108. Parameters
  109. ----------
  110. objs : tuple of objects
  111. The Python objects to display.
  112. raw : bool, optional
  113. Are the objects to be displayed already mimetype-keyed dicts of raw display data,
  114. or Python objects that need to be formatted before display? [default: False]
  115. include : list or tuple, optional
  116. A list of format type strings (MIME types) to include in the
  117. format data dict. If this is set *only* the format types included
  118. in this list will be computed.
  119. exclude : list or tuple, optional
  120. A list of format type strings (MIME types) to exclude in the format
  121. data dict. If this is set all format types will be computed,
  122. except for those included in this argument.
  123. metadata : dict, optional
  124. A dictionary of metadata to associate with the output.
  125. mime-type keys in this dictionary will be associated with the individual
  126. representation formats, if they exist.
  127. """
  128. raw = kwargs.get('raw', False)
  129. include = kwargs.get('include')
  130. exclude = kwargs.get('exclude')
  131. metadata = kwargs.get('metadata')
  132. from IPython.core.interactiveshell import InteractiveShell
  133. if not raw:
  134. format = InteractiveShell.instance().display_formatter.format
  135. for obj in objs:
  136. if raw:
  137. publish_display_data(data=obj, metadata=metadata)
  138. else:
  139. format_dict, md_dict = format(obj, include=include, exclude=exclude)
  140. if not format_dict:
  141. # nothing to display (e.g. _ipython_display_ took over)
  142. continue
  143. if metadata:
  144. # kwarg-specified metadata gets precedence
  145. _merge(md_dict, metadata)
  146. publish_display_data(data=format_dict, metadata=md_dict)
  147. def display_pretty(*objs, **kwargs):
  148. """Display the pretty (default) representation of an object.
  149. Parameters
  150. ----------
  151. objs : tuple of objects
  152. The Python objects to display, or if raw=True raw text data to
  153. display.
  154. raw : bool
  155. Are the data objects raw data or Python objects that need to be
  156. formatted before display? [default: False]
  157. metadata : dict (optional)
  158. Metadata to be associated with the specific mimetype output.
  159. """
  160. _display_mimetype('text/plain', objs, **kwargs)
  161. def display_html(*objs, **kwargs):
  162. """Display the HTML representation of an object.
  163. Note: If raw=False and the object does not have a HTML
  164. representation, no HTML will be shown.
  165. Parameters
  166. ----------
  167. objs : tuple of objects
  168. The Python objects to display, or if raw=True raw HTML data to
  169. display.
  170. raw : bool
  171. Are the data objects raw data or Python objects that need to be
  172. formatted before display? [default: False]
  173. metadata : dict (optional)
  174. Metadata to be associated with the specific mimetype output.
  175. """
  176. _display_mimetype('text/html', objs, **kwargs)
  177. def display_markdown(*objs, **kwargs):
  178. """Displays the Markdown representation of an object.
  179. Parameters
  180. ----------
  181. objs : tuple of objects
  182. The Python objects to display, or if raw=True raw markdown data to
  183. display.
  184. raw : bool
  185. Are the data objects raw data or Python objects that need to be
  186. formatted before display? [default: False]
  187. metadata : dict (optional)
  188. Metadata to be associated with the specific mimetype output.
  189. """
  190. _display_mimetype('text/markdown', objs, **kwargs)
  191. def display_svg(*objs, **kwargs):
  192. """Display the SVG representation of an object.
  193. Parameters
  194. ----------
  195. objs : tuple of objects
  196. The Python objects to display, or if raw=True raw svg data to
  197. display.
  198. raw : bool
  199. Are the data objects raw data or Python objects that need to be
  200. formatted before display? [default: False]
  201. metadata : dict (optional)
  202. Metadata to be associated with the specific mimetype output.
  203. """
  204. _display_mimetype('image/svg+xml', objs, **kwargs)
  205. def display_png(*objs, **kwargs):
  206. """Display the PNG representation of an object.
  207. Parameters
  208. ----------
  209. objs : tuple of objects
  210. The Python objects to display, or if raw=True raw png data to
  211. display.
  212. raw : bool
  213. Are the data objects raw data or Python objects that need to be
  214. formatted before display? [default: False]
  215. metadata : dict (optional)
  216. Metadata to be associated with the specific mimetype output.
  217. """
  218. _display_mimetype('image/png', objs, **kwargs)
  219. def display_jpeg(*objs, **kwargs):
  220. """Display the JPEG representation of an object.
  221. Parameters
  222. ----------
  223. objs : tuple of objects
  224. The Python objects to display, or if raw=True raw JPEG 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('image/jpeg', objs, **kwargs)
  233. def display_latex(*objs, **kwargs):
  234. """Display the LaTeX representation of an object.
  235. Parameters
  236. ----------
  237. objs : tuple of objects
  238. The Python objects to display, or if raw=True raw latex data to
  239. display.
  240. raw : bool
  241. Are the data objects raw data or Python objects that need to be
  242. formatted before display? [default: False]
  243. metadata : dict (optional)
  244. Metadata to be associated with the specific mimetype output.
  245. """
  246. _display_mimetype('text/latex', objs, **kwargs)
  247. def display_json(*objs, **kwargs):
  248. """Display the JSON representation of an object.
  249. Note that not many frontends support displaying JSON.
  250. Parameters
  251. ----------
  252. objs : tuple of objects
  253. The Python objects to display, or if raw=True raw json data to
  254. display.
  255. raw : bool
  256. Are the data objects raw data or Python objects that need to be
  257. formatted before display? [default: False]
  258. metadata : dict (optional)
  259. Metadata to be associated with the specific mimetype output.
  260. """
  261. _display_mimetype('application/json', objs, **kwargs)
  262. def display_javascript(*objs, **kwargs):
  263. """Display the Javascript representation of an object.
  264. Parameters
  265. ----------
  266. objs : tuple of objects
  267. The Python objects to display, or if raw=True raw javascript data to
  268. display.
  269. raw : bool
  270. Are the data objects raw data or Python objects that need to be
  271. formatted before display? [default: False]
  272. metadata : dict (optional)
  273. Metadata to be associated with the specific mimetype output.
  274. """
  275. _display_mimetype('application/javascript', objs, **kwargs)
  276. def display_pdf(*objs, **kwargs):
  277. """Display the PDF representation of an object.
  278. Parameters
  279. ----------
  280. objs : tuple of objects
  281. The Python objects to display, or if raw=True raw javascript data to
  282. display.
  283. raw : bool
  284. Are the data objects raw data or Python objects that need to be
  285. formatted before display? [default: False]
  286. metadata : dict (optional)
  287. Metadata to be associated with the specific mimetype output.
  288. """
  289. _display_mimetype('application/pdf', objs, **kwargs)
  290. #-----------------------------------------------------------------------------
  291. # Smart classes
  292. #-----------------------------------------------------------------------------
  293. class DisplayObject(object):
  294. """An object that wraps data to be displayed."""
  295. _read_flags = 'r'
  296. _show_mem_addr = False
  297. def __init__(self, data=None, url=None, filename=None):
  298. """Create a display object given raw data.
  299. When this object is returned by an expression or passed to the
  300. display function, it will result in the data being displayed
  301. in the frontend. The MIME type of the data should match the
  302. subclasses used, so the Png subclass should be used for 'image/png'
  303. data. If the data is a URL, the data will first be downloaded
  304. and then displayed. If
  305. Parameters
  306. ----------
  307. data : unicode, str or bytes
  308. The raw data or a URL or file to load the data from
  309. url : unicode
  310. A URL to download the data from.
  311. filename : unicode
  312. Path to a local file to load the data from.
  313. """
  314. if data is not None and isinstance(data, string_types):
  315. if data.startswith('http') and url is None:
  316. url = data
  317. filename = None
  318. data = None
  319. elif _safe_exists(data) and filename is None:
  320. url = None
  321. filename = data
  322. data = None
  323. self.data = data
  324. self.url = url
  325. self.filename = None if filename is None else unicode_type(filename)
  326. self.reload()
  327. self._check_data()
  328. def __repr__(self):
  329. if not self._show_mem_addr:
  330. cls = self.__class__
  331. r = "<%s.%s object>" % (cls.__module__, cls.__name__)
  332. else:
  333. r = super(DisplayObject, self).__repr__()
  334. return r
  335. def _check_data(self):
  336. """Override in subclasses if there's something to check."""
  337. pass
  338. def reload(self):
  339. """Reload the raw data from file or URL."""
  340. if self.filename is not None:
  341. with open(self.filename, self._read_flags) as f:
  342. self.data = f.read()
  343. elif self.url is not None:
  344. try:
  345. try:
  346. from urllib.request import urlopen # Py3
  347. except ImportError:
  348. from urllib2 import urlopen
  349. response = urlopen(self.url)
  350. self.data = response.read()
  351. # extract encoding from header, if there is one:
  352. encoding = None
  353. for sub in response.headers['content-type'].split(';'):
  354. sub = sub.strip()
  355. if sub.startswith('charset'):
  356. encoding = sub.split('=')[-1].strip()
  357. break
  358. # decode data, if an encoding was specified
  359. if encoding:
  360. self.data = self.data.decode(encoding, 'replace')
  361. except:
  362. self.data = None
  363. class TextDisplayObject(DisplayObject):
  364. """Validate that display data is text"""
  365. def _check_data(self):
  366. if self.data is not None and not isinstance(self.data, string_types):
  367. raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
  368. class Pretty(TextDisplayObject):
  369. def _repr_pretty_(self):
  370. return self.data
  371. class HTML(TextDisplayObject):
  372. def _repr_html_(self):
  373. return self.data
  374. def __html__(self):
  375. """
  376. This method exists to inform other HTML-using modules (e.g. Markupsafe,
  377. htmltag, etc) that this object is HTML and does not need things like
  378. special characters (<>&) escaped.
  379. """
  380. return self._repr_html_()
  381. class Markdown(TextDisplayObject):
  382. def _repr_markdown_(self):
  383. return self.data
  384. class Math(TextDisplayObject):
  385. def _repr_latex_(self):
  386. s = self.data.strip('$')
  387. return "$$%s$$" % s
  388. class Latex(TextDisplayObject):
  389. def _repr_latex_(self):
  390. return self.data
  391. class SVG(DisplayObject):
  392. # wrap data in a property, which extracts the <svg> tag, discarding
  393. # document headers
  394. _data = None
  395. @property
  396. def data(self):
  397. return self._data
  398. @data.setter
  399. def data(self, svg):
  400. if svg is None:
  401. self._data = None
  402. return
  403. # parse into dom object
  404. from xml.dom import minidom
  405. svg = cast_bytes_py2(svg)
  406. x = minidom.parseString(svg)
  407. # get svg tag (should be 1)
  408. found_svg = x.getElementsByTagName('svg')
  409. if found_svg:
  410. svg = found_svg[0].toxml()
  411. else:
  412. # fallback on the input, trust the user
  413. # but this is probably an error.
  414. pass
  415. svg = cast_unicode(svg)
  416. self._data = svg
  417. def _repr_svg_(self):
  418. return self.data
  419. class JSON(DisplayObject):
  420. """JSON expects a JSON-able dict or list
  421. not an already-serialized JSON string.
  422. Scalar types (None, number, string) are not allowed, only dict or list containers.
  423. """
  424. # wrap data in a property, which warns about passing already-serialized JSON
  425. _data = None
  426. def _check_data(self):
  427. if self.data is not None and not isinstance(self.data, (dict, list)):
  428. raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
  429. @property
  430. def data(self):
  431. return self._data
  432. @data.setter
  433. def data(self, data):
  434. if isinstance(data, string_types):
  435. warnings.warn("JSON expects JSONable dict or list, not JSON strings")
  436. data = json.loads(data)
  437. self._data = data
  438. def _repr_json_(self):
  439. return self.data
  440. css_t = """$("head").append($("<link/>").attr({
  441. rel: "stylesheet",
  442. type: "text/css",
  443. href: "%s"
  444. }));
  445. """
  446. lib_t1 = """$.getScript("%s", function () {
  447. """
  448. lib_t2 = """});
  449. """
  450. class Javascript(TextDisplayObject):
  451. def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
  452. """Create a Javascript display object given raw data.
  453. When this object is returned by an expression or passed to the
  454. display function, it will result in the data being displayed
  455. in the frontend. If the data is a URL, the data will first be
  456. downloaded and then displayed.
  457. In the Notebook, the containing element will be available as `element`,
  458. and jQuery will be available. Content appended to `element` will be
  459. visible in the output area.
  460. Parameters
  461. ----------
  462. data : unicode, str or bytes
  463. The Javascript source code or a URL to download it from.
  464. url : unicode
  465. A URL to download the data from.
  466. filename : unicode
  467. Path to a local file to load the data from.
  468. lib : list or str
  469. A sequence of Javascript library URLs to load asynchronously before
  470. running the source code. The full URLs of the libraries should
  471. be given. A single Javascript library URL can also be given as a
  472. string.
  473. css: : list or str
  474. A sequence of css files to load before running the source code.
  475. The full URLs of the css files should be given. A single css URL
  476. can also be given as a string.
  477. """
  478. if isinstance(lib, string_types):
  479. lib = [lib]
  480. elif lib is None:
  481. lib = []
  482. if isinstance(css, string_types):
  483. css = [css]
  484. elif css is None:
  485. css = []
  486. if not isinstance(lib, (list,tuple)):
  487. raise TypeError('expected sequence, got: %r' % lib)
  488. if not isinstance(css, (list,tuple)):
  489. raise TypeError('expected sequence, got: %r' % css)
  490. self.lib = lib
  491. self.css = css
  492. super(Javascript, self).__init__(data=data, url=url, filename=filename)
  493. def _repr_javascript_(self):
  494. r = ''
  495. for c in self.css:
  496. r += css_t % c
  497. for l in self.lib:
  498. r += lib_t1 % l
  499. r += self.data
  500. r += lib_t2*len(self.lib)
  501. return r
  502. # constants for identifying png/jpeg data
  503. _PNG = b'\x89PNG\r\n\x1a\n'
  504. _JPEG = b'\xff\xd8'
  505. def _pngxy(data):
  506. """read the (width, height) from a PNG header"""
  507. ihdr = data.index(b'IHDR')
  508. # next 8 bytes are width/height
  509. w4h4 = data[ihdr+4:ihdr+12]
  510. return struct.unpack('>ii', w4h4)
  511. def _jpegxy(data):
  512. """read the (width, height) from a JPEG header"""
  513. # adapted from http://www.64lines.com/jpeg-width-height
  514. idx = 4
  515. while True:
  516. block_size = struct.unpack('>H', data[idx:idx+2])[0]
  517. idx = idx + block_size
  518. if data[idx:idx+2] == b'\xFF\xC0':
  519. # found Start of Frame
  520. iSOF = idx
  521. break
  522. else:
  523. # read another block
  524. idx += 2
  525. h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
  526. return w, h
  527. class Image(DisplayObject):
  528. _read_flags = 'rb'
  529. _FMT_JPEG = u'jpeg'
  530. _FMT_PNG = u'png'
  531. _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
  532. def __init__(self, data=None, url=None, filename=None, format=None,
  533. embed=None, width=None, height=None, retina=False,
  534. unconfined=False, metadata=None):
  535. """Create a PNG/JPEG image object given raw data.
  536. When this object is returned by an input cell or passed to the
  537. display function, it will result in the image being displayed
  538. in the frontend.
  539. Parameters
  540. ----------
  541. data : unicode, str or bytes
  542. The raw image data or a URL or filename to load the data from.
  543. This always results in embedded image data.
  544. url : unicode
  545. A URL to download the data from. If you specify `url=`,
  546. the image data will not be embedded unless you also specify `embed=True`.
  547. filename : unicode
  548. Path to a local file to load the data from.
  549. Images from a file are always embedded.
  550. format : unicode
  551. The format of the image data (png/jpeg/jpg). If a filename or URL is given
  552. for format will be inferred from the filename extension.
  553. embed : bool
  554. Should the image data be embedded using a data URI (True) or be
  555. loaded using an <img> tag. Set this to True if you want the image
  556. to be viewable later with no internet connection in the notebook.
  557. Default is `True`, unless the keyword argument `url` is set, then
  558. default value is `False`.
  559. Note that QtConsole is not able to display images if `embed` is set to `False`
  560. width : int
  561. Width in pixels to which to constrain the image in html
  562. height : int
  563. Height in pixels to which to constrain the image in html
  564. retina : bool
  565. Automatically set the width and height to half of the measured
  566. width and height.
  567. This only works for embedded images because it reads the width/height
  568. from image data.
  569. For non-embedded images, you can just set the desired display width
  570. and height directly.
  571. unconfined: bool
  572. Set unconfined=True to disable max-width confinement of the image.
  573. metadata: dict
  574. Specify extra metadata to attach to the image.
  575. Examples
  576. --------
  577. # embedded image data, works in qtconsole and notebook
  578. # when passed positionally, the first arg can be any of raw image data,
  579. # a URL, or a filename from which to load image data.
  580. # The result is always embedding image data for inline images.
  581. Image('http://www.google.fr/images/srpr/logo3w.png')
  582. Image('/path/to/image.jpg')
  583. Image(b'RAW_PNG_DATA...')
  584. # Specifying Image(url=...) does not embed the image data,
  585. # it only generates `<img>` tag with a link to the source.
  586. # This will not work in the qtconsole or offline.
  587. Image(url='http://www.google.fr/images/srpr/logo3w.png')
  588. """
  589. if filename is not None:
  590. ext = self._find_ext(filename)
  591. elif url is not None:
  592. ext = self._find_ext(url)
  593. elif data is None:
  594. raise ValueError("No image data found. Expecting filename, url, or data.")
  595. elif isinstance(data, string_types) and (
  596. data.startswith('http') or _safe_exists(data)
  597. ):
  598. ext = self._find_ext(data)
  599. else:
  600. ext = None
  601. if format is None:
  602. if ext is not None:
  603. if ext == u'jpg' or ext == u'jpeg':
  604. format = self._FMT_JPEG
  605. if ext == u'png':
  606. format = self._FMT_PNG
  607. else:
  608. format = ext.lower()
  609. elif isinstance(data, bytes):
  610. # infer image type from image data header,
  611. # only if format has not been specified.
  612. if data[:2] == _JPEG:
  613. format = self._FMT_JPEG
  614. # failed to detect format, default png
  615. if format is None:
  616. format = 'png'
  617. if format.lower() == 'jpg':
  618. # jpg->jpeg
  619. format = self._FMT_JPEG
  620. self.format = unicode_type(format).lower()
  621. self.embed = embed if embed is not None else (url is None)
  622. if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
  623. raise ValueError("Cannot embed the '%s' image format" % (self.format))
  624. self.width = width
  625. self.height = height
  626. self.retina = retina
  627. self.unconfined = unconfined
  628. self.metadata = metadata
  629. super(Image, self).__init__(data=data, url=url, filename=filename)
  630. if retina:
  631. self._retina_shape()
  632. def _retina_shape(self):
  633. """load pixel-doubled width and height from image data"""
  634. if not self.embed:
  635. return
  636. if self.format == 'png':
  637. w, h = _pngxy(self.data)
  638. elif self.format == 'jpeg':
  639. w, h = _jpegxy(self.data)
  640. else:
  641. # retina only supports png
  642. return
  643. self.width = w // 2
  644. self.height = h // 2
  645. def reload(self):
  646. """Reload the raw data from file or URL."""
  647. if self.embed:
  648. super(Image,self).reload()
  649. if self.retina:
  650. self._retina_shape()
  651. def _repr_html_(self):
  652. if not self.embed:
  653. width = height = klass = ''
  654. if self.width:
  655. width = ' width="%d"' % self.width
  656. if self.height:
  657. height = ' height="%d"' % self.height
  658. if self.unconfined:
  659. klass = ' class="unconfined"'
  660. return u'<img src="{url}"{width}{height}{klass}/>'.format(
  661. url=self.url,
  662. width=width,
  663. height=height,
  664. klass=klass,
  665. )
  666. def _data_and_metadata(self):
  667. """shortcut for returning metadata with shape information, if defined"""
  668. md = {}
  669. if self.width:
  670. md['width'] = self.width
  671. if self.height:
  672. md['height'] = self.height
  673. if self.unconfined:
  674. md['unconfined'] = self.unconfined
  675. if self.metadata:
  676. md.update(self.metadata)
  677. if md:
  678. return self.data, md
  679. else:
  680. return self.data
  681. def _repr_png_(self):
  682. if self.embed and self.format == u'png':
  683. return self._data_and_metadata()
  684. def _repr_jpeg_(self):
  685. if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
  686. return self._data_and_metadata()
  687. def _find_ext(self, s):
  688. return unicode_type(s.split('.')[-1].lower())
  689. class Video(DisplayObject):
  690. def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
  691. """Create a video object given raw data or an URL.
  692. When this object is returned by an input cell or passed to the
  693. display function, it will result in the video being displayed
  694. in the frontend.
  695. Parameters
  696. ----------
  697. data : unicode, str or bytes
  698. The raw video data or a URL or filename to load the data from.
  699. Raw data will require passing `embed=True`.
  700. url : unicode
  701. A URL for the video. If you specify `url=`,
  702. the image data will not be embedded.
  703. filename : unicode
  704. Path to a local file containing the video.
  705. Will be interpreted as a local URL unless `embed=True`.
  706. embed : bool
  707. Should the video be embedded using a data URI (True) or be
  708. loaded using a <video> tag (False).
  709. Since videos are large, embedding them should be avoided, if possible.
  710. You must confirm embedding as your intention by passing `embed=True`.
  711. Local files can be displayed with URLs without embedding the content, via::
  712. Video('./video.mp4')
  713. mimetype: unicode
  714. Specify the mimetype for embedded videos.
  715. Default will be guessed from file extension, if available.
  716. Examples
  717. --------
  718. Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
  719. Video('path/to/video.mp4')
  720. Video('path/to/video.mp4', embed=True)
  721. Video(b'raw-videodata', embed=True)
  722. """
  723. if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')):
  724. url = data
  725. data = None
  726. elif os.path.exists(data):
  727. filename = data
  728. data = None
  729. if data and not embed:
  730. msg = ''.join([
  731. "To embed videos, you must pass embed=True ",
  732. "(this may make your notebook files huge)\n",
  733. "Consider passing Video(url='...')",
  734. ])
  735. raise ValueError(msg)
  736. self.mimetype = mimetype
  737. self.embed = embed
  738. super(Video, self).__init__(data=data, url=url, filename=filename)
  739. def _repr_html_(self):
  740. # External URLs and potentially local files are not embedded into the
  741. # notebook output.
  742. if not self.embed:
  743. url = self.url if self.url is not None else self.filename
  744. output = """<video src="{0}" controls>
  745. Your browser does not support the <code>video</code> element.
  746. </video>""".format(url)
  747. return output
  748. # Embedded videos are base64-encoded.
  749. mimetype = self.mimetype
  750. if self.filename is not None:
  751. if not mimetype:
  752. mimetype, _ = mimetypes.guess_type(self.filename)
  753. with open(self.filename, 'rb') as f:
  754. video = f.read()
  755. else:
  756. video = self.data
  757. if isinstance(video, unicode_type):
  758. # unicode input is already b64-encoded
  759. b64_video = video
  760. else:
  761. b64_video = base64_encode(video).decode('ascii').rstrip()
  762. output = """<video controls>
  763. <source src="data:{0};base64,{1}" type="{0}">
  764. Your browser does not support the video tag.
  765. </video>""".format(mimetype, b64_video)
  766. return output
  767. def reload(self):
  768. # TODO
  769. pass
  770. def _repr_png_(self):
  771. # TODO
  772. pass
  773. def _repr_jpeg_(self):
  774. # TODO
  775. pass
  776. def clear_output(wait=False):
  777. """Clear the output of the current cell receiving output.
  778. Parameters
  779. ----------
  780. wait : bool [default: false]
  781. Wait to clear the output until new output is available to replace it."""
  782. from IPython.core.interactiveshell import InteractiveShell
  783. if InteractiveShell.initialized():
  784. InteractiveShell.instance().display_pub.clear_output(wait)
  785. else:
  786. print('\033[2K\r', end='')
  787. sys.stdout.flush()
  788. print('\033[2K\r', end='')
  789. sys.stderr.flush()
  790. @skip_doctest
  791. def set_matplotlib_formats(*formats, **kwargs):
  792. """Select figure formats for the inline backend. Optionally pass quality for JPEG.
  793. For example, this enables PNG and JPEG output with a JPEG quality of 90%::
  794. In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
  795. To set this in your config files use the following::
  796. c.InlineBackend.figure_formats = {'png', 'jpeg'}
  797. c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
  798. Parameters
  799. ----------
  800. *formats : strs
  801. One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
  802. **kwargs :
  803. Keyword args will be relayed to ``figure.canvas.print_figure``.
  804. """
  805. from IPython.core.interactiveshell import InteractiveShell
  806. from IPython.core.pylabtools import select_figure_formats
  807. # build kwargs, starting with InlineBackend config
  808. kw = {}
  809. from ipykernel.pylab.config import InlineBackend
  810. cfg = InlineBackend.instance()
  811. kw.update(cfg.print_figure_kwargs)
  812. kw.update(**kwargs)
  813. shell = InteractiveShell.instance()
  814. select_figure_formats(shell, formats, **kw)
  815. @skip_doctest
  816. def set_matplotlib_close(close=True):
  817. """Set whether the inline backend closes all figures automatically or not.
  818. By default, the inline backend used in the IPython Notebook will close all
  819. matplotlib figures automatically after each cell is run. This means that
  820. plots in different cells won't interfere. Sometimes, you may want to make
  821. a plot in one cell and then refine it in later cells. This can be accomplished
  822. by::
  823. In [1]: set_matplotlib_close(False)
  824. To set this in your config files use the following::
  825. c.InlineBackend.close_figures = False
  826. Parameters
  827. ----------
  828. close : bool
  829. Should all matplotlib figures be automatically closed after each cell is
  830. run?
  831. """
  832. from ipykernel.pylab.config import InlineBackend
  833. cfg = InlineBackend.instance()
  834. cfg.close_figures = close