##// END OF EJS Templates
Restoring two lines I accidentally removed in display.py
Nick Tallant -
Show More
@@ -1,1468 +1,1470 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Top-level display functions for displaying object in different formats."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from binascii import b2a_hex, b2a_base64, hexlify
9 9 import json
10 10 import mimetypes
11 11 import os
12 12 import struct
13 13 import sys
14 14 import warnings
15 15 from copy import deepcopy
16 16
17 17 from IPython.utils.py3compat import cast_unicode
18 18 from IPython.testing.skipdoctest import skip_doctest
19 19
20 20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
21 21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
22 22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
23 23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
24 24 'GeoJSON', 'Javascript', 'Image', 'clear_output', 'set_matplotlib_formats',
25 25 'set_matplotlib_close', 'publish_display_data', 'update_display', 'DisplayHandle',
26 26 'Video']
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # utility functions
30 30 #-----------------------------------------------------------------------------
31 31
32 32 def _safe_exists(path):
33 33 """Check path, but don't let exceptions raise"""
34 34 try:
35 35 return os.path.exists(path)
36 36 except Exception:
37 37 return False
38 38
39 39 def _merge(d1, d2):
40 40 """Like update, but merges sub-dicts instead of clobbering at the top level.
41 41
42 42 Updates d1 in-place
43 43 """
44 44
45 45 if not isinstance(d2, dict) or not isinstance(d1, dict):
46 46 return d2
47 47 for key, value in d2.items():
48 48 d1[key] = _merge(d1.get(key), value)
49 49 return d1
50 50
51 51 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
52 52 """internal implementation of all display_foo methods
53 53
54 54 Parameters
55 55 ----------
56 56 mimetype : str
57 57 The mimetype to be published (e.g. 'image/png')
58 58 objs : tuple of objects
59 59 The Python objects to display, or if raw=True raw text data to
60 60 display.
61 61 raw : bool
62 62 Are the data objects raw data or Python objects that need to be
63 63 formatted before display? [default: False]
64 64 metadata : dict (optional)
65 65 Metadata to be associated with the specific mimetype output.
66 66 """
67 67 if metadata:
68 68 metadata = {mimetype: metadata}
69 69 if raw:
70 70 # turn list of pngdata into list of { 'image/png': pngdata }
71 71 objs = [ {mimetype: obj} for obj in objs ]
72 72 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
73 73
74 74 #-----------------------------------------------------------------------------
75 75 # Main functions
76 76 #-----------------------------------------------------------------------------
77 77
78 78 # use * to indicate transient is keyword-only
79 79 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
80 80 """Publish data and metadata to all frontends.
81 81
82 82 See the ``display_data`` message in the messaging documentation for
83 83 more details about this message type.
84 84
85 85 Keys of data and metadata can be any mime-type.
86 86
87 87 Parameters
88 88 ----------
89 89 data : dict
90 90 A dictionary having keys that are valid MIME types (like
91 91 'text/plain' or 'image/svg+xml') and values that are the data for
92 92 that MIME type. The data itself must be a JSON'able data
93 93 structure. Minimally all data should have the 'text/plain' data,
94 94 which can be displayed by all frontends. If more than the plain
95 95 text is given, it is up to the frontend to decide which
96 96 representation to use.
97 97 metadata : dict
98 98 A dictionary for metadata related to the data. This can contain
99 99 arbitrary key, value pairs that frontends can use to interpret
100 100 the data. mime-type keys matching those in data can be used
101 101 to specify metadata about particular representations.
102 102 source : str, deprecated
103 103 Unused.
104 104 transient : dict, keyword-only
105 105 A dictionary of transient data, such as display_id.
106 106 """
107 107 from IPython.core.interactiveshell import InteractiveShell
108 108
109 109 display_pub = InteractiveShell.instance().display_pub
110 110
111 111 # only pass transient if supplied,
112 112 # to avoid errors with older ipykernel.
113 113 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
114 114 if transient:
115 115 kwargs['transient'] = transient
116 116
117 117 display_pub.publish(
118 118 data=data,
119 119 metadata=metadata,
120 120 **kwargs
121 121 )
122 122
123 123
124 124 def _new_id():
125 125 """Generate a new random text id with urandom"""
126 126 return b2a_hex(os.urandom(16)).decode('ascii')
127 127
128 128
129 129 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
130 130 """Display a Python object in all frontends.
131 131
132 132 By default all representations will be computed and sent to the frontends.
133 133 Frontends can decide which representation is used and how.
134 134
135 135 In terminal IPython this will be similar to using :func:`print`, for use in richer
136 136 frontends see Jupyter notebook examples with rich display logic.
137 137
138 138 Parameters
139 139 ----------
140 140 objs : tuple of objects
141 141 The Python objects to display.
142 142 raw : bool, optional
143 143 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
144 144 or Python objects that need to be formatted before display? [default: False]
145 145 include : list, tuple or set, optional
146 146 A list of format type strings (MIME types) to include in the
147 147 format data dict. If this is set *only* the format types included
148 148 in this list will be computed.
149 149 exclude : list, tuple or set, optional
150 150 A list of format type strings (MIME types) to exclude in the format
151 151 data dict. If this is set all format types will be computed,
152 152 except for those included in this argument.
153 153 metadata : dict, optional
154 154 A dictionary of metadata to associate with the output.
155 155 mime-type keys in this dictionary will be associated with the individual
156 156 representation formats, if they exist.
157 157 transient : dict, optional
158 158 A dictionary of transient data to associate with the output.
159 159 Data in this dict should not be persisted to files (e.g. notebooks).
160 160 display_id : str, bool optional
161 161 Set an id for the display.
162 162 This id can be used for updating this display area later via update_display.
163 163 If given as `True`, generate a new `display_id`
164 164 kwargs: additional keyword-args, optional
165 165 Additional keyword-arguments are passed through to the display publisher.
166 166
167 167 Returns
168 168 -------
169 169
170 170 handle: DisplayHandle
171 171 Returns a handle on updatable displays for use with :func:`update_display`,
172 172 if `display_id` is given. Returns :any:`None` if no `display_id` is given
173 173 (default).
174 174
175 175 Examples
176 176 --------
177 177
178 178 >>> class Json(object):
179 179 ... def __init__(self, json):
180 180 ... self.json = json
181 181 ... def _repr_pretty_(self, pp, cycle):
182 182 ... import json
183 183 ... pp.text(json.dumps(self.json, indent=2))
184 184 ... def __repr__(self):
185 185 ... return str(self.json)
186 186 ...
187 187
188 188 >>> d = Json({1:2, 3: {4:5}})
189 189
190 190 >>> print(d)
191 191 {1: 2, 3: {4: 5}}
192 192
193 193 >>> display(d)
194 194 {
195 195 "1": 2,
196 196 "3": {
197 197 "4": 5
198 198 }
199 199 }
200 200
201 201 >>> def int_formatter(integer, pp, cycle):
202 202 ... pp.text('I'*integer)
203 203
204 204 >>> plain = get_ipython().display_formatter.formatters['text/plain']
205 205 >>> plain.for_type(int, int_formatter)
206 206 <function _repr_pprint at 0x...>
207 207 >>> display(7-5)
208 208 II
209 209
210 210 >>> del plain.type_printers[int]
211 211 >>> display(7-5)
212 212 2
213 213
214 214 See Also
215 215 --------
216 216
217 217 :func:`update_display`
218 218
219 219 Notes
220 220 -----
221 221
222 222 In Python, objects can declare their textual representation using the
223 223 `__repr__` method. IPython expands on this idea and allows objects to declare
224 224 other, rich representations including:
225 225
226 226 - HTML
227 227 - JSON
228 228 - PNG
229 229 - JPEG
230 230 - SVG
231 231 - LaTeX
232 232
233 233 A single object can declare some or all of these representations; all are
234 234 handled by IPython's display system.
235 235
236 236 The main idea of the first approach is that you have to implement special
237 237 display methods when you define your class, one for each representation you
238 238 want to use. Here is a list of the names of the special methods and the
239 239 values they must return:
240 240
241 241 - `_repr_html_`: return raw HTML as a string, or a tuple (see below).
242 242 - `_repr_json_`: return a JSONable dict, or a tuple (see below).
243 243 - `_repr_jpeg_`: return raw JPEG data, or a tuple (see below).
244 244 - `_repr_png_`: return raw PNG data, or a tuple (see below).
245 245 - `_repr_svg_`: return raw SVG data as a string, or a tuple (see below).
246 246 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$",
247 247 or a tuple (see below).
248 248 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
249 249 from all mimetypes to data.
250 250 Use this for any mime-type not listed above.
251 251
252 252 The above functions may also return the object's metadata alonside the
253 253 data. If the metadata is available, the functions will return a tuple
254 254 containing the data and metadata, in that order. If there is no metadata
255 255 available, then the functions will return the data only.
256 256
257 257 When you are directly writing your own classes, you can adapt them for
258 258 display in IPython by following the above approach. But in practice, you
259 259 often need to work with existing classes that you can't easily modify.
260 260
261 261 You can refer to the documentation on integrating with the display system in
262 262 order to register custom formatters for already existing types
263 263 (:ref:`integrating_rich_display`).
264 264
265 265 .. versionadded:: 5.4 display available without import
266 266 .. versionadded:: 6.1 display available without import
267 267
268 268 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
269 269 the user without import. If you are using display in a document that might
270 270 be used in a pure python context or with older version of IPython, use the
271 271 following import at the top of your file::
272 272
273 273 from IPython.display import display
274 274
275 275 """
276 276 from IPython.core.interactiveshell import InteractiveShell
277 277
278 278 if not InteractiveShell.initialized():
279 279 # Directly print objects.
280 280 print(*objs)
281 281 return
282 282
283 283 raw = kwargs.pop('raw', False)
284 284 if transient is None:
285 285 transient = {}
286 286 if metadata is None:
287 287 metadata={}
288 288 if display_id:
289 289 if display_id is True:
290 290 display_id = _new_id()
291 291 transient['display_id'] = display_id
292 292 if kwargs.get('update') and 'display_id' not in transient:
293 293 raise TypeError('display_id required for update_display')
294 294 if transient:
295 295 kwargs['transient'] = transient
296 296
297 297 if not raw:
298 298 format = InteractiveShell.instance().display_formatter.format
299 299
300 300 for obj in objs:
301 301 if raw:
302 302 publish_display_data(data=obj, metadata=metadata, **kwargs)
303 303 else:
304 304 format_dict, md_dict = format(obj, include=include, exclude=exclude)
305 305 if not format_dict:
306 306 # nothing to display (e.g. _ipython_display_ took over)
307 307 continue
308 308 if metadata:
309 309 # kwarg-specified metadata gets precedence
310 310 _merge(md_dict, metadata)
311 311 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
312 312 if display_id:
313 313 return DisplayHandle(display_id)
314 314
315 315
316 316 # use * for keyword-only display_id arg
317 317 def update_display(obj, *, display_id, **kwargs):
318 318 """Update an existing display by id
319 319
320 320 Parameters
321 321 ----------
322 322
323 323 obj:
324 324 The object with which to update the display
325 325 display_id: keyword-only
326 326 The id of the display to update
327 327
328 328 See Also
329 329 --------
330 330
331 331 :func:`display`
332 332 """
333 333 kwargs['update'] = True
334 334 display(obj, display_id=display_id, **kwargs)
335 335
336 336
337 337 class DisplayHandle(object):
338 338 """A handle on an updatable display
339 339
340 340 Call `.update(obj)` to display a new object.
341 341
342 342 Call `.display(obj`) to add a new instance of this display,
343 343 and update existing instances.
344 344
345 345 See Also
346 346 --------
347 347
348 348 :func:`display`, :func:`update_display`
349 349
350 350 """
351 351
352 352 def __init__(self, display_id=None):
353 353 if display_id is None:
354 354 display_id = _new_id()
355 355 self.display_id = display_id
356 356
357 357 def __repr__(self):
358 358 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
359 359
360 360 def display(self, obj, **kwargs):
361 361 """Make a new display with my id, updating existing instances.
362 362
363 363 Parameters
364 364 ----------
365 365
366 366 obj:
367 367 object to display
368 368 **kwargs:
369 369 additional keyword arguments passed to display
370 370 """
371 371 display(obj, display_id=self.display_id, **kwargs)
372 372
373 373 def update(self, obj, **kwargs):
374 374 """Update existing displays with my id
375 375
376 376 Parameters
377 377 ----------
378 378
379 379 obj:
380 380 object to display
381 381 **kwargs:
382 382 additional keyword arguments passed to update_display
383 383 """
384 384 update_display(obj, display_id=self.display_id, **kwargs)
385 385
386 386
387 387 def display_pretty(*objs, **kwargs):
388 388 """Display the pretty (default) representation of an object.
389 389
390 390 Parameters
391 391 ----------
392 392 objs : tuple of objects
393 393 The Python objects to display, or if raw=True raw text data to
394 394 display.
395 395 raw : bool
396 396 Are the data objects raw data or Python objects that need to be
397 397 formatted before display? [default: False]
398 398 metadata : dict (optional)
399 399 Metadata to be associated with the specific mimetype output.
400 400 """
401 401 _display_mimetype('text/plain', objs, **kwargs)
402 402
403 403
404 404 def display_html(*objs, **kwargs):
405 405 """Display the HTML representation of an object.
406 406
407 407 Note: If raw=False and the object does not have a HTML
408 408 representation, no HTML will be shown.
409 409
410 410 Parameters
411 411 ----------
412 412 objs : tuple of objects
413 413 The Python objects to display, or if raw=True raw HTML data to
414 414 display.
415 415 raw : bool
416 416 Are the data objects raw data or Python objects that need to be
417 417 formatted before display? [default: False]
418 418 metadata : dict (optional)
419 419 Metadata to be associated with the specific mimetype output.
420 420 """
421 421 _display_mimetype('text/html', objs, **kwargs)
422 422
423 423
424 424 def display_markdown(*objs, **kwargs):
425 425 """Displays the Markdown representation of an object.
426 426
427 427 Parameters
428 428 ----------
429 429 objs : tuple of objects
430 430 The Python objects to display, or if raw=True raw markdown data to
431 431 display.
432 432 raw : bool
433 433 Are the data objects raw data or Python objects that need to be
434 434 formatted before display? [default: False]
435 435 metadata : dict (optional)
436 436 Metadata to be associated with the specific mimetype output.
437 437 """
438 438
439 439 _display_mimetype('text/markdown', objs, **kwargs)
440 440
441 441
442 442 def display_svg(*objs, **kwargs):
443 443 """Display the SVG representation of an object.
444 444
445 445 Parameters
446 446 ----------
447 447 objs : tuple of objects
448 448 The Python objects to display, or if raw=True raw svg data to
449 449 display.
450 450 raw : bool
451 451 Are the data objects raw data or Python objects that need to be
452 452 formatted before display? [default: False]
453 453 metadata : dict (optional)
454 454 Metadata to be associated with the specific mimetype output.
455 455 """
456 456 _display_mimetype('image/svg+xml', objs, **kwargs)
457 457
458 458
459 459 def display_png(*objs, **kwargs):
460 460 """Display the PNG representation of an object.
461 461
462 462 Parameters
463 463 ----------
464 464 objs : tuple of objects
465 465 The Python objects to display, or if raw=True raw png data to
466 466 display.
467 467 raw : bool
468 468 Are the data objects raw data or Python objects that need to be
469 469 formatted before display? [default: False]
470 470 metadata : dict (optional)
471 471 Metadata to be associated with the specific mimetype output.
472 472 """
473 473 _display_mimetype('image/png', objs, **kwargs)
474 474
475 475
476 476 def display_jpeg(*objs, **kwargs):
477 477 """Display the JPEG representation of an object.
478 478
479 479 Parameters
480 480 ----------
481 481 objs : tuple of objects
482 482 The Python objects to display, or if raw=True raw JPEG data to
483 483 display.
484 484 raw : bool
485 485 Are the data objects raw data or Python objects that need to be
486 486 formatted before display? [default: False]
487 487 metadata : dict (optional)
488 488 Metadata to be associated with the specific mimetype output.
489 489 """
490 490 _display_mimetype('image/jpeg', objs, **kwargs)
491 491
492 492
493 493 def display_latex(*objs, **kwargs):
494 494 """Display the LaTeX representation of an object.
495 495
496 496 Parameters
497 497 ----------
498 498 objs : tuple of objects
499 499 The Python objects to display, or if raw=True raw latex data to
500 500 display.
501 501 raw : bool
502 502 Are the data objects raw data or Python objects that need to be
503 503 formatted before display? [default: False]
504 504 metadata : dict (optional)
505 505 Metadata to be associated with the specific mimetype output.
506 506 """
507 507 _display_mimetype('text/latex', objs, **kwargs)
508 508
509 509
510 510 def display_json(*objs, **kwargs):
511 511 """Display the JSON representation of an object.
512 512
513 513 Note that not many frontends support displaying JSON.
514 514
515 515 Parameters
516 516 ----------
517 517 objs : tuple of objects
518 518 The Python objects to display, or if raw=True raw json data to
519 519 display.
520 520 raw : bool
521 521 Are the data objects raw data or Python objects that need to be
522 522 formatted before display? [default: False]
523 523 metadata : dict (optional)
524 524 Metadata to be associated with the specific mimetype output.
525 525 """
526 526 _display_mimetype('application/json', objs, **kwargs)
527 527
528 528
529 529 def display_javascript(*objs, **kwargs):
530 530 """Display the Javascript representation of an object.
531 531
532 532 Parameters
533 533 ----------
534 534 objs : tuple of objects
535 535 The Python objects to display, or if raw=True raw javascript data to
536 536 display.
537 537 raw : bool
538 538 Are the data objects raw data or Python objects that need to be
539 539 formatted before display? [default: False]
540 540 metadata : dict (optional)
541 541 Metadata to be associated with the specific mimetype output.
542 542 """
543 543 _display_mimetype('application/javascript', objs, **kwargs)
544 544
545 545
546 546 def display_pdf(*objs, **kwargs):
547 547 """Display the PDF representation of an object.
548 548
549 549 Parameters
550 550 ----------
551 551 objs : tuple of objects
552 552 The Python objects to display, or if raw=True raw javascript data to
553 553 display.
554 554 raw : bool
555 555 Are the data objects raw data or Python objects that need to be
556 556 formatted before display? [default: False]
557 557 metadata : dict (optional)
558 558 Metadata to be associated with the specific mimetype output.
559 559 """
560 560 _display_mimetype('application/pdf', objs, **kwargs)
561 561
562 562
563 563 #-----------------------------------------------------------------------------
564 564 # Smart classes
565 565 #-----------------------------------------------------------------------------
566 566
567 567
568 568 class DisplayObject(object):
569 569 """An object that wraps data to be displayed."""
570 570
571 571 _read_flags = 'r'
572 572 _show_mem_addr = False
573 573 metadata = None
574 574
575 575 def __init__(self, data=None, url=None, filename=None, metadata=None):
576 576 """Create a display object given raw data.
577 577
578 578 When this object is returned by an expression or passed to the
579 579 display function, it will result in the data being displayed
580 580 in the frontend. The MIME type of the data should match the
581 581 subclasses used, so the Png subclass should be used for 'image/png'
582 582 data. If the data is a URL, the data will first be downloaded
583 583 and then displayed. If
584 584
585 585 Parameters
586 586 ----------
587 587 data : unicode, str or bytes
588 588 The raw data or a URL or file to load the data from
589 589 url : unicode
590 590 A URL to download the data from.
591 591 filename : unicode
592 592 Path to a local file to load the data from.
593 593 metadata : dict
594 594 Dict of metadata associated to be the object when displayed
595 595 """
596 596 if data is not None and isinstance(data, str):
597 597 if data.startswith('http') and url is None:
598 598 url = data
599 599 filename = None
600 600 data = None
601 601 elif _safe_exists(data) and filename is None:
602 602 url = None
603 603 filename = data
604 604 data = None
605 605
606 606 self.data = data
607 607 self.url = url
608 608 self.filename = filename
609 609
610 610 if metadata is not None:
611 611 self.metadata = metadata
612 612 elif self.metadata is None:
613 613 self.metadata = {}
614 614
615 615 self.reload()
616 616 self._check_data()
617 617
618 618 def __repr__(self):
619 619 if not self._show_mem_addr:
620 620 cls = self.__class__
621 621 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
622 622 else:
623 623 r = super(DisplayObject, self).__repr__()
624 624 return r
625 625
626 626 def _check_data(self):
627 627 """Override in subclasses if there's something to check."""
628 628 pass
629 629
630 630 def _data_and_metadata(self):
631 631 """shortcut for returning metadata with shape information, if defined"""
632 632 if self.metadata:
633 633 return self.data, deepcopy(self.metadata)
634 634 else:
635 635 return self.data
636 636
637 637 def reload(self):
638 638 """Reload the raw data from file or URL."""
639 639 if self.filename is not None:
640 640 with open(self.filename, self._read_flags) as f:
641 641 self.data = f.read()
642 642 elif self.url is not None:
643 643 try:
644 644 # Deferred import
645 645 from urllib.request import urlopen
646 646 response = urlopen(self.url)
647 647 self.data = response.read()
648 648 # extract encoding from header, if there is one:
649 649 encoding = None
650 650 for sub in response.headers['content-type'].split(';'):
651 651 sub = sub.strip()
652 652 if sub.startswith('charset'):
653 653 encoding = sub.split('=')[-1].strip()
654 654 break
655 655 # decode data, if an encoding was specified
656 656 if encoding:
657 657 self.data = self.data.decode(encoding, 'replace')
658 658 except:
659 659 self.data = None
660 660
661 661 class TextDisplayObject(DisplayObject):
662 662 """Validate that display data is text"""
663 663 def _check_data(self):
664 664 if self.data is not None and not isinstance(self.data, str):
665 665 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
666 666
667 667 class Pretty(TextDisplayObject):
668 668
669 669 def _repr_pretty_(self, pp, cycle):
670 670 return pp.text(self.data)
671 671
672 672
673 673 class HTML(TextDisplayObject):
674 674
675 675 def __init__(self, data=None, url=None, filename=None, metadata=None):
676 676 def warn():
677 677 if not data:
678 678 return False
679 679
680 680 #
681 681 # Avoid calling lower() on the entire data, because it could be a
682 682 # long string and we're only interested in its beginning and end.
683 683 #
684 684 prefix = data[:10].lower()
685 685 suffix = data[-10:].lower()
686 686 return prefix.startswith("<iframe ") and suffix.endswith("</iframe>")
687 687
688 688 if warn():
689 689 warnings.warn("Consider using IPython.display.IFrame instead")
690 690 super(HTML, self).__init__(data=data, url=url, filename=filename, metadata=metadata)
691 691
692 692 def _repr_html_(self):
693 693 return self._data_and_metadata()
694 694
695 695 def __html__(self):
696 696 """
697 697 This method exists to inform other HTML-using modules (e.g. Markupsafe,
698 698 htmltag, etc) that this object is HTML and does not need things like
699 699 special characters (<>&) escaped.
700 700 """
701 701 return self._repr_html_()
702 702
703 703
704 704 class Markdown(TextDisplayObject):
705 705
706 706 def _repr_markdown_(self):
707 707 return self._data_and_metadata()
708 708
709 709
710 710 class Math(TextDisplayObject):
711 711
712 712 def _repr_latex_(self):
713 713 s = r"$\displaystyle %s$" % self.data.strip('$')
714 714 if self.metadata:
715 715 return s, deepcopy(self.metadata)
716 716 else:
717 717 return s
718 718
719 719
720 720 class Latex(TextDisplayObject):
721 721
722 722 def _repr_latex_(self):
723 723 return self._data_and_metadata()
724 724
725 725
726 726 class SVG(DisplayObject):
727 727
728 728 _read_flags = 'rb'
729 729 # wrap data in a property, which extracts the <svg> tag, discarding
730 730 # document headers
731 731 _data = None
732 732
733 733 @property
734 734 def data(self):
735 735 return self._data
736 736
737 737 @data.setter
738 738 def data(self, svg):
739 739 if svg is None:
740 740 self._data = None
741 741 return
742 742 # parse into dom object
743 743 from xml.dom import minidom
744 744 x = minidom.parseString(svg)
745 745 # get svg tag (should be 1)
746 746 found_svg = x.getElementsByTagName('svg')
747 747 if found_svg:
748 748 svg = found_svg[0].toxml()
749 749 else:
750 750 # fallback on the input, trust the user
751 751 # but this is probably an error.
752 752 pass
753 753 svg = cast_unicode(svg)
754 754 self._data = svg
755 755
756 756 def _repr_svg_(self):
757 757 return self._data_and_metadata()
758 758
759 759 class ProgressBar(DisplayObject):
760 760 """Progressbar supports displaying a progressbar like element
761 761 """
762 762 def __init__(self, total):
763 763 """Creates a new progressbar
764 764
765 765 Parameters
766 766 ----------
767 767 total : int
768 768 maximum size of the progressbar
769 769 """
770 770 self.total = total
771 771 self._progress = 0
772 772 self.html_width = '60ex'
773 773 self.text_width = 60
774 774 self._display_id = hexlify(os.urandom(8)).decode('ascii')
775 775
776 776 def __repr__(self):
777 777 fraction = self.progress / self.total
778 778 filled = '=' * int(fraction * self.text_width)
779 779 rest = ' ' * (self.text_width - len(filled))
780 780 return '[{}{}] {}/{}'.format(
781 781 filled, rest,
782 782 self.progress, self.total,
783 783 )
784 784
785 785 def _repr_html_(self):
786 786 return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
787 787 self.html_width, self.total, self.progress)
788 788
789 789 def display(self):
790 790 display(self, display_id=self._display_id)
791 791
792 792 def update(self):
793 793 display(self, display_id=self._display_id, update=True)
794 794
795 795 @property
796 796 def progress(self):
797 797 return self._progress
798 798
799 799 @progress.setter
800 800 def progress(self, value):
801 801 self._progress = value
802 802 self.update()
803 803
804 804 def __iter__(self):
805 805 self.display()
806 806 self._progress = -1 # First iteration is 0
807 807 return self
808 808
809 809 def __next__(self):
810 810 """Returns current value and increments display by one."""
811 811 self.progress += 1
812 812 if self.progress < self.total:
813 813 return self.progress
814 814 else:
815 815 raise StopIteration()
816 816
817 817 class JSON(DisplayObject):
818 818 """JSON expects a JSON-able dict or list
819 819
820 820 not an already-serialized JSON string.
821 821
822 822 Scalar types (None, number, string) are not allowed, only dict or list containers.
823 823 """
824 824 # wrap data in a property, which warns about passing already-serialized JSON
825 825 _data = None
826 826 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs):
827 827 """Create a JSON display object given raw data.
828 828
829 829 Parameters
830 830 ----------
831 831 data : dict or list
832 832 JSON data to display. Not an already-serialized JSON string.
833 833 Scalar types (None, number, string) are not allowed, only dict
834 834 or list containers.
835 835 url : unicode
836 836 A URL to download the data from.
837 837 filename : unicode
838 838 Path to a local file to load the data from.
839 839 expanded : boolean
840 840 Metadata to control whether a JSON display component is expanded.
841 841 metadata: dict
842 842 Specify extra metadata to attach to the json display object.
843 843 root : str
844 844 The name of the root element of the JSON tree
845 845 """
846 846 self.metadata = {
847 847 'expanded': expanded,
848 848 'root': root,
849 849 }
850 850 if metadata:
851 851 self.metadata.update(metadata)
852 852 if kwargs:
853 853 self.metadata.update(kwargs)
854 854 super(JSON, self).__init__(data=data, url=url, filename=filename)
855 855
856 856 def _check_data(self):
857 857 if self.data is not None and not isinstance(self.data, (dict, list)):
858 858 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
859 859
860 860 @property
861 861 def data(self):
862 862 return self._data
863 863
864 864 @data.setter
865 865 def data(self, data):
866 866 if isinstance(data, str):
867 867 if getattr(self, 'filename', None) is None:
868 868 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
869 869 data = json.loads(data)
870 870 self._data = data
871 871
872 872 def _data_and_metadata(self):
873 873 return self.data, self.metadata
874 874
875 875 def _repr_json_(self):
876 876 return self._data_and_metadata()
877 877
878 878 _css_t = """var link = document.createElement("link");
879 879 link.ref = "stylesheet";
880 880 link.type = "text/css";
881 881 link.href = "%s";
882 882 document.head.appendChild(link);
883 883 """
884 884
885 885 _lib_t1 = """new Promise(function(resolve, reject) {
886 886 var script = document.createElement("script");
887 887 script.onload = resolve;
888 888 script.onerror = reject;
889 889 script.src = "%s";
890 890 document.head.appendChild(script);
891 891 }).then(() => {
892 892 """
893 893
894 894 _lib_t2 = """
895 895 });"""
896 896
897 897 class GeoJSON(JSON):
898 898 """GeoJSON expects JSON-able dict
899 899
900 900 not an already-serialized JSON string.
901 901
902 902 Scalar types (None, number, string) are not allowed, only dict containers.
903 903 """
904 904
905 905 def __init__(self, *args, **kwargs):
906 906 """Create a GeoJSON display object given raw data.
907 907
908 908 Parameters
909 909 ----------
910 910 data : dict or list
911 911 VegaLite data. Not an already-serialized JSON string.
912 912 Scalar types (None, number, string) are not allowed, only dict
913 913 or list containers.
914 914 url_template : string
915 915 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
916 916 layer_options : dict
917 917 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
918 918 url : unicode
919 919 A URL to download the data from.
920 920 filename : unicode
921 921 Path to a local file to load the data from.
922 922 metadata: dict
923 923 Specify extra metadata to attach to the json display object.
924 924
925 925 Examples
926 926 --------
927 927
928 928 The following will display an interactive map of Mars with a point of
929 929 interest on frontend that do support GeoJSON display.
930 930
931 931 >>> from IPython.display import GeoJSON
932 932
933 933 >>> GeoJSON(data={
934 934 ... "type": "Feature",
935 935 ... "geometry": {
936 936 ... "type": "Point",
937 937 ... "coordinates": [-81.327, 296.038]
938 938 ... }
939 939 ... },
940 940 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
941 941 ... layer_options={
942 942 ... "basemap_id": "celestia_mars-shaded-16k_global",
943 943 ... "attribution" : "Celestia/praesepe",
944 944 ... "minZoom" : 0,
945 945 ... "maxZoom" : 18,
946 946 ... })
947 947 <IPython.core.display.GeoJSON object>
948 948
949 949 In the terminal IPython, you will only see the text representation of
950 950 the GeoJSON object.
951 951
952 952 """
953 953
954 954 super(GeoJSON, self).__init__(*args, **kwargs)
955 955
956 956
957 957 def _ipython_display_(self):
958 958 bundle = {
959 959 'application/geo+json': self.data,
960 960 'text/plain': '<IPython.display.GeoJSON object>'
961 961 }
962 962 metadata = {
963 963 'application/geo+json': self.metadata
964 964 }
965 965 display(bundle, metadata=metadata, raw=True)
966 966
967 967 class Javascript(TextDisplayObject):
968 968
969 969 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
970 970 """Create a Javascript display object given raw data.
971 971
972 972 When this object is returned by an expression or passed to the
973 973 display function, it will result in the data being displayed
974 974 in the frontend. If the data is a URL, the data will first be
975 975 downloaded and then displayed.
976 976
977 977 In the Notebook, the containing element will be available as `element`,
978 978 and jQuery will be available. Content appended to `element` will be
979 979 visible in the output area.
980 980
981 981 Parameters
982 982 ----------
983 983 data : unicode, str or bytes
984 984 The Javascript source code or a URL to download it from.
985 985 url : unicode
986 986 A URL to download the data from.
987 987 filename : unicode
988 988 Path to a local file to load the data from.
989 989 lib : list or str
990 990 A sequence of Javascript library URLs to load asynchronously before
991 991 running the source code. The full URLs of the libraries should
992 992 be given. A single Javascript library URL can also be given as a
993 993 string.
994 994 css: : list or str
995 995 A sequence of css files to load before running the source code.
996 996 The full URLs of the css files should be given. A single css URL
997 997 can also be given as a string.
998 998 """
999 999 if isinstance(lib, str):
1000 1000 lib = [lib]
1001 1001 elif lib is None:
1002 1002 lib = []
1003 1003 if isinstance(css, str):
1004 1004 css = [css]
1005 1005 elif css is None:
1006 1006 css = []
1007 1007 if not isinstance(lib, (list,tuple)):
1008 1008 raise TypeError('expected sequence, got: %r' % lib)
1009 1009 if not isinstance(css, (list,tuple)):
1010 1010 raise TypeError('expected sequence, got: %r' % css)
1011 1011 self.lib = lib
1012 1012 self.css = css
1013 1013 super(Javascript, self).__init__(data=data, url=url, filename=filename)
1014 1014
1015 1015 def _repr_javascript_(self):
1016 1016 r = ''
1017 1017 for c in self.css:
1018 1018 r += _css_t % c
1019 1019 for l in self.lib:
1020 1020 r += _lib_t1 % l
1021 1021 r += self.data
1022 1022 r += _lib_t2*len(self.lib)
1023 1023 return r
1024 1024
1025 1025 # constants for identifying png/jpeg data
1026 1026 _PNG = b'\x89PNG\r\n\x1a\n'
1027 1027 _JPEG = b'\xff\xd8'
1028 1028
1029 1029 def _pngxy(data):
1030 1030 """read the (width, height) from a PNG header"""
1031 1031 ihdr = data.index(b'IHDR')
1032 1032 # next 8 bytes are width/height
1033 1033 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
1034 1034
1035 1035 def _jpegxy(data):
1036 1036 """read the (width, height) from a JPEG header"""
1037 1037 # adapted from http://www.64lines.com/jpeg-width-height
1038 1038
1039 1039 idx = 4
1040 1040 while True:
1041 1041 block_size = struct.unpack('>H', data[idx:idx+2])[0]
1042 1042 idx = idx + block_size
1043 1043 if data[idx:idx+2] == b'\xFF\xC0':
1044 1044 # found Start of Frame
1045 1045 iSOF = idx
1046 1046 break
1047 1047 else:
1048 1048 # read another block
1049 1049 idx += 2
1050 1050
1051 1051 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
1052 1052 return w, h
1053 1053
1054 1054 def _gifxy(data):
1055 1055 """read the (width, height) from a GIF header"""
1056 1056 return struct.unpack('<HH', data[6:10])
1057 1057
1058 1058
1059 1059 class Image(DisplayObject):
1060 1060
1061 1061 _read_flags = 'rb'
1062 1062 _FMT_JPEG = u'jpeg'
1063 1063 _FMT_PNG = u'png'
1064 1064 _FMT_GIF = u'gif'
1065 1065 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1066 1066 _MIMETYPES = {
1067 1067 _FMT_PNG: 'image/png',
1068 1068 _FMT_JPEG: 'image/jpeg',
1069 1069 _FMT_GIF: 'image/gif',
1070 1070 }
1071 1071
1072 1072 def __init__(self, data=None, url=None, filename=None, format=None,
1073 1073 embed=None, width=None, height=None, retina=False,
1074 1074 unconfined=False, metadata=None):
1075 1075 """Create a PNG/JPEG/GIF image object given raw data.
1076 1076
1077 1077 When this object is returned by an input cell or passed to the
1078 1078 display function, it will result in the image being displayed
1079 1079 in the frontend.
1080 1080
1081 1081 Parameters
1082 1082 ----------
1083 1083 data : unicode, str or bytes
1084 1084 The raw image data or a URL or filename to load the data from.
1085 1085 This always results in embedded image data.
1086 1086 url : unicode
1087 1087 A URL to download the data from. If you specify `url=`,
1088 1088 the image data will not be embedded unless you also specify `embed=True`.
1089 1089 filename : unicode
1090 1090 Path to a local file to load the data from.
1091 1091 Images from a file are always embedded.
1092 1092 format : unicode
1093 1093 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
1094 1094 for format will be inferred from the filename extension.
1095 1095 embed : bool
1096 1096 Should the image data be embedded using a data URI (True) or be
1097 1097 loaded using an <img> tag. Set this to True if you want the image
1098 1098 to be viewable later with no internet connection in the notebook.
1099 1099
1100 1100 Default is `True`, unless the keyword argument `url` is set, then
1101 1101 default value is `False`.
1102 1102
1103 1103 Note that QtConsole is not able to display images if `embed` is set to `False`
1104 1104 width : int
1105 1105 Width in pixels to which to constrain the image in html
1106 1106 height : int
1107 1107 Height in pixels to which to constrain the image in html
1108 1108 retina : bool
1109 1109 Automatically set the width and height to half of the measured
1110 1110 width and height.
1111 1111 This only works for embedded images because it reads the width/height
1112 1112 from image data.
1113 1113 For non-embedded images, you can just set the desired display width
1114 1114 and height directly.
1115 1115 unconfined: bool
1116 1116 Set unconfined=True to disable max-width confinement of the image.
1117 1117 metadata: dict
1118 1118 Specify extra metadata to attach to the image.
1119 1119
1120 1120 Examples
1121 1121 --------
1122 1122 # embedded image data, works in qtconsole and notebook
1123 1123 # when passed positionally, the first arg can be any of raw image data,
1124 1124 # a URL, or a filename from which to load image data.
1125 1125 # The result is always embedding image data for inline images.
1126 1126 Image('http://www.google.fr/images/srpr/logo3w.png')
1127 1127 Image('/path/to/image.jpg')
1128 1128 Image(b'RAW_PNG_DATA...')
1129 1129
1130 1130 # Specifying Image(url=...) does not embed the image data,
1131 1131 # it only generates `<img>` tag with a link to the source.
1132 1132 # This will not work in the qtconsole or offline.
1133 1133 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1134 1134
1135 1135 """
1136 1136 if filename is not None:
1137 1137 ext = self._find_ext(filename)
1138 1138 elif url is not None:
1139 1139 ext = self._find_ext(url)
1140 1140 elif data is None:
1141 1141 raise ValueError("No image data found. Expecting filename, url, or data.")
1142 1142 elif isinstance(data, str) and (
1143 1143 data.startswith('http') or _safe_exists(data)
1144 1144 ):
1145 1145 ext = self._find_ext(data)
1146 1146 else:
1147 1147 ext = None
1148 1148
1149 1149 if format is None:
1150 1150 if ext is not None:
1151 1151 if ext == u'jpg' or ext == u'jpeg':
1152 1152 format = self._FMT_JPEG
1153 1153 elif ext == u'png':
1154 1154 format = self._FMT_PNG
1155 1155 elif ext == u'gif':
1156 1156 format = self._FMT_GIF
1157 1157 else:
1158 1158 format = ext.lower()
1159 1159 elif isinstance(data, bytes):
1160 1160 # infer image type from image data header,
1161 1161 # only if format has not been specified.
1162 1162 if data[:2] == _JPEG:
1163 1163 format = self._FMT_JPEG
1164 1164
1165 1165 # failed to detect format, default png
1166 1166 if format is None:
1167 1167 format = self._FMT_PNG
1168 1168
1169 1169 if format.lower() == 'jpg':
1170 1170 # jpg->jpeg
1171 1171 format = self._FMT_JPEG
1172 1172
1173 1173 self.format = format.lower()
1174 1174 self.embed = embed if embed is not None else (url is None)
1175 1175
1176 1176 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1177 1177 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1178 1178 if self.embed:
1179 1179 self._mimetype = self._MIMETYPES.get(self.format)
1180 1180
1181 1181 self.width = width
1182 1182 self.height = height
1183 1183 self.retina = retina
1184 1184 self.unconfined = unconfined
1185 1185 super(Image, self).__init__(data=data, url=url, filename=filename,
1186 1186 metadata=metadata)
1187 1187
1188 1188 if self.width is None and self.metadata.get('width', {}):
1189 1189 self.width = metadata['width']
1190 1190
1191 1191 if self.height is None and self.metadata.get('height', {}):
1192 1192 self.height = metadata['height']
1193 1193
1194 1194 if retina:
1195 1195 self._retina_shape()
1196 1196
1197 1197
1198 1198 def _retina_shape(self):
1199 1199 """load pixel-doubled width and height from image data"""
1200 1200 if not self.embed:
1201 1201 return
1202 1202 if self.format == self._FMT_PNG:
1203 1203 w, h = _pngxy(self.data)
1204 1204 elif self.format == self._FMT_JPEG:
1205 1205 w, h = _jpegxy(self.data)
1206 1206 elif self.format == self._FMT_GIF:
1207 1207 w, h = _gifxy(self.data)
1208 1208 else:
1209 1209 # retina only supports png
1210 1210 return
1211 1211 self.width = w // 2
1212 1212 self.height = h // 2
1213 1213
1214 1214 def reload(self):
1215 1215 """Reload the raw data from file or URL."""
1216 1216 if self.embed:
1217 1217 super(Image,self).reload()
1218 1218 if self.retina:
1219 1219 self._retina_shape()
1220 1220
1221 1221 def _repr_html_(self):
1222 1222 if not self.embed:
1223 1223 width = height = klass = ''
1224 1224 if self.width:
1225 1225 width = ' width="%d"' % self.width
1226 1226 if self.height:
1227 1227 height = ' height="%d"' % self.height
1228 1228 if self.unconfined:
1229 1229 klass = ' class="unconfined"'
1230 1230 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1231 1231 url=self.url,
1232 1232 width=width,
1233 1233 height=height,
1234 1234 klass=klass,
1235 1235 )
1236 1236
1237 1237 def _repr_mimebundle_(self, include=None, exclude=None):
1238 1238 """Return the image as a mimebundle
1239 1239
1240 1240 Any new mimetype support should be implemented here.
1241 1241 """
1242 1242 if self.embed:
1243 1243 mimetype = self._mimetype
1244 1244 data, metadata = self._data_and_metadata(always_both=True)
1245 1245 if metadata:
1246 1246 metadata = {mimetype: metadata}
1247 1247 return {mimetype: data}, metadata
1248 1248 else:
1249 1249 return {'text/html': self._repr_html_()}
1250 1250
1251 1251 def _data_and_metadata(self, always_both=False):
1252 1252 """shortcut for returning metadata with shape information, if defined"""
1253 1253 try:
1254 1254 b64_data = b2a_base64(self.data).decode('ascii')
1255 1255 except TypeError:
1256 1256 raise FileNotFoundError(
1257 1257 "No such file or directory: '%s'" % (self.data))
1258 1258 md = {}
1259 1259 if self.metadata:
1260 1260 md.update(self.metadata)
1261 1261 if self.width:
1262 1262 md['width'] = self.width
1263 1263 if self.height:
1264 1264 md['height'] = self.height
1265 1265 if self.unconfined:
1266 1266 md['unconfined'] = self.unconfined
1267 1267 if md or always_both:
1268 1268 return b64_data, md
1269 1269 else:
1270 1270 return b64_data
1271 1271
1272 1272 def _repr_png_(self):
1273 return self._data_and_metadata()
1273 if self.embed and self.format == self._FMT_PNG:
1274 return self._data_and_metadata()
1274 1275
1275 1276 def _repr_jpeg_(self):
1276 return self._data_and_metadata()
1277 if self.embed and self.format == self._FMT_JPEG:
1278 return self._data_and_metadata()
1277 1279
1278 1280 def _find_ext(self, s):
1279 1281 return s.split('.')[-1].lower()
1280 1282
1281 1283
1282 1284 class Video(DisplayObject):
1283 1285
1284 1286 def __init__(self, data=None, url=None, filename=None, embed=False,
1285 1287 mimetype=None, width=None, height=None):
1286 1288 """Create a video object given raw data or an URL.
1287 1289
1288 1290 When this object is returned by an input cell or passed to the
1289 1291 display function, it will result in the video being displayed
1290 1292 in the frontend.
1291 1293
1292 1294 Parameters
1293 1295 ----------
1294 1296 data : unicode, str or bytes
1295 1297 The raw video data or a URL or filename to load the data from.
1296 1298 Raw data will require passing `embed=True`.
1297 1299 url : unicode
1298 1300 A URL for the video. If you specify `url=`,
1299 1301 the image data will not be embedded.
1300 1302 filename : unicode
1301 1303 Path to a local file containing the video.
1302 1304 Will be interpreted as a local URL unless `embed=True`.
1303 1305 embed : bool
1304 1306 Should the video be embedded using a data URI (True) or be
1305 1307 loaded using a <video> tag (False).
1306 1308
1307 1309 Since videos are large, embedding them should be avoided, if possible.
1308 1310 You must confirm embedding as your intention by passing `embed=True`.
1309 1311
1310 1312 Local files can be displayed with URLs without embedding the content, via::
1311 1313
1312 1314 Video('./video.mp4')
1313 1315
1314 1316 mimetype: unicode
1315 1317 Specify the mimetype for embedded videos.
1316 1318 Default will be guessed from file extension, if available.
1317 1319 width : int
1318 1320 Width in pixels to which to constrain the video in HTML.
1319 1321 If not supplied, defaults to the width of the video.
1320 1322 height : int
1321 1323 Height in pixels to which to constrain the video in html.
1322 1324 If not supplied, defaults to the height of the video.
1323 1325
1324 1326 Examples
1325 1327 --------
1326 1328
1327 1329 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1328 1330 Video('path/to/video.mp4')
1329 1331 Video('path/to/video.mp4', embed=True)
1330 1332 Video(b'raw-videodata', embed=True)
1331 1333 """
1332 1334 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1333 1335 url = data
1334 1336 data = None
1335 1337 elif os.path.exists(data):
1336 1338 filename = data
1337 1339 data = None
1338 1340
1339 1341 if data and not embed:
1340 1342 msg = ''.join([
1341 1343 "To embed videos, you must pass embed=True ",
1342 1344 "(this may make your notebook files huge)\n",
1343 1345 "Consider passing Video(url='...')",
1344 1346 ])
1345 1347 raise ValueError(msg)
1346 1348
1347 1349 self.mimetype = mimetype
1348 1350 self.embed = embed
1349 1351 self.width = width
1350 1352 self.height = height
1351 1353 super(Video, self).__init__(data=data, url=url, filename=filename)
1352 1354
1353 1355 def _repr_html_(self):
1354 1356 width = height = ''
1355 1357 if self.width:
1356 1358 width = ' width="%d"' % self.width
1357 1359 if self.height:
1358 1360 height = ' height="%d"' % self.height
1359 1361
1360 1362 # External URLs and potentially local files are not embedded into the
1361 1363 # notebook output.
1362 1364 if not self.embed:
1363 1365 url = self.url if self.url is not None else self.filename
1364 1366 output = """<video src="{0}" controls {1} {2}>
1365 1367 Your browser does not support the <code>video</code> element.
1366 1368 </video>""".format(url, width, height)
1367 1369 return output
1368 1370
1369 1371 # Embedded videos are base64-encoded.
1370 1372 mimetype = self.mimetype
1371 1373 if self.filename is not None:
1372 1374 if not mimetype:
1373 1375 mimetype, _ = mimetypes.guess_type(self.filename)
1374 1376
1375 1377 with open(self.filename, 'rb') as f:
1376 1378 video = f.read()
1377 1379 else:
1378 1380 video = self.data
1379 1381 if isinstance(video, str):
1380 1382 # unicode input is already b64-encoded
1381 1383 b64_video = video
1382 1384 else:
1383 1385 b64_video = b2a_base64(video).decode('ascii').rstrip()
1384 1386
1385 1387 output = """<video controls {0} {1}>
1386 1388 <source src="data:{2};base64,{3}" type="{2}">
1387 1389 Your browser does not support the video tag.
1388 1390 </video>""".format(width, height, mimetype, b64_video)
1389 1391 return output
1390 1392
1391 1393 def reload(self):
1392 1394 # TODO
1393 1395 pass
1394 1396
1395 1397
1396 1398 def clear_output(wait=False):
1397 1399 """Clear the output of the current cell receiving output.
1398 1400
1399 1401 Parameters
1400 1402 ----------
1401 1403 wait : bool [default: false]
1402 1404 Wait to clear the output until new output is available to replace it."""
1403 1405 from IPython.core.interactiveshell import InteractiveShell
1404 1406 if InteractiveShell.initialized():
1405 1407 InteractiveShell.instance().display_pub.clear_output(wait)
1406 1408 else:
1407 1409 print('\033[2K\r', end='')
1408 1410 sys.stdout.flush()
1409 1411 print('\033[2K\r', end='')
1410 1412 sys.stderr.flush()
1411 1413
1412 1414
1413 1415 @skip_doctest
1414 1416 def set_matplotlib_formats(*formats, **kwargs):
1415 1417 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1416 1418
1417 1419 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1418 1420
1419 1421 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1420 1422
1421 1423 To set this in your config files use the following::
1422 1424
1423 1425 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1424 1426 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1425 1427
1426 1428 Parameters
1427 1429 ----------
1428 1430 *formats : strs
1429 1431 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1430 1432 **kwargs :
1431 1433 Keyword args will be relayed to ``figure.canvas.print_figure``.
1432 1434 """
1433 1435 from IPython.core.interactiveshell import InteractiveShell
1434 1436 from IPython.core.pylabtools import select_figure_formats
1435 1437 # build kwargs, starting with InlineBackend config
1436 1438 kw = {}
1437 1439 from ipykernel.pylab.config import InlineBackend
1438 1440 cfg = InlineBackend.instance()
1439 1441 kw.update(cfg.print_figure_kwargs)
1440 1442 kw.update(**kwargs)
1441 1443 shell = InteractiveShell.instance()
1442 1444 select_figure_formats(shell, formats, **kw)
1443 1445
1444 1446 @skip_doctest
1445 1447 def set_matplotlib_close(close=True):
1446 1448 """Set whether the inline backend closes all figures automatically or not.
1447 1449
1448 1450 By default, the inline backend used in the IPython Notebook will close all
1449 1451 matplotlib figures automatically after each cell is run. This means that
1450 1452 plots in different cells won't interfere. Sometimes, you may want to make
1451 1453 a plot in one cell and then refine it in later cells. This can be accomplished
1452 1454 by::
1453 1455
1454 1456 In [1]: set_matplotlib_close(False)
1455 1457
1456 1458 To set this in your config files use the following::
1457 1459
1458 1460 c.InlineBackend.close_figures = False
1459 1461
1460 1462 Parameters
1461 1463 ----------
1462 1464 close : bool
1463 1465 Should all matplotlib figures be automatically closed after each cell is
1464 1466 run?
1465 1467 """
1466 1468 from ipykernel.pylab.config import InlineBackend
1467 1469 cfg = InlineBackend.instance()
1468 1470 cfg.close_figures = close
General Comments 0
You need to be logged in to leave comments. Login now