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