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