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