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