##// END OF EJS Templates
Add 'rb' flags while reading SVG file
Srinivas Reddy Thatiparthy -
Show More
@@ -1,1135 +1,1136 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Top-level display functions for displaying object in different formats."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 try:
9 9 from base64 import encodebytes as base64_encode
10 10 except ImportError:
11 11 from base64 import encodestring as base64_encode
12 12
13 13 from binascii import b2a_hex
14 14 import json
15 15 import mimetypes
16 16 import os
17 17 import struct
18 18 import sys
19 19 import warnings
20 20
21 21 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
22 22 unicode_type)
23 23 from IPython.testing.skipdoctest import skip_doctest
24 24
25 25 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
26 26 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
27 27 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
28 28 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
29 29 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
30 30 'publish_display_data', 'update_display', 'DisplayHandle']
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # utility functions
34 34 #-----------------------------------------------------------------------------
35 35
36 36 def _safe_exists(path):
37 37 """Check path, but don't let exceptions raise"""
38 38 try:
39 39 return os.path.exists(path)
40 40 except Exception:
41 41 return False
42 42
43 43 def _merge(d1, d2):
44 44 """Like update, but merges sub-dicts instead of clobbering at the top level.
45 45
46 46 Updates d1 in-place
47 47 """
48 48
49 49 if not isinstance(d2, dict) or not isinstance(d1, dict):
50 50 return d2
51 51 for key, value in d2.items():
52 52 d1[key] = _merge(d1.get(key), value)
53 53 return d1
54 54
55 55 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
56 56 """internal implementation of all display_foo methods
57 57
58 58 Parameters
59 59 ----------
60 60 mimetype : str
61 61 The mimetype to be published (e.g. 'image/png')
62 62 objs : tuple of objects
63 63 The Python objects to display, or if raw=True raw text data to
64 64 display.
65 65 raw : bool
66 66 Are the data objects raw data or Python objects that need to be
67 67 formatted before display? [default: False]
68 68 metadata : dict (optional)
69 69 Metadata to be associated with the specific mimetype output.
70 70 """
71 71 if metadata:
72 72 metadata = {mimetype: metadata}
73 73 if raw:
74 74 # turn list of pngdata into list of { 'image/png': pngdata }
75 75 objs = [ {mimetype: obj} for obj in objs ]
76 76 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
77 77
78 78 #-----------------------------------------------------------------------------
79 79 # Main functions
80 80 #-----------------------------------------------------------------------------
81 81
82 82 # use * to indicate transient is keyword-only
83 83 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
84 84 """Publish data and metadata to all frontends.
85 85
86 86 See the ``display_data`` message in the messaging documentation for
87 87 more details about this message type.
88 88
89 89 The following MIME types are currently implemented:
90 90
91 91 * text/plain
92 92 * text/html
93 93 * text/markdown
94 94 * text/latex
95 95 * application/json
96 96 * application/javascript
97 97 * image/png
98 98 * image/jpeg
99 99 * image/svg+xml
100 100
101 101 Parameters
102 102 ----------
103 103 data : dict
104 104 A dictionary having keys that are valid MIME types (like
105 105 'text/plain' or 'image/svg+xml') and values that are the data for
106 106 that MIME type. The data itself must be a JSON'able data
107 107 structure. Minimally all data should have the 'text/plain' data,
108 108 which can be displayed by all frontends. If more than the plain
109 109 text is given, it is up to the frontend to decide which
110 110 representation to use.
111 111 metadata : dict
112 112 A dictionary for metadata related to the data. This can contain
113 113 arbitrary key, value pairs that frontends can use to interpret
114 114 the data. mime-type keys matching those in data can be used
115 115 to specify metadata about particular representations.
116 116 source : str, deprecated
117 117 Unused.
118 118 transient : dict, keyword-only
119 119 A dictionary of transient data, such as display_id.
120 120 """
121 121 from IPython.core.interactiveshell import InteractiveShell
122 122
123 123 display_pub = InteractiveShell.instance().display_pub
124 124
125 125 # only pass transient if supplied,
126 126 # to avoid errors with older ipykernel.
127 127 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
128 128 if transient:
129 129 kwargs['transient'] = transient
130 130
131 131 display_pub.publish(
132 132 data=data,
133 133 metadata=metadata,
134 134 **kwargs
135 135 )
136 136
137 137
138 138 def _new_id():
139 139 """Generate a new random text id with urandom"""
140 140 return b2a_hex(os.urandom(16)).decode('ascii')
141 141
142 142
143 143 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
144 144 """Display a Python object in all frontends.
145 145
146 146 By default all representations will be computed and sent to the frontends.
147 147 Frontends can decide which representation is used and how.
148 148
149 149 Parameters
150 150 ----------
151 151 objs : tuple of objects
152 152 The Python objects to display.
153 153 raw : bool, optional
154 154 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
155 155 or Python objects that need to be formatted before display? [default: False]
156 156 include : list or tuple, optional
157 157 A list of format type strings (MIME types) to include in the
158 158 format data dict. If this is set *only* the format types included
159 159 in this list will be computed.
160 160 exclude : list or tuple, optional
161 161 A list of format type strings (MIME types) to exclude in the format
162 162 data dict. If this is set all format types will be computed,
163 163 except for those included in this argument.
164 164 metadata : dict, optional
165 165 A dictionary of metadata to associate with the output.
166 166 mime-type keys in this dictionary will be associated with the individual
167 167 representation formats, if they exist.
168 168 transient : dict, optional
169 169 A dictionary of transient data to associate with the output.
170 170 Data in this dict should not be persisted to files (e.g. notebooks).
171 171 display_id : str, optional
172 172 Set an id for the display.
173 173 This id can be used for updating this display area later via update_display.
174 174 If given as True, generate a new display_id
175 175 kwargs: additional keyword-args, optional
176 176 Additional keyword-arguments are passed through to the display publisher.
177 177
178 178 Returns
179 179 -------
180 180
181 181 handle: DisplayHandle
182 182 Returns a handle on updatable displays, if display_id is given.
183 183 Returns None if no display_id is given (default).
184 184 """
185 185 raw = kwargs.pop('raw', False)
186 186 if transient is None:
187 187 transient = {}
188 188 if display_id:
189 189 if display_id == True:
190 190 display_id = _new_id()
191 191 transient['display_id'] = display_id
192 192 if kwargs.get('update') and 'display_id' not in transient:
193 193 raise TypeError('display_id required for update_display')
194 194 if transient:
195 195 kwargs['transient'] = transient
196 196
197 197 from IPython.core.interactiveshell import InteractiveShell
198 198
199 199 if not raw:
200 200 format = InteractiveShell.instance().display_formatter.format
201 201
202 202 for obj in objs:
203 203 if raw:
204 204 publish_display_data(data=obj, metadata=metadata, **kwargs)
205 205 else:
206 206 format_dict, md_dict = format(obj, include=include, exclude=exclude)
207 207 if not format_dict:
208 208 # nothing to display (e.g. _ipython_display_ took over)
209 209 continue
210 210 if metadata:
211 211 # kwarg-specified metadata gets precedence
212 212 _merge(md_dict, metadata)
213 213 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
214 214 if display_id:
215 215 return DisplayHandle(display_id)
216 216
217 217
218 218 # use * for keyword-only display_id arg
219 219 def update_display(obj, *, display_id, **kwargs):
220 220 """Update an existing display by id
221 221
222 222 Parameters
223 223 ----------
224 224
225 225 obj:
226 226 The object with which to update the display
227 227 display_id: keyword-only
228 228 The id of the display to update
229 229 """
230 230 kwargs['update'] = True
231 231 display(obj, display_id=display_id, **kwargs)
232 232
233 233
234 234 class DisplayHandle(object):
235 235 """A handle on an updatable display
236 236
237 237 Call .update(obj) to display a new object.
238 238
239 239 Call .display(obj) to add a new instance of this display,
240 240 and update existing instances.
241 241 """
242 242
243 243 def __init__(self, display_id=None):
244 244 if display_id is None:
245 245 display_id = _new_id()
246 246 self.display_id = display_id
247 247
248 248 def __repr__(self):
249 249 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
250 250
251 251 def display(self, obj, **kwargs):
252 252 """Make a new display with my id, updating existing instances.
253 253
254 254 Parameters
255 255 ----------
256 256
257 257 obj:
258 258 object to display
259 259 **kwargs:
260 260 additional keyword arguments passed to display
261 261 """
262 262 display(obj, display_id=self.display_id, **kwargs)
263 263
264 264 def update(self, obj, **kwargs):
265 265 """Update existing displays with my id
266 266
267 267 Parameters
268 268 ----------
269 269
270 270 obj:
271 271 object to display
272 272 **kwargs:
273 273 additional keyword arguments passed to update_display
274 274 """
275 275 update_display(obj, display_id=self.display_id, **kwargs)
276 276
277 277
278 278 def display_pretty(*objs, **kwargs):
279 279 """Display the pretty (default) representation of an object.
280 280
281 281 Parameters
282 282 ----------
283 283 objs : tuple of objects
284 284 The Python objects to display, or if raw=True raw text data to
285 285 display.
286 286 raw : bool
287 287 Are the data objects raw data or Python objects that need to be
288 288 formatted before display? [default: False]
289 289 metadata : dict (optional)
290 290 Metadata to be associated with the specific mimetype output.
291 291 """
292 292 _display_mimetype('text/plain', objs, **kwargs)
293 293
294 294
295 295 def display_html(*objs, **kwargs):
296 296 """Display the HTML representation of an object.
297 297
298 298 Note: If raw=False and the object does not have a HTML
299 299 representation, no HTML will be shown.
300 300
301 301 Parameters
302 302 ----------
303 303 objs : tuple of objects
304 304 The Python objects to display, or if raw=True raw HTML data to
305 305 display.
306 306 raw : bool
307 307 Are the data objects raw data or Python objects that need to be
308 308 formatted before display? [default: False]
309 309 metadata : dict (optional)
310 310 Metadata to be associated with the specific mimetype output.
311 311 """
312 312 _display_mimetype('text/html', objs, **kwargs)
313 313
314 314
315 315 def display_markdown(*objs, **kwargs):
316 316 """Displays the Markdown representation of an object.
317 317
318 318 Parameters
319 319 ----------
320 320 objs : tuple of objects
321 321 The Python objects to display, or if raw=True raw markdown data to
322 322 display.
323 323 raw : bool
324 324 Are the data objects raw data or Python objects that need to be
325 325 formatted before display? [default: False]
326 326 metadata : dict (optional)
327 327 Metadata to be associated with the specific mimetype output.
328 328 """
329 329
330 330 _display_mimetype('text/markdown', objs, **kwargs)
331 331
332 332
333 333 def display_svg(*objs, **kwargs):
334 334 """Display the SVG representation of an object.
335 335
336 336 Parameters
337 337 ----------
338 338 objs : tuple of objects
339 339 The Python objects to display, or if raw=True raw svg data to
340 340 display.
341 341 raw : bool
342 342 Are the data objects raw data or Python objects that need to be
343 343 formatted before display? [default: False]
344 344 metadata : dict (optional)
345 345 Metadata to be associated with the specific mimetype output.
346 346 """
347 347 _display_mimetype('image/svg+xml', objs, **kwargs)
348 348
349 349
350 350 def display_png(*objs, **kwargs):
351 351 """Display the PNG representation of an object.
352 352
353 353 Parameters
354 354 ----------
355 355 objs : tuple of objects
356 356 The Python objects to display, or if raw=True raw png data to
357 357 display.
358 358 raw : bool
359 359 Are the data objects raw data or Python objects that need to be
360 360 formatted before display? [default: False]
361 361 metadata : dict (optional)
362 362 Metadata to be associated with the specific mimetype output.
363 363 """
364 364 _display_mimetype('image/png', objs, **kwargs)
365 365
366 366
367 367 def display_jpeg(*objs, **kwargs):
368 368 """Display the JPEG representation of an object.
369 369
370 370 Parameters
371 371 ----------
372 372 objs : tuple of objects
373 373 The Python objects to display, or if raw=True raw JPEG data to
374 374 display.
375 375 raw : bool
376 376 Are the data objects raw data or Python objects that need to be
377 377 formatted before display? [default: False]
378 378 metadata : dict (optional)
379 379 Metadata to be associated with the specific mimetype output.
380 380 """
381 381 _display_mimetype('image/jpeg', objs, **kwargs)
382 382
383 383
384 384 def display_latex(*objs, **kwargs):
385 385 """Display the LaTeX representation of an object.
386 386
387 387 Parameters
388 388 ----------
389 389 objs : tuple of objects
390 390 The Python objects to display, or if raw=True raw latex data to
391 391 display.
392 392 raw : bool
393 393 Are the data objects raw data or Python objects that need to be
394 394 formatted before display? [default: False]
395 395 metadata : dict (optional)
396 396 Metadata to be associated with the specific mimetype output.
397 397 """
398 398 _display_mimetype('text/latex', objs, **kwargs)
399 399
400 400
401 401 def display_json(*objs, **kwargs):
402 402 """Display the JSON representation of an object.
403 403
404 404 Note that not many frontends support displaying JSON.
405 405
406 406 Parameters
407 407 ----------
408 408 objs : tuple of objects
409 409 The Python objects to display, or if raw=True raw json data to
410 410 display.
411 411 raw : bool
412 412 Are the data objects raw data or Python objects that need to be
413 413 formatted before display? [default: False]
414 414 metadata : dict (optional)
415 415 Metadata to be associated with the specific mimetype output.
416 416 """
417 417 _display_mimetype('application/json', objs, **kwargs)
418 418
419 419
420 420 def display_javascript(*objs, **kwargs):
421 421 """Display the Javascript representation of an object.
422 422
423 423 Parameters
424 424 ----------
425 425 objs : tuple of objects
426 426 The Python objects to display, or if raw=True raw javascript data to
427 427 display.
428 428 raw : bool
429 429 Are the data objects raw data or Python objects that need to be
430 430 formatted before display? [default: False]
431 431 metadata : dict (optional)
432 432 Metadata to be associated with the specific mimetype output.
433 433 """
434 434 _display_mimetype('application/javascript', objs, **kwargs)
435 435
436 436
437 437 def display_pdf(*objs, **kwargs):
438 438 """Display the PDF representation of an object.
439 439
440 440 Parameters
441 441 ----------
442 442 objs : tuple of objects
443 443 The Python objects to display, or if raw=True raw javascript data to
444 444 display.
445 445 raw : bool
446 446 Are the data objects raw data or Python objects that need to be
447 447 formatted before display? [default: False]
448 448 metadata : dict (optional)
449 449 Metadata to be associated with the specific mimetype output.
450 450 """
451 451 _display_mimetype('application/pdf', objs, **kwargs)
452 452
453 453
454 454 #-----------------------------------------------------------------------------
455 455 # Smart classes
456 456 #-----------------------------------------------------------------------------
457 457
458 458
459 459 class DisplayObject(object):
460 460 """An object that wraps data to be displayed."""
461 461
462 462 _read_flags = 'r'
463 463 _show_mem_addr = False
464 464
465 465 def __init__(self, data=None, url=None, filename=None):
466 466 """Create a display object given raw data.
467 467
468 468 When this object is returned by an expression or passed to the
469 469 display function, it will result in the data being displayed
470 470 in the frontend. The MIME type of the data should match the
471 471 subclasses used, so the Png subclass should be used for 'image/png'
472 472 data. If the data is a URL, the data will first be downloaded
473 473 and then displayed. If
474 474
475 475 Parameters
476 476 ----------
477 477 data : unicode, str or bytes
478 478 The raw data or a URL or file to load the data from
479 479 url : unicode
480 480 A URL to download the data from.
481 481 filename : unicode
482 482 Path to a local file to load the data from.
483 483 """
484 484 if data is not None and isinstance(data, string_types):
485 485 if data.startswith('http') and url is None:
486 486 url = data
487 487 filename = None
488 488 data = None
489 489 elif _safe_exists(data) and filename is None:
490 490 url = None
491 491 filename = data
492 492 data = None
493 493
494 494 self.data = data
495 495 self.url = url
496 496 self.filename = None if filename is None else unicode_type(filename)
497 497
498 498 self.reload()
499 499 self._check_data()
500 500
501 501 def __repr__(self):
502 502 if not self._show_mem_addr:
503 503 cls = self.__class__
504 504 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
505 505 else:
506 506 r = super(DisplayObject, self).__repr__()
507 507 return r
508 508
509 509 def _check_data(self):
510 510 """Override in subclasses if there's something to check."""
511 511 pass
512 512
513 513 def reload(self):
514 514 """Reload the raw data from file or URL."""
515 515 if self.filename is not None:
516 516 with open(self.filename, self._read_flags) as f:
517 517 self.data = f.read()
518 518 elif self.url is not None:
519 519 try:
520 520 try:
521 521 from urllib.request import urlopen # Py3
522 522 except ImportError:
523 523 from urllib2 import urlopen
524 524 response = urlopen(self.url)
525 525 self.data = response.read()
526 526 # extract encoding from header, if there is one:
527 527 encoding = None
528 528 for sub in response.headers['content-type'].split(';'):
529 529 sub = sub.strip()
530 530 if sub.startswith('charset'):
531 531 encoding = sub.split('=')[-1].strip()
532 532 break
533 533 # decode data, if an encoding was specified
534 534 if encoding:
535 535 self.data = self.data.decode(encoding, 'replace')
536 536 except:
537 537 self.data = None
538 538
539 539 class TextDisplayObject(DisplayObject):
540 540 """Validate that display data is text"""
541 541 def _check_data(self):
542 542 if self.data is not None and not isinstance(self.data, string_types):
543 543 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
544 544
545 545 class Pretty(TextDisplayObject):
546 546
547 547 def _repr_pretty_(self):
548 548 return self.data
549 549
550 550
551 551 class HTML(TextDisplayObject):
552 552
553 553 def _repr_html_(self):
554 554 return self.data
555 555
556 556 def __html__(self):
557 557 """
558 558 This method exists to inform other HTML-using modules (e.g. Markupsafe,
559 559 htmltag, etc) that this object is HTML and does not need things like
560 560 special characters (<>&) escaped.
561 561 """
562 562 return self._repr_html_()
563 563
564 564
565 565 class Markdown(TextDisplayObject):
566 566
567 567 def _repr_markdown_(self):
568 568 return self.data
569 569
570 570
571 571 class Math(TextDisplayObject):
572 572
573 573 def _repr_latex_(self):
574 574 s = self.data.strip('$')
575 575 return "$$%s$$" % s
576 576
577 577
578 578 class Latex(TextDisplayObject):
579 579
580 580 def _repr_latex_(self):
581 581 return self.data
582 582
583 583
584 584 class SVG(DisplayObject):
585 585
586 _read_flags = 'rb'
586 587 # wrap data in a property, which extracts the <svg> tag, discarding
587 588 # document headers
588 589 _data = None
589 590
590 591 @property
591 592 def data(self):
592 593 return self._data
593 594
594 595 @data.setter
595 596 def data(self, svg):
596 597 if svg is None:
597 598 self._data = None
598 599 return
599 600 # parse into dom object
600 601 from xml.dom import minidom
601 602 svg = cast_bytes_py2(svg)
602 603 x = minidom.parseString(svg)
603 604 # get svg tag (should be 1)
604 605 found_svg = x.getElementsByTagName('svg')
605 606 if found_svg:
606 607 svg = found_svg[0].toxml()
607 608 else:
608 609 # fallback on the input, trust the user
609 610 # but this is probably an error.
610 611 pass
611 612 svg = cast_unicode(svg)
612 613 self._data = svg
613 614
614 615 def _repr_svg_(self):
615 616 return self.data
616 617
617 618
618 619 class JSON(DisplayObject):
619 620 """JSON expects a JSON-able dict or list
620 621
621 622 not an already-serialized JSON string.
622 623
623 624 Scalar types (None, number, string) are not allowed, only dict or list containers.
624 625 """
625 626 # wrap data in a property, which warns about passing already-serialized JSON
626 627 _data = None
627 628 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None):
628 629 """Create a JSON display object given raw data.
629 630
630 631 Parameters
631 632 ----------
632 633 data : dict or list
633 634 JSON data to display. Not an already-serialized JSON string.
634 635 Scalar types (None, number, string) are not allowed, only dict
635 636 or list containers.
636 637 url : unicode
637 638 A URL to download the data from.
638 639 filename : unicode
639 640 Path to a local file to load the data from.
640 641 expanded : boolean
641 642 Metadata to control whether a JSON display component is expanded.
642 643 metadata: dict
643 644 Specify extra metadata to attach to the json display object.
644 645 """
645 646 self.expanded = expanded
646 647 self.metadata = metadata
647 648 super(JSON, self).__init__(data=data, url=url, filename=filename)
648 649
649 650 def _check_data(self):
650 651 if self.data is not None and not isinstance(self.data, (dict, list)):
651 652 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
652 653
653 654 @property
654 655 def data(self):
655 656 return self._data
656 657
657 658 @data.setter
658 659 def data(self, data):
659 660 if isinstance(data, string_types):
660 661 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
661 662 data = json.loads(data)
662 663 self._data = data
663 664
664 665 def _data_and_metadata(self):
665 666 md = {'expanded': self.expanded}
666 667 if self.metadata:
667 668 md.update(self.metadata)
668 669 return self.data, md
669 670
670 671 def _repr_json_(self):
671 672 return self._data_and_metadata()
672 673
673 674 css_t = """$("head").append($("<link/>").attr({
674 675 rel: "stylesheet",
675 676 type: "text/css",
676 677 href: "%s"
677 678 }));
678 679 """
679 680
680 681 lib_t1 = """$.getScript("%s", function () {
681 682 """
682 683 lib_t2 = """});
683 684 """
684 685
685 686 class Javascript(TextDisplayObject):
686 687
687 688 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
688 689 """Create a Javascript display object given raw data.
689 690
690 691 When this object is returned by an expression or passed to the
691 692 display function, it will result in the data being displayed
692 693 in the frontend. If the data is a URL, the data will first be
693 694 downloaded and then displayed.
694 695
695 696 In the Notebook, the containing element will be available as `element`,
696 697 and jQuery will be available. Content appended to `element` will be
697 698 visible in the output area.
698 699
699 700 Parameters
700 701 ----------
701 702 data : unicode, str or bytes
702 703 The Javascript source code or a URL to download it from.
703 704 url : unicode
704 705 A URL to download the data from.
705 706 filename : unicode
706 707 Path to a local file to load the data from.
707 708 lib : list or str
708 709 A sequence of Javascript library URLs to load asynchronously before
709 710 running the source code. The full URLs of the libraries should
710 711 be given. A single Javascript library URL can also be given as a
711 712 string.
712 713 css: : list or str
713 714 A sequence of css files to load before running the source code.
714 715 The full URLs of the css files should be given. A single css URL
715 716 can also be given as a string.
716 717 """
717 718 if isinstance(lib, string_types):
718 719 lib = [lib]
719 720 elif lib is None:
720 721 lib = []
721 722 if isinstance(css, string_types):
722 723 css = [css]
723 724 elif css is None:
724 725 css = []
725 726 if not isinstance(lib, (list,tuple)):
726 727 raise TypeError('expected sequence, got: %r' % lib)
727 728 if not isinstance(css, (list,tuple)):
728 729 raise TypeError('expected sequence, got: %r' % css)
729 730 self.lib = lib
730 731 self.css = css
731 732 super(Javascript, self).__init__(data=data, url=url, filename=filename)
732 733
733 734 def _repr_javascript_(self):
734 735 r = ''
735 736 for c in self.css:
736 737 r += css_t % c
737 738 for l in self.lib:
738 739 r += lib_t1 % l
739 740 r += self.data
740 741 r += lib_t2*len(self.lib)
741 742 return r
742 743
743 744 # constants for identifying png/jpeg data
744 745 _PNG = b'\x89PNG\r\n\x1a\n'
745 746 _JPEG = b'\xff\xd8'
746 747
747 748 def _pngxy(data):
748 749 """read the (width, height) from a PNG header"""
749 750 ihdr = data.index(b'IHDR')
750 751 # next 8 bytes are width/height
751 752 w4h4 = data[ihdr+4:ihdr+12]
752 753 return struct.unpack('>ii', w4h4)
753 754
754 755 def _jpegxy(data):
755 756 """read the (width, height) from a JPEG header"""
756 757 # adapted from http://www.64lines.com/jpeg-width-height
757 758
758 759 idx = 4
759 760 while True:
760 761 block_size = struct.unpack('>H', data[idx:idx+2])[0]
761 762 idx = idx + block_size
762 763 if data[idx:idx+2] == b'\xFF\xC0':
763 764 # found Start of Frame
764 765 iSOF = idx
765 766 break
766 767 else:
767 768 # read another block
768 769 idx += 2
769 770
770 771 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
771 772 return w, h
772 773
773 774 class Image(DisplayObject):
774 775
775 776 _read_flags = 'rb'
776 777 _FMT_JPEG = u'jpeg'
777 778 _FMT_PNG = u'png'
778 779 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
779 780
780 781 def __init__(self, data=None, url=None, filename=None, format=None,
781 782 embed=None, width=None, height=None, retina=False,
782 783 unconfined=False, metadata=None):
783 784 """Create a PNG/JPEG image object given raw data.
784 785
785 786 When this object is returned by an input cell or passed to the
786 787 display function, it will result in the image being displayed
787 788 in the frontend.
788 789
789 790 Parameters
790 791 ----------
791 792 data : unicode, str or bytes
792 793 The raw image data or a URL or filename to load the data from.
793 794 This always results in embedded image data.
794 795 url : unicode
795 796 A URL to download the data from. If you specify `url=`,
796 797 the image data will not be embedded unless you also specify `embed=True`.
797 798 filename : unicode
798 799 Path to a local file to load the data from.
799 800 Images from a file are always embedded.
800 801 format : unicode
801 802 The format of the image data (png/jpeg/jpg). If a filename or URL is given
802 803 for format will be inferred from the filename extension.
803 804 embed : bool
804 805 Should the image data be embedded using a data URI (True) or be
805 806 loaded using an <img> tag. Set this to True if you want the image
806 807 to be viewable later with no internet connection in the notebook.
807 808
808 809 Default is `True`, unless the keyword argument `url` is set, then
809 810 default value is `False`.
810 811
811 812 Note that QtConsole is not able to display images if `embed` is set to `False`
812 813 width : int
813 814 Width in pixels to which to constrain the image in html
814 815 height : int
815 816 Height in pixels to which to constrain the image in html
816 817 retina : bool
817 818 Automatically set the width and height to half of the measured
818 819 width and height.
819 820 This only works for embedded images because it reads the width/height
820 821 from image data.
821 822 For non-embedded images, you can just set the desired display width
822 823 and height directly.
823 824 unconfined: bool
824 825 Set unconfined=True to disable max-width confinement of the image.
825 826 metadata: dict
826 827 Specify extra metadata to attach to the image.
827 828
828 829 Examples
829 830 --------
830 831 # embedded image data, works in qtconsole and notebook
831 832 # when passed positionally, the first arg can be any of raw image data,
832 833 # a URL, or a filename from which to load image data.
833 834 # The result is always embedding image data for inline images.
834 835 Image('http://www.google.fr/images/srpr/logo3w.png')
835 836 Image('/path/to/image.jpg')
836 837 Image(b'RAW_PNG_DATA...')
837 838
838 839 # Specifying Image(url=...) does not embed the image data,
839 840 # it only generates `<img>` tag with a link to the source.
840 841 # This will not work in the qtconsole or offline.
841 842 Image(url='http://www.google.fr/images/srpr/logo3w.png')
842 843
843 844 """
844 845 if filename is not None:
845 846 ext = self._find_ext(filename)
846 847 elif url is not None:
847 848 ext = self._find_ext(url)
848 849 elif data is None:
849 850 raise ValueError("No image data found. Expecting filename, url, or data.")
850 851 elif isinstance(data, string_types) and (
851 852 data.startswith('http') or _safe_exists(data)
852 853 ):
853 854 ext = self._find_ext(data)
854 855 else:
855 856 ext = None
856 857
857 858 if format is None:
858 859 if ext is not None:
859 860 if ext == u'jpg' or ext == u'jpeg':
860 861 format = self._FMT_JPEG
861 862 if ext == u'png':
862 863 format = self._FMT_PNG
863 864 else:
864 865 format = ext.lower()
865 866 elif isinstance(data, bytes):
866 867 # infer image type from image data header,
867 868 # only if format has not been specified.
868 869 if data[:2] == _JPEG:
869 870 format = self._FMT_JPEG
870 871
871 872 # failed to detect format, default png
872 873 if format is None:
873 874 format = 'png'
874 875
875 876 if format.lower() == 'jpg':
876 877 # jpg->jpeg
877 878 format = self._FMT_JPEG
878 879
879 880 self.format = unicode_type(format).lower()
880 881 self.embed = embed if embed is not None else (url is None)
881 882
882 883 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
883 884 raise ValueError("Cannot embed the '%s' image format" % (self.format))
884 885 self.width = width
885 886 self.height = height
886 887 self.retina = retina
887 888 self.unconfined = unconfined
888 889 self.metadata = metadata
889 890 super(Image, self).__init__(data=data, url=url, filename=filename)
890 891
891 892 if retina:
892 893 self._retina_shape()
893 894
894 895 def _retina_shape(self):
895 896 """load pixel-doubled width and height from image data"""
896 897 if not self.embed:
897 898 return
898 899 if self.format == 'png':
899 900 w, h = _pngxy(self.data)
900 901 elif self.format == 'jpeg':
901 902 w, h = _jpegxy(self.data)
902 903 else:
903 904 # retina only supports png
904 905 return
905 906 self.width = w // 2
906 907 self.height = h // 2
907 908
908 909 def reload(self):
909 910 """Reload the raw data from file or URL."""
910 911 if self.embed:
911 912 super(Image,self).reload()
912 913 if self.retina:
913 914 self._retina_shape()
914 915
915 916 def _repr_html_(self):
916 917 if not self.embed:
917 918 width = height = klass = ''
918 919 if self.width:
919 920 width = ' width="%d"' % self.width
920 921 if self.height:
921 922 height = ' height="%d"' % self.height
922 923 if self.unconfined:
923 924 klass = ' class="unconfined"'
924 925 return u'<img src="{url}"{width}{height}{klass}/>'.format(
925 926 url=self.url,
926 927 width=width,
927 928 height=height,
928 929 klass=klass,
929 930 )
930 931
931 932 def _data_and_metadata(self):
932 933 """shortcut for returning metadata with shape information, if defined"""
933 934 md = {}
934 935 if self.width:
935 936 md['width'] = self.width
936 937 if self.height:
937 938 md['height'] = self.height
938 939 if self.unconfined:
939 940 md['unconfined'] = self.unconfined
940 941 if self.metadata:
941 942 md.update(self.metadata)
942 943 if md:
943 944 return self.data, md
944 945 else:
945 946 return self.data
946 947
947 948 def _repr_png_(self):
948 949 if self.embed and self.format == u'png':
949 950 return self._data_and_metadata()
950 951
951 952 def _repr_jpeg_(self):
952 953 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
953 954 return self._data_and_metadata()
954 955
955 956 def _find_ext(self, s):
956 957 return unicode_type(s.split('.')[-1].lower())
957 958
958 959 class Video(DisplayObject):
959 960
960 961 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
961 962 """Create a video object given raw data or an URL.
962 963
963 964 When this object is returned by an input cell or passed to the
964 965 display function, it will result in the video being displayed
965 966 in the frontend.
966 967
967 968 Parameters
968 969 ----------
969 970 data : unicode, str or bytes
970 971 The raw video data or a URL or filename to load the data from.
971 972 Raw data will require passing `embed=True`.
972 973 url : unicode
973 974 A URL for the video. If you specify `url=`,
974 975 the image data will not be embedded.
975 976 filename : unicode
976 977 Path to a local file containing the video.
977 978 Will be interpreted as a local URL unless `embed=True`.
978 979 embed : bool
979 980 Should the video be embedded using a data URI (True) or be
980 981 loaded using a <video> tag (False).
981 982
982 983 Since videos are large, embedding them should be avoided, if possible.
983 984 You must confirm embedding as your intention by passing `embed=True`.
984 985
985 986 Local files can be displayed with URLs without embedding the content, via::
986 987
987 988 Video('./video.mp4')
988 989
989 990 mimetype: unicode
990 991 Specify the mimetype for embedded videos.
991 992 Default will be guessed from file extension, if available.
992 993
993 994 Examples
994 995 --------
995 996
996 997 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
997 998 Video('path/to/video.mp4')
998 999 Video('path/to/video.mp4', embed=True)
999 1000 Video(b'raw-videodata', embed=True)
1000 1001 """
1001 1002 if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')):
1002 1003 url = data
1003 1004 data = None
1004 1005 elif os.path.exists(data):
1005 1006 filename = data
1006 1007 data = None
1007 1008
1008 1009 if data and not embed:
1009 1010 msg = ''.join([
1010 1011 "To embed videos, you must pass embed=True ",
1011 1012 "(this may make your notebook files huge)\n",
1012 1013 "Consider passing Video(url='...')",
1013 1014 ])
1014 1015 raise ValueError(msg)
1015 1016
1016 1017 self.mimetype = mimetype
1017 1018 self.embed = embed
1018 1019 super(Video, self).__init__(data=data, url=url, filename=filename)
1019 1020
1020 1021 def _repr_html_(self):
1021 1022 # External URLs and potentially local files are not embedded into the
1022 1023 # notebook output.
1023 1024 if not self.embed:
1024 1025 url = self.url if self.url is not None else self.filename
1025 1026 output = """<video src="{0}" controls>
1026 1027 Your browser does not support the <code>video</code> element.
1027 1028 </video>""".format(url)
1028 1029 return output
1029 1030
1030 1031 # Embedded videos are base64-encoded.
1031 1032 mimetype = self.mimetype
1032 1033 if self.filename is not None:
1033 1034 if not mimetype:
1034 1035 mimetype, _ = mimetypes.guess_type(self.filename)
1035 1036
1036 1037 with open(self.filename, 'rb') as f:
1037 1038 video = f.read()
1038 1039 else:
1039 1040 video = self.data
1040 1041 if isinstance(video, unicode_type):
1041 1042 # unicode input is already b64-encoded
1042 1043 b64_video = video
1043 1044 else:
1044 1045 b64_video = base64_encode(video).decode('ascii').rstrip()
1045 1046
1046 1047 output = """<video controls>
1047 1048 <source src="data:{0};base64,{1}" type="{0}">
1048 1049 Your browser does not support the video tag.
1049 1050 </video>""".format(mimetype, b64_video)
1050 1051 return output
1051 1052
1052 1053 def reload(self):
1053 1054 # TODO
1054 1055 pass
1055 1056
1056 1057 def _repr_png_(self):
1057 1058 # TODO
1058 1059 pass
1059 1060 def _repr_jpeg_(self):
1060 1061 # TODO
1061 1062 pass
1062 1063
1063 1064 def clear_output(wait=False):
1064 1065 """Clear the output of the current cell receiving output.
1065 1066
1066 1067 Parameters
1067 1068 ----------
1068 1069 wait : bool [default: false]
1069 1070 Wait to clear the output until new output is available to replace it."""
1070 1071 from IPython.core.interactiveshell import InteractiveShell
1071 1072 if InteractiveShell.initialized():
1072 1073 InteractiveShell.instance().display_pub.clear_output(wait)
1073 1074 else:
1074 1075 print('\033[2K\r', end='')
1075 1076 sys.stdout.flush()
1076 1077 print('\033[2K\r', end='')
1077 1078 sys.stderr.flush()
1078 1079
1079 1080
1080 1081 @skip_doctest
1081 1082 def set_matplotlib_formats(*formats, **kwargs):
1082 1083 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1083 1084
1084 1085 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1085 1086
1086 1087 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1087 1088
1088 1089 To set this in your config files use the following::
1089 1090
1090 1091 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1091 1092 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1092 1093
1093 1094 Parameters
1094 1095 ----------
1095 1096 *formats : strs
1096 1097 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1097 1098 **kwargs :
1098 1099 Keyword args will be relayed to ``figure.canvas.print_figure``.
1099 1100 """
1100 1101 from IPython.core.interactiveshell import InteractiveShell
1101 1102 from IPython.core.pylabtools import select_figure_formats
1102 1103 # build kwargs, starting with InlineBackend config
1103 1104 kw = {}
1104 1105 from ipykernel.pylab.config import InlineBackend
1105 1106 cfg = InlineBackend.instance()
1106 1107 kw.update(cfg.print_figure_kwargs)
1107 1108 kw.update(**kwargs)
1108 1109 shell = InteractiveShell.instance()
1109 1110 select_figure_formats(shell, formats, **kw)
1110 1111
1111 1112 @skip_doctest
1112 1113 def set_matplotlib_close(close=True):
1113 1114 """Set whether the inline backend closes all figures automatically or not.
1114 1115
1115 1116 By default, the inline backend used in the IPython Notebook will close all
1116 1117 matplotlib figures automatically after each cell is run. This means that
1117 1118 plots in different cells won't interfere. Sometimes, you may want to make
1118 1119 a plot in one cell and then refine it in later cells. This can be accomplished
1119 1120 by::
1120 1121
1121 1122 In [1]: set_matplotlib_close(False)
1122 1123
1123 1124 To set this in your config files use the following::
1124 1125
1125 1126 c.InlineBackend.close_figures = False
1126 1127
1127 1128 Parameters
1128 1129 ----------
1129 1130 close : bool
1130 1131 Should all matplotlib figures be automatically closed after each cell is
1131 1132 run?
1132 1133 """
1133 1134 from ipykernel.pylab.config import InlineBackend
1134 1135 cfg = InlineBackend.instance()
1135 1136 cfg.close_figures = close
General Comments 0
You need to be logged in to leave comments. Login now