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