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