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