##// END OF EJS Templates
remove python 2.x specific urllib2's functions
Srinivas Reddy Thatiparthy -
Show More

The requested changes are too big and content was truncated. Show full diff

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