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