##// END OF EJS Templates
further clarify Image docstring
MinRK -
Show More
@@ -1,626 +1,635 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
24 24 from IPython.utils.py3compat import string_types
25 25
26 26 from .displaypub import publish_display_data
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 def display(*objs, **kwargs):
79 79 """Display a Python object in all frontends.
80 80
81 81 By default all representations will be computed and sent to the frontends.
82 82 Frontends can decide which representation is used and how.
83 83
84 84 Parameters
85 85 ----------
86 86 objs : tuple of objects
87 87 The Python objects to display.
88 88 raw : bool, optional
89 89 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
90 90 or Python objects that need to be formatted before display? [default: False]
91 91 include : list or tuple, optional
92 92 A list of format type strings (MIME types) to include in the
93 93 format data dict. If this is set *only* the format types included
94 94 in this list will be computed.
95 95 exclude : list or tuple, optional
96 96 A list of format type strings (MIME types) to exclude in the format
97 97 data dict. If this is set all format types will be computed,
98 98 except for those included in this argument.
99 99 metadata : dict, optional
100 100 A dictionary of metadata to associate with the output.
101 101 mime-type keys in this dictionary will be associated with the individual
102 102 representation formats, if they exist.
103 103 """
104 104 raw = kwargs.get('raw', False)
105 105 include = kwargs.get('include')
106 106 exclude = kwargs.get('exclude')
107 107 metadata = kwargs.get('metadata')
108 108
109 109 from IPython.core.interactiveshell import InteractiveShell
110 110
111 111 if raw:
112 112 for obj in objs:
113 113 publish_display_data('display', obj, metadata)
114 114 else:
115 115 format = InteractiveShell.instance().display_formatter.format
116 116 for obj in objs:
117 117 format_dict, md_dict = format(obj, include=include, exclude=exclude)
118 118 if metadata:
119 119 # kwarg-specified metadata gets precedence
120 120 _merge(md_dict, metadata)
121 121 publish_display_data('display', format_dict, md_dict)
122 122
123 123
124 124 def display_pretty(*objs, **kwargs):
125 125 """Display the pretty (default) representation of an object.
126 126
127 127 Parameters
128 128 ----------
129 129 objs : tuple of objects
130 130 The Python objects to display, or if raw=True raw text data to
131 131 display.
132 132 raw : bool
133 133 Are the data objects raw data or Python objects that need to be
134 134 formatted before display? [default: False]
135 135 metadata : dict (optional)
136 136 Metadata to be associated with the specific mimetype output.
137 137 """
138 138 _display_mimetype('text/plain', objs, **kwargs)
139 139
140 140
141 141 def display_html(*objs, **kwargs):
142 142 """Display the HTML representation of an object.
143 143
144 144 Parameters
145 145 ----------
146 146 objs : tuple of objects
147 147 The Python objects to display, or if raw=True raw HTML data to
148 148 display.
149 149 raw : bool
150 150 Are the data objects raw data or Python objects that need to be
151 151 formatted before display? [default: False]
152 152 metadata : dict (optional)
153 153 Metadata to be associated with the specific mimetype output.
154 154 """
155 155 _display_mimetype('text/html', objs, **kwargs)
156 156
157 157
158 158 def display_svg(*objs, **kwargs):
159 159 """Display the SVG representation of an object.
160 160
161 161 Parameters
162 162 ----------
163 163 objs : tuple of objects
164 164 The Python objects to display, or if raw=True raw svg data to
165 165 display.
166 166 raw : bool
167 167 Are the data objects raw data or Python objects that need to be
168 168 formatted before display? [default: False]
169 169 metadata : dict (optional)
170 170 Metadata to be associated with the specific mimetype output.
171 171 """
172 172 _display_mimetype('image/svg+xml', objs, **kwargs)
173 173
174 174
175 175 def display_png(*objs, **kwargs):
176 176 """Display the PNG representation of an object.
177 177
178 178 Parameters
179 179 ----------
180 180 objs : tuple of objects
181 181 The Python objects to display, or if raw=True raw png data to
182 182 display.
183 183 raw : bool
184 184 Are the data objects raw data or Python objects that need to be
185 185 formatted before display? [default: False]
186 186 metadata : dict (optional)
187 187 Metadata to be associated with the specific mimetype output.
188 188 """
189 189 _display_mimetype('image/png', objs, **kwargs)
190 190
191 191
192 192 def display_jpeg(*objs, **kwargs):
193 193 """Display the JPEG representation of an object.
194 194
195 195 Parameters
196 196 ----------
197 197 objs : tuple of objects
198 198 The Python objects to display, or if raw=True raw JPEG data to
199 199 display.
200 200 raw : bool
201 201 Are the data objects raw data or Python objects that need to be
202 202 formatted before display? [default: False]
203 203 metadata : dict (optional)
204 204 Metadata to be associated with the specific mimetype output.
205 205 """
206 206 _display_mimetype('image/jpeg', objs, **kwargs)
207 207
208 208
209 209 def display_latex(*objs, **kwargs):
210 210 """Display the LaTeX representation of an object.
211 211
212 212 Parameters
213 213 ----------
214 214 objs : tuple of objects
215 215 The Python objects to display, or if raw=True raw latex data to
216 216 display.
217 217 raw : bool
218 218 Are the data objects raw data or Python objects that need to be
219 219 formatted before display? [default: False]
220 220 metadata : dict (optional)
221 221 Metadata to be associated with the specific mimetype output.
222 222 """
223 223 _display_mimetype('text/latex', objs, **kwargs)
224 224
225 225
226 226 def display_json(*objs, **kwargs):
227 227 """Display the JSON representation of an object.
228 228
229 229 Note that not many frontends support displaying JSON.
230 230
231 231 Parameters
232 232 ----------
233 233 objs : tuple of objects
234 234 The Python objects to display, or if raw=True raw json data to
235 235 display.
236 236 raw : bool
237 237 Are the data objects raw data or Python objects that need to be
238 238 formatted before display? [default: False]
239 239 metadata : dict (optional)
240 240 Metadata to be associated with the specific mimetype output.
241 241 """
242 242 _display_mimetype('application/json', objs, **kwargs)
243 243
244 244
245 245 def display_javascript(*objs, **kwargs):
246 246 """Display the Javascript representation of an object.
247 247
248 248 Parameters
249 249 ----------
250 250 objs : tuple of objects
251 251 The Python objects to display, or if raw=True raw javascript data to
252 252 display.
253 253 raw : bool
254 254 Are the data objects raw data or Python objects that need to be
255 255 formatted before display? [default: False]
256 256 metadata : dict (optional)
257 257 Metadata to be associated with the specific mimetype output.
258 258 """
259 259 _display_mimetype('application/javascript', objs, **kwargs)
260 260
261 261 #-----------------------------------------------------------------------------
262 262 # Smart classes
263 263 #-----------------------------------------------------------------------------
264 264
265 265
266 266 class DisplayObject(object):
267 267 """An object that wraps data to be displayed."""
268 268
269 269 _read_flags = 'r'
270 270
271 271 def __init__(self, data=None, url=None, filename=None):
272 272 """Create a display object given raw data.
273 273
274 274 When this object is returned by an expression or passed to the
275 275 display function, it will result in the data being displayed
276 276 in the frontend. The MIME type of the data should match the
277 277 subclasses used, so the Png subclass should be used for 'image/png'
278 278 data. If the data is a URL, the data will first be downloaded
279 279 and then displayed. If
280 280
281 281 Parameters
282 282 ----------
283 283 data : unicode, str or bytes
284 284 The raw data or a URL or file to load the data from
285 285 url : unicode
286 286 A URL to download the data from.
287 287 filename : unicode
288 288 Path to a local file to load the data from.
289 289 """
290 290 if data is not None and isinstance(data, string_types):
291 291 if data.startswith('http') and url is None:
292 292 url = data
293 293 filename = None
294 294 data = None
295 295 elif _safe_exists(data) and filename is None:
296 296 url = None
297 297 filename = data
298 298 data = None
299 299
300 300 self.data = data
301 301 self.url = url
302 302 self.filename = None if filename is None else unicode(filename)
303 303
304 304 self.reload()
305 305
306 306 def reload(self):
307 307 """Reload the raw data from file or URL."""
308 308 if self.filename is not None:
309 309 with open(self.filename, self._read_flags) as f:
310 310 self.data = f.read()
311 311 elif self.url is not None:
312 312 try:
313 313 import urllib2
314 314 response = urllib2.urlopen(self.url)
315 315 self.data = response.read()
316 316 # extract encoding from header, if there is one:
317 317 encoding = None
318 318 for sub in response.headers['content-type'].split(';'):
319 319 sub = sub.strip()
320 320 if sub.startswith('charset'):
321 321 encoding = sub.split('=')[-1].strip()
322 322 break
323 323 # decode data, if an encoding was specified
324 324 if encoding:
325 325 self.data = self.data.decode(encoding, 'replace')
326 326 except:
327 327 self.data = None
328 328
329 329 class Pretty(DisplayObject):
330 330
331 331 def _repr_pretty_(self):
332 332 return self.data
333 333
334 334
335 335 class HTML(DisplayObject):
336 336
337 337 def _repr_html_(self):
338 338 return self.data
339 339
340 340 def __html__(self):
341 341 """
342 342 This method exists to inform other HTML-using modules (e.g. Markupsafe,
343 343 htmltag, etc) that this object is HTML and does not need things like
344 344 special characters (<>&) escaped.
345 345 """
346 346 return self._repr_html_()
347 347
348 348
349 349 class Math(DisplayObject):
350 350
351 351 def _repr_latex_(self):
352 352 s = self.data.strip('$')
353 353 return "$$%s$$" % s
354 354
355 355
356 356 class Latex(DisplayObject):
357 357
358 358 def _repr_latex_(self):
359 359 return self.data
360 360
361 361
362 362 class SVG(DisplayObject):
363 363
364 364 # wrap data in a property, which extracts the <svg> tag, discarding
365 365 # document headers
366 366 _data = None
367 367
368 368 @property
369 369 def data(self):
370 370 return self._data
371 371
372 372 @data.setter
373 373 def data(self, svg):
374 374 if svg is None:
375 375 self._data = None
376 376 return
377 377 # parse into dom object
378 378 from xml.dom import minidom
379 379 x = minidom.parseString(svg)
380 380 # get svg tag (should be 1)
381 381 found_svg = x.getElementsByTagName('svg')
382 382 if found_svg:
383 383 svg = found_svg[0].toxml()
384 384 else:
385 385 # fallback on the input, trust the user
386 386 # but this is probably an error.
387 387 pass
388 388 self._data = svg
389 389
390 390 def _repr_svg_(self):
391 391 return self.data
392 392
393 393
394 394 class JSON(DisplayObject):
395 395
396 396 def _repr_json_(self):
397 397 return self.data
398 398
399 399 css_t = """$("head").append($("<link/>").attr({
400 400 rel: "stylesheet",
401 401 type: "text/css",
402 402 href: "%s"
403 403 }));
404 404 """
405 405
406 406 lib_t1 = """$.getScript("%s", function () {
407 407 """
408 408 lib_t2 = """});
409 409 """
410 410
411 411 class Javascript(DisplayObject):
412 412
413 413 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
414 414 """Create a Javascript display object given raw data.
415 415
416 416 When this object is returned by an expression or passed to the
417 417 display function, it will result in the data being displayed
418 418 in the frontend. If the data is a URL, the data will first be
419 419 downloaded and then displayed.
420 420
421 421 In the Notebook, the containing element will be available as `element`,
422 422 and jQuery will be available. The output area starts hidden, so if
423 423 the js appends content to `element` that should be visible, then
424 424 it must call `container.show()` to unhide the area.
425 425
426 426 Parameters
427 427 ----------
428 428 data : unicode, str or bytes
429 429 The Javascript source code or a URL to download it from.
430 430 url : unicode
431 431 A URL to download the data from.
432 432 filename : unicode
433 433 Path to a local file to load the data from.
434 434 lib : list or str
435 435 A sequence of Javascript library URLs to load asynchronously before
436 436 running the source code. The full URLs of the libraries should
437 437 be given. A single Javascript library URL can also be given as a
438 438 string.
439 439 css: : list or str
440 440 A sequence of css files to load before running the source code.
441 441 The full URLs of the css files should be given. A single css URL
442 442 can also be given as a string.
443 443 """
444 444 if isinstance(lib, basestring):
445 445 lib = [lib]
446 446 elif lib is None:
447 447 lib = []
448 448 if isinstance(css, basestring):
449 449 css = [css]
450 450 elif css is None:
451 451 css = []
452 452 if not isinstance(lib, (list,tuple)):
453 453 raise TypeError('expected sequence, got: %r' % lib)
454 454 if not isinstance(css, (list,tuple)):
455 455 raise TypeError('expected sequence, got: %r' % css)
456 456 self.lib = lib
457 457 self.css = css
458 458 super(Javascript, self).__init__(data=data, url=url, filename=filename)
459 459
460 460 def _repr_javascript_(self):
461 461 r = ''
462 462 for c in self.css:
463 463 r += css_t % c
464 464 for l in self.lib:
465 465 r += lib_t1 % l
466 466 r += self.data
467 467 r += lib_t2*len(self.lib)
468 468 return r
469 469
470 470 # constants for identifying png/jpeg data
471 471 _PNG = b'\x89PNG\r\n\x1a\n'
472 472 _JPEG = b'\xff\xd8'
473 473
474 474 class Image(DisplayObject):
475 475
476 476 _read_flags = 'rb'
477 477 _FMT_JPEG = u'jpeg'
478 478 _FMT_PNG = u'png'
479 479 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
480 480
481 481 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None):
482 482 """Create a display an PNG/JPEG image given raw data.
483 483
484 484 When this object is returned by an expression or passed to the
485 485 display function, it will result in the image being displayed
486 486 in the frontend.
487 487
488 488 Parameters
489 489 ----------
490 490 data : unicode, str or bytes
491 The raw data or a URL to download the data from.
491 The raw image data or a URL or filename to load the data from.
492 This always results in embedded image data.
492 493 url : unicode
493 A URL to download the data from.
494 A URL to download the data from. If you specify `url=`,
495 the image data will not be embedded unless you also specify `embed=True`.
494 496 filename : unicode
495 497 Path to a local file to load the data from.
498 Images from a file are always embedded.
496 499 format : unicode
497 500 The format of the image data (png/jpeg/jpg). If a filename or URL is given
498 501 for format will be inferred from the filename extension.
499 502 embed : bool
500 503 Should the image data be embedded using a data URI (True) or be
501 504 loaded using an <img> tag. Set this to True if you want the image
502 505 to be viewable later with no internet connection in the notebook.
503 506
504 507 Default is `True`, unless the keyword argument `url` is set, then
505 508 default value is `False`.
506 509
507 510 Note that QtConsole is not able to display images if `embed` is set to `False`
508 511 width : int
509 512 Width to which to constrain the image in html
510 513 height : int
511 514 Height to which to constrain the image in html
512 515
513 516 Examples
514 517 --------
515 # embed implicitly True, works in qtconsole and notebook
518 # embedded image data, works in qtconsole and notebook
519 # when passed positionally, the first arg can be any of raw image data,
520 # a URL, or a filename from which to load image data.
521 # The result is always embedding image data for inline images.
516 522 Image('http://www.google.fr/images/srpr/logo3w.png')
523 Image('/path/to/image.jpg')
524 Image(b'RAW_PNG_DATA...')
517 525
518 # embed implicitly False, does not works in qtconsole but works in notebook if
519 # internet connection available
526 # Specifying Image(url=...) does not embed the image data,
527 # it only generates `<img>` tag with a link to the source.
528 # This will not work in the qtconsole or offline.
520 529 Image(url='http://www.google.fr/images/srpr/logo3w.png')
521 530
522 531 """
523 532 if filename is not None:
524 533 ext = self._find_ext(filename)
525 534 elif url is not None:
526 535 ext = self._find_ext(url)
527 536 elif data is None:
528 537 raise ValueError("No image data found. Expecting filename, url, or data.")
529 538 elif isinstance(data, string_types) and (
530 539 data.startswith('http') or _safe_exists(data)
531 540 ):
532 541 ext = self._find_ext(data)
533 542 else:
534 543 ext = None
535 544
536 545 if ext is not None:
537 546 format = ext.lower()
538 547 if ext == u'jpg' or ext == u'jpeg':
539 548 format = self._FMT_JPEG
540 549 if ext == u'png':
541 550 format = self._FMT_PNG
542 551 elif isinstance(data, bytes) and format == 'png':
543 552 # infer image type from image data header,
544 553 # only if format might not have been specified.
545 554 if data[:2] == _JPEG:
546 555 format = 'jpeg'
547 556
548 557 self.format = unicode(format).lower()
549 558 self.embed = embed if embed is not None else (url is None)
550 559
551 560 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
552 561 raise ValueError("Cannot embed the '%s' image format" % (self.format))
553 562 self.width = width
554 563 self.height = height
555 564 super(Image, self).__init__(data=data, url=url, filename=filename)
556 565
557 566 def reload(self):
558 567 """Reload the raw data from file or URL."""
559 568 if self.embed:
560 569 super(Image,self).reload()
561 570
562 571 def _repr_html_(self):
563 572 if not self.embed:
564 573 width = height = ''
565 574 if self.width:
566 575 width = ' width="%d"' % self.width
567 576 if self.height:
568 577 height = ' height="%d"' % self.height
569 578 return u'<img src="%s"%s%s/>' % (self.url, width, height)
570 579
571 580 def _data_and_metadata(self):
572 581 """shortcut for returning metadata with shape information, if defined"""
573 582 md = {}
574 583 if self.width:
575 584 md['width'] = self.width
576 585 if self.height:
577 586 md['height'] = self.height
578 587 if md:
579 588 return self.data, md
580 589 else:
581 590 return self.data
582 591
583 592 def _repr_png_(self):
584 593 if self.embed and self.format == u'png':
585 594 return self._data_and_metadata()
586 595
587 596 def _repr_jpeg_(self):
588 597 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
589 598 return self._data_and_metadata()
590 599
591 600 def _find_ext(self, s):
592 601 return unicode(s.split('.')[-1].lower())
593 602
594 603
595 604 def clear_output(stdout=True, stderr=True, other=True):
596 605 """Clear the output of the current cell receiving output.
597 606
598 607 Optionally, each of stdout/stderr or other non-stream data (e.g. anything
599 608 produced by display()) can be excluded from the clear event.
600 609
601 610 By default, everything is cleared.
602 611
603 612 Parameters
604 613 ----------
605 614 stdout : bool [default: True]
606 615 Whether to clear stdout.
607 616 stderr : bool [default: True]
608 617 Whether to clear stderr.
609 618 other : bool [default: True]
610 619 Whether to clear everything else that is not stdout/stderr
611 620 (e.g. figures,images,HTML, any result of display()).
612 621 """
613 622 from IPython.core.interactiveshell import InteractiveShell
614 623 if InteractiveShell.initialized():
615 624 InteractiveShell.instance().display_pub.clear_output(
616 625 stdout=stdout, stderr=stderr, other=other,
617 626 )
618 627 else:
619 628 from IPython.utils import io
620 629 if stdout:
621 630 print('\033[2K\r', file=io.stdout, end='')
622 631 io.stdout.flush()
623 632 if stderr:
624 633 print('\033[2K\r', file=io.stderr, end='')
625 634 io.stderr.flush()
626 635
General Comments 0
You need to be logged in to leave comments. Login now