##// END OF EJS Templates
Document IPython.display API correctly
Thomas Kluyver -
Show More
@@ -1,811 +1,817 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Top-level display functions for displaying object in different formats.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2013 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from __future__ import print_function
21 21
22 22 import os
23 23 import struct
24 24
25 25 from IPython.core.formatters import _safe_get_formatter_method
26 26 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
27 27 unicode_type)
28 28 from IPython.testing.skipdoctest import skip_doctest
29 29 from .displaypub import publish_display_data
30 30
31 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
32 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
33 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
34 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
35 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close']
36
31 37 #-----------------------------------------------------------------------------
32 38 # utility functions
33 39 #-----------------------------------------------------------------------------
34 40
35 41 def _safe_exists(path):
36 42 """Check path, but don't let exceptions raise"""
37 43 try:
38 44 return os.path.exists(path)
39 45 except Exception:
40 46 return False
41 47
42 48 def _merge(d1, d2):
43 49 """Like update, but merges sub-dicts instead of clobbering at the top level.
44 50
45 51 Updates d1 in-place
46 52 """
47 53
48 54 if not isinstance(d2, dict) or not isinstance(d1, dict):
49 55 return d2
50 56 for key, value in d2.items():
51 57 d1[key] = _merge(d1.get(key), value)
52 58 return d1
53 59
54 60 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
55 61 """internal implementation of all display_foo methods
56 62
57 63 Parameters
58 64 ----------
59 65 mimetype : str
60 66 The mimetype to be published (e.g. 'image/png')
61 67 objs : tuple of objects
62 68 The Python objects to display, or if raw=True raw text data to
63 69 display.
64 70 raw : bool
65 71 Are the data objects raw data or Python objects that need to be
66 72 formatted before display? [default: False]
67 73 metadata : dict (optional)
68 74 Metadata to be associated with the specific mimetype output.
69 75 """
70 76 if metadata:
71 77 metadata = {mimetype: metadata}
72 78 if raw:
73 79 # turn list of pngdata into list of { 'image/png': pngdata }
74 80 objs = [ {mimetype: obj} for obj in objs ]
75 81 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
76 82
77 83 #-----------------------------------------------------------------------------
78 84 # Main functions
79 85 #-----------------------------------------------------------------------------
80 86
81 87 def display(*objs, **kwargs):
82 88 """Display a Python object in all frontends.
83 89
84 90 By default all representations will be computed and sent to the frontends.
85 91 Frontends can decide which representation is used and how.
86 92
87 93 Parameters
88 94 ----------
89 95 objs : tuple of objects
90 96 The Python objects to display.
91 97 raw : bool, optional
92 98 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
93 99 or Python objects that need to be formatted before display? [default: False]
94 100 include : list or tuple, optional
95 101 A list of format type strings (MIME types) to include in the
96 102 format data dict. If this is set *only* the format types included
97 103 in this list will be computed.
98 104 exclude : list or tuple, optional
99 105 A list of format type strings (MIME types) to exclude in the format
100 106 data dict. If this is set all format types will be computed,
101 107 except for those included in this argument.
102 108 metadata : dict, optional
103 109 A dictionary of metadata to associate with the output.
104 110 mime-type keys in this dictionary will be associated with the individual
105 111 representation formats, if they exist.
106 112 """
107 113 raw = kwargs.get('raw', False)
108 114 include = kwargs.get('include')
109 115 exclude = kwargs.get('exclude')
110 116 metadata = kwargs.get('metadata')
111 117
112 118 from IPython.core.interactiveshell import InteractiveShell
113 119
114 120 if not raw:
115 121 format = InteractiveShell.instance().display_formatter.format
116 122
117 123 for obj in objs:
118 124
119 125 # If _ipython_display_ is defined, use that to display this object.
120 126 display_method = _safe_get_formatter_method(obj, '_ipython_display_')
121 127 if display_method is not None:
122 128 try:
123 129 display_method(**kwargs)
124 130 except NotImplementedError:
125 131 pass
126 132 else:
127 133 continue
128 134 if raw:
129 135 publish_display_data(data=obj, metadata=metadata)
130 136 else:
131 137 format_dict, md_dict = format(obj, include=include, exclude=exclude)
132 138 if metadata:
133 139 # kwarg-specified metadata gets precedence
134 140 _merge(md_dict, metadata)
135 141 publish_display_data(data=format_dict, metadata=md_dict)
136 142
137 143
138 144 def display_pretty(*objs, **kwargs):
139 145 """Display the pretty (default) representation of an object.
140 146
141 147 Parameters
142 148 ----------
143 149 objs : tuple of objects
144 150 The Python objects to display, or if raw=True raw text data to
145 151 display.
146 152 raw : bool
147 153 Are the data objects raw data or Python objects that need to be
148 154 formatted before display? [default: False]
149 155 metadata : dict (optional)
150 156 Metadata to be associated with the specific mimetype output.
151 157 """
152 158 _display_mimetype('text/plain', objs, **kwargs)
153 159
154 160
155 161 def display_html(*objs, **kwargs):
156 162 """Display the HTML representation of an object.
157 163
158 164 Parameters
159 165 ----------
160 166 objs : tuple of objects
161 167 The Python objects to display, or if raw=True raw HTML data to
162 168 display.
163 169 raw : bool
164 170 Are the data objects raw data or Python objects that need to be
165 171 formatted before display? [default: False]
166 172 metadata : dict (optional)
167 173 Metadata to be associated with the specific mimetype output.
168 174 """
169 175 _display_mimetype('text/html', objs, **kwargs)
170 176
171 177
172 178 def display_markdown(*objs, **kwargs):
173 179 """Displays the Markdown representation of an object.
174 180
175 181 Parameters
176 182 ----------
177 183 objs : tuple of objects
178 184 The Python objects to display, or if raw=True raw markdown data to
179 185 display.
180 186 raw : bool
181 187 Are the data objects raw data or Python objects that need to be
182 188 formatted before display? [default: False]
183 189 metadata : dict (optional)
184 190 Metadata to be associated with the specific mimetype output.
185 191 """
186 192
187 193 _display_mimetype('text/markdown', objs, **kwargs)
188 194
189 195
190 196 def display_svg(*objs, **kwargs):
191 197 """Display the SVG representation of an object.
192 198
193 199 Parameters
194 200 ----------
195 201 objs : tuple of objects
196 202 The Python objects to display, or if raw=True raw svg data to
197 203 display.
198 204 raw : bool
199 205 Are the data objects raw data or Python objects that need to be
200 206 formatted before display? [default: False]
201 207 metadata : dict (optional)
202 208 Metadata to be associated with the specific mimetype output.
203 209 """
204 210 _display_mimetype('image/svg+xml', objs, **kwargs)
205 211
206 212
207 213 def display_png(*objs, **kwargs):
208 214 """Display the PNG representation of an object.
209 215
210 216 Parameters
211 217 ----------
212 218 objs : tuple of objects
213 219 The Python objects to display, or if raw=True raw png data to
214 220 display.
215 221 raw : bool
216 222 Are the data objects raw data or Python objects that need to be
217 223 formatted before display? [default: False]
218 224 metadata : dict (optional)
219 225 Metadata to be associated with the specific mimetype output.
220 226 """
221 227 _display_mimetype('image/png', objs, **kwargs)
222 228
223 229
224 230 def display_jpeg(*objs, **kwargs):
225 231 """Display the JPEG representation of an object.
226 232
227 233 Parameters
228 234 ----------
229 235 objs : tuple of objects
230 236 The Python objects to display, or if raw=True raw JPEG data to
231 237 display.
232 238 raw : bool
233 239 Are the data objects raw data or Python objects that need to be
234 240 formatted before display? [default: False]
235 241 metadata : dict (optional)
236 242 Metadata to be associated with the specific mimetype output.
237 243 """
238 244 _display_mimetype('image/jpeg', objs, **kwargs)
239 245
240 246
241 247 def display_latex(*objs, **kwargs):
242 248 """Display the LaTeX representation of an object.
243 249
244 250 Parameters
245 251 ----------
246 252 objs : tuple of objects
247 253 The Python objects to display, or if raw=True raw latex data to
248 254 display.
249 255 raw : bool
250 256 Are the data objects raw data or Python objects that need to be
251 257 formatted before display? [default: False]
252 258 metadata : dict (optional)
253 259 Metadata to be associated with the specific mimetype output.
254 260 """
255 261 _display_mimetype('text/latex', objs, **kwargs)
256 262
257 263
258 264 def display_json(*objs, **kwargs):
259 265 """Display the JSON representation of an object.
260 266
261 267 Note that not many frontends support displaying JSON.
262 268
263 269 Parameters
264 270 ----------
265 271 objs : tuple of objects
266 272 The Python objects to display, or if raw=True raw json data to
267 273 display.
268 274 raw : bool
269 275 Are the data objects raw data or Python objects that need to be
270 276 formatted before display? [default: False]
271 277 metadata : dict (optional)
272 278 Metadata to be associated with the specific mimetype output.
273 279 """
274 280 _display_mimetype('application/json', objs, **kwargs)
275 281
276 282
277 283 def display_javascript(*objs, **kwargs):
278 284 """Display the Javascript representation of an object.
279 285
280 286 Parameters
281 287 ----------
282 288 objs : tuple of objects
283 289 The Python objects to display, or if raw=True raw javascript data to
284 290 display.
285 291 raw : bool
286 292 Are the data objects raw data or Python objects that need to be
287 293 formatted before display? [default: False]
288 294 metadata : dict (optional)
289 295 Metadata to be associated with the specific mimetype output.
290 296 """
291 297 _display_mimetype('application/javascript', objs, **kwargs)
292 298
293 299
294 300 def display_pdf(*objs, **kwargs):
295 301 """Display the PDF representation of an object.
296 302
297 303 Parameters
298 304 ----------
299 305 objs : tuple of objects
300 306 The Python objects to display, or if raw=True raw javascript data to
301 307 display.
302 308 raw : bool
303 309 Are the data objects raw data or Python objects that need to be
304 310 formatted before display? [default: False]
305 311 metadata : dict (optional)
306 312 Metadata to be associated with the specific mimetype output.
307 313 """
308 314 _display_mimetype('application/pdf', objs, **kwargs)
309 315
310 316
311 317 #-----------------------------------------------------------------------------
312 318 # Smart classes
313 319 #-----------------------------------------------------------------------------
314 320
315 321
316 322 class DisplayObject(object):
317 323 """An object that wraps data to be displayed."""
318 324
319 325 _read_flags = 'r'
320 326 _show_mem_addr = False
321 327
322 328 def __init__(self, data=None, url=None, filename=None):
323 329 """Create a display object given raw data.
324 330
325 331 When this object is returned by an expression or passed to the
326 332 display function, it will result in the data being displayed
327 333 in the frontend. The MIME type of the data should match the
328 334 subclasses used, so the Png subclass should be used for 'image/png'
329 335 data. If the data is a URL, the data will first be downloaded
330 336 and then displayed. If
331 337
332 338 Parameters
333 339 ----------
334 340 data : unicode, str or bytes
335 341 The raw data or a URL or file to load the data from
336 342 url : unicode
337 343 A URL to download the data from.
338 344 filename : unicode
339 345 Path to a local file to load the data from.
340 346 """
341 347 if data is not None and isinstance(data, string_types):
342 348 if data.startswith('http') and url is None:
343 349 url = data
344 350 filename = None
345 351 data = None
346 352 elif _safe_exists(data) and filename is None:
347 353 url = None
348 354 filename = data
349 355 data = None
350 356
351 357 self.data = data
352 358 self.url = url
353 359 self.filename = None if filename is None else unicode_type(filename)
354 360
355 361 self.reload()
356 362 self._check_data()
357 363
358 364 def __repr__(self):
359 365 if not self._show_mem_addr:
360 366 cls = self.__class__
361 367 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
362 368 else:
363 369 r = super(DisplayObject, self).__repr__()
364 370 return r
365 371
366 372 def _check_data(self):
367 373 """Override in subclasses if there's something to check."""
368 374 pass
369 375
370 376 def reload(self):
371 377 """Reload the raw data from file or URL."""
372 378 if self.filename is not None:
373 379 with open(self.filename, self._read_flags) as f:
374 380 self.data = f.read()
375 381 elif self.url is not None:
376 382 try:
377 383 try:
378 384 from urllib.request import urlopen # Py3
379 385 except ImportError:
380 386 from urllib2 import urlopen
381 387 response = urlopen(self.url)
382 388 self.data = response.read()
383 389 # extract encoding from header, if there is one:
384 390 encoding = None
385 391 for sub in response.headers['content-type'].split(';'):
386 392 sub = sub.strip()
387 393 if sub.startswith('charset'):
388 394 encoding = sub.split('=')[-1].strip()
389 395 break
390 396 # decode data, if an encoding was specified
391 397 if encoding:
392 398 self.data = self.data.decode(encoding, 'replace')
393 399 except:
394 400 self.data = None
395 401
396 402 class TextDisplayObject(DisplayObject):
397 403 """Validate that display data is text"""
398 404 def _check_data(self):
399 405 if self.data is not None and not isinstance(self.data, string_types):
400 406 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
401 407
402 408 class Pretty(TextDisplayObject):
403 409
404 410 def _repr_pretty_(self):
405 411 return self.data
406 412
407 413
408 414 class HTML(TextDisplayObject):
409 415
410 416 def _repr_html_(self):
411 417 return self.data
412 418
413 419 def __html__(self):
414 420 """
415 421 This method exists to inform other HTML-using modules (e.g. Markupsafe,
416 422 htmltag, etc) that this object is HTML and does not need things like
417 423 special characters (<>&) escaped.
418 424 """
419 425 return self._repr_html_()
420 426
421 427
422 428 class Markdown(TextDisplayObject):
423 429
424 430 def _repr_markdown_(self):
425 431 return self.data
426 432
427 433
428 434 class Math(TextDisplayObject):
429 435
430 436 def _repr_latex_(self):
431 437 s = self.data.strip('$')
432 438 return "$$%s$$" % s
433 439
434 440
435 441 class Latex(TextDisplayObject):
436 442
437 443 def _repr_latex_(self):
438 444 return self.data
439 445
440 446
441 447 class SVG(DisplayObject):
442 448
443 449 # wrap data in a property, which extracts the <svg> tag, discarding
444 450 # document headers
445 451 _data = None
446 452
447 453 @property
448 454 def data(self):
449 455 return self._data
450 456
451 457 @data.setter
452 458 def data(self, svg):
453 459 if svg is None:
454 460 self._data = None
455 461 return
456 462 # parse into dom object
457 463 from xml.dom import minidom
458 464 svg = cast_bytes_py2(svg)
459 465 x = minidom.parseString(svg)
460 466 # get svg tag (should be 1)
461 467 found_svg = x.getElementsByTagName('svg')
462 468 if found_svg:
463 469 svg = found_svg[0].toxml()
464 470 else:
465 471 # fallback on the input, trust the user
466 472 # but this is probably an error.
467 473 pass
468 474 svg = cast_unicode(svg)
469 475 self._data = svg
470 476
471 477 def _repr_svg_(self):
472 478 return self.data
473 479
474 480
475 481 class JSON(TextDisplayObject):
476 482
477 483 def _repr_json_(self):
478 484 return self.data
479 485
480 486 css_t = """$("head").append($("<link/>").attr({
481 487 rel: "stylesheet",
482 488 type: "text/css",
483 489 href: "%s"
484 490 }));
485 491 """
486 492
487 493 lib_t1 = """$.getScript("%s", function () {
488 494 """
489 495 lib_t2 = """});
490 496 """
491 497
492 498 class Javascript(TextDisplayObject):
493 499
494 500 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
495 501 """Create a Javascript display object given raw data.
496 502
497 503 When this object is returned by an expression or passed to the
498 504 display function, it will result in the data being displayed
499 505 in the frontend. If the data is a URL, the data will first be
500 506 downloaded and then displayed.
501 507
502 508 In the Notebook, the containing element will be available as `element`,
503 509 and jQuery will be available. Content appended to `element` will be
504 510 visible in the output area.
505 511
506 512 Parameters
507 513 ----------
508 514 data : unicode, str or bytes
509 515 The Javascript source code or a URL to download it from.
510 516 url : unicode
511 517 A URL to download the data from.
512 518 filename : unicode
513 519 Path to a local file to load the data from.
514 520 lib : list or str
515 521 A sequence of Javascript library URLs to load asynchronously before
516 522 running the source code. The full URLs of the libraries should
517 523 be given. A single Javascript library URL can also be given as a
518 524 string.
519 525 css: : list or str
520 526 A sequence of css files to load before running the source code.
521 527 The full URLs of the css files should be given. A single css URL
522 528 can also be given as a string.
523 529 """
524 530 if isinstance(lib, string_types):
525 531 lib = [lib]
526 532 elif lib is None:
527 533 lib = []
528 534 if isinstance(css, string_types):
529 535 css = [css]
530 536 elif css is None:
531 537 css = []
532 538 if not isinstance(lib, (list,tuple)):
533 539 raise TypeError('expected sequence, got: %r' % lib)
534 540 if not isinstance(css, (list,tuple)):
535 541 raise TypeError('expected sequence, got: %r' % css)
536 542 self.lib = lib
537 543 self.css = css
538 544 super(Javascript, self).__init__(data=data, url=url, filename=filename)
539 545
540 546 def _repr_javascript_(self):
541 547 r = ''
542 548 for c in self.css:
543 549 r += css_t % c
544 550 for l in self.lib:
545 551 r += lib_t1 % l
546 552 r += self.data
547 553 r += lib_t2*len(self.lib)
548 554 return r
549 555
550 556 # constants for identifying png/jpeg data
551 557 _PNG = b'\x89PNG\r\n\x1a\n'
552 558 _JPEG = b'\xff\xd8'
553 559
554 560 def _pngxy(data):
555 561 """read the (width, height) from a PNG header"""
556 562 ihdr = data.index(b'IHDR')
557 563 # next 8 bytes are width/height
558 564 w4h4 = data[ihdr+4:ihdr+12]
559 565 return struct.unpack('>ii', w4h4)
560 566
561 567 def _jpegxy(data):
562 568 """read the (width, height) from a JPEG header"""
563 569 # adapted from http://www.64lines.com/jpeg-width-height
564 570
565 571 idx = 4
566 572 while True:
567 573 block_size = struct.unpack('>H', data[idx:idx+2])[0]
568 574 idx = idx + block_size
569 575 if data[idx:idx+2] == b'\xFF\xC0':
570 576 # found Start of Frame
571 577 iSOF = idx
572 578 break
573 579 else:
574 580 # read another block
575 581 idx += 2
576 582
577 583 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
578 584 return w, h
579 585
580 586 class Image(DisplayObject):
581 587
582 588 _read_flags = 'rb'
583 589 _FMT_JPEG = u'jpeg'
584 590 _FMT_PNG = u'png'
585 591 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
586 592
587 593 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
588 594 """Create a PNG/JPEG image object given raw data.
589 595
590 596 When this object is returned by an input cell or passed to the
591 597 display function, it will result in the image being displayed
592 598 in the frontend.
593 599
594 600 Parameters
595 601 ----------
596 602 data : unicode, str or bytes
597 603 The raw image data or a URL or filename to load the data from.
598 604 This always results in embedded image data.
599 605 url : unicode
600 606 A URL to download the data from. If you specify `url=`,
601 607 the image data will not be embedded unless you also specify `embed=True`.
602 608 filename : unicode
603 609 Path to a local file to load the data from.
604 610 Images from a file are always embedded.
605 611 format : unicode
606 612 The format of the image data (png/jpeg/jpg). If a filename or URL is given
607 613 for format will be inferred from the filename extension.
608 614 embed : bool
609 615 Should the image data be embedded using a data URI (True) or be
610 616 loaded using an <img> tag. Set this to True if you want the image
611 617 to be viewable later with no internet connection in the notebook.
612 618
613 619 Default is `True`, unless the keyword argument `url` is set, then
614 620 default value is `False`.
615 621
616 622 Note that QtConsole is not able to display images if `embed` is set to `False`
617 623 width : int
618 624 Width to which to constrain the image in html
619 625 height : int
620 626 Height to which to constrain the image in html
621 627 retina : bool
622 628 Automatically set the width and height to half of the measured
623 629 width and height.
624 630 This only works for embedded images because it reads the width/height
625 631 from image data.
626 632 For non-embedded images, you can just set the desired display width
627 633 and height directly.
628 634
629 635 Examples
630 636 --------
631 637 # embedded image data, works in qtconsole and notebook
632 638 # when passed positionally, the first arg can be any of raw image data,
633 639 # a URL, or a filename from which to load image data.
634 640 # The result is always embedding image data for inline images.
635 641 Image('http://www.google.fr/images/srpr/logo3w.png')
636 642 Image('/path/to/image.jpg')
637 643 Image(b'RAW_PNG_DATA...')
638 644
639 645 # Specifying Image(url=...) does not embed the image data,
640 646 # it only generates `<img>` tag with a link to the source.
641 647 # This will not work in the qtconsole or offline.
642 648 Image(url='http://www.google.fr/images/srpr/logo3w.png')
643 649
644 650 """
645 651 if filename is not None:
646 652 ext = self._find_ext(filename)
647 653 elif url is not None:
648 654 ext = self._find_ext(url)
649 655 elif data is None:
650 656 raise ValueError("No image data found. Expecting filename, url, or data.")
651 657 elif isinstance(data, string_types) and (
652 658 data.startswith('http') or _safe_exists(data)
653 659 ):
654 660 ext = self._find_ext(data)
655 661 else:
656 662 ext = None
657 663
658 664 if ext is not None:
659 665 format = ext.lower()
660 666 if ext == u'jpg' or ext == u'jpeg':
661 667 format = self._FMT_JPEG
662 668 if ext == u'png':
663 669 format = self._FMT_PNG
664 670 elif isinstance(data, bytes) and format == 'png':
665 671 # infer image type from image data header,
666 672 # only if format might not have been specified.
667 673 if data[:2] == _JPEG:
668 674 format = 'jpeg'
669 675
670 676 self.format = unicode_type(format).lower()
671 677 self.embed = embed if embed is not None else (url is None)
672 678
673 679 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
674 680 raise ValueError("Cannot embed the '%s' image format" % (self.format))
675 681 self.width = width
676 682 self.height = height
677 683 self.retina = retina
678 684 super(Image, self).__init__(data=data, url=url, filename=filename)
679 685
680 686 if retina:
681 687 self._retina_shape()
682 688
683 689 def _retina_shape(self):
684 690 """load pixel-doubled width and height from image data"""
685 691 if not self.embed:
686 692 return
687 693 if self.format == 'png':
688 694 w, h = _pngxy(self.data)
689 695 elif self.format == 'jpeg':
690 696 w, h = _jpegxy(self.data)
691 697 else:
692 698 # retina only supports png
693 699 return
694 700 self.width = w // 2
695 701 self.height = h // 2
696 702
697 703 def reload(self):
698 704 """Reload the raw data from file or URL."""
699 705 if self.embed:
700 706 super(Image,self).reload()
701 707 if self.retina:
702 708 self._retina_shape()
703 709
704 710 def _repr_html_(self):
705 711 if not self.embed:
706 712 width = height = ''
707 713 if self.width:
708 714 width = ' width="%d"' % self.width
709 715 if self.height:
710 716 height = ' height="%d"' % self.height
711 717 return u'<img src="%s"%s%s/>' % (self.url, width, height)
712 718
713 719 def _data_and_metadata(self):
714 720 """shortcut for returning metadata with shape information, if defined"""
715 721 md = {}
716 722 if self.width:
717 723 md['width'] = self.width
718 724 if self.height:
719 725 md['height'] = self.height
720 726 if md:
721 727 return self.data, md
722 728 else:
723 729 return self.data
724 730
725 731 def _repr_png_(self):
726 732 if self.embed and self.format == u'png':
727 733 return self._data_and_metadata()
728 734
729 735 def _repr_jpeg_(self):
730 736 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
731 737 return self._data_and_metadata()
732 738
733 739 def _find_ext(self, s):
734 740 return unicode_type(s.split('.')[-1].lower())
735 741
736 742
737 743 def clear_output(wait=False):
738 744 """Clear the output of the current cell receiving output.
739 745
740 746 Parameters
741 747 ----------
742 748 wait : bool [default: false]
743 749 Wait to clear the output until new output is available to replace it."""
744 750 from IPython.core.interactiveshell import InteractiveShell
745 751 if InteractiveShell.initialized():
746 752 InteractiveShell.instance().display_pub.clear_output(wait)
747 753 else:
748 754 from IPython.utils import io
749 755 print('\033[2K\r', file=io.stdout, end='')
750 756 io.stdout.flush()
751 757 print('\033[2K\r', file=io.stderr, end='')
752 758 io.stderr.flush()
753 759
754 760
755 761 @skip_doctest
756 762 def set_matplotlib_formats(*formats, **kwargs):
757 763 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
758 764
759 765 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
760 766
761 767 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
762 768
763 769 To set this in your config files use the following::
764 770
765 771 c.InlineBackend.figure_formats = {'png', 'jpeg'}
766 772 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
767 773
768 774 Parameters
769 775 ----------
770 776 *formats : strs
771 777 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
772 778 **kwargs :
773 779 Keyword args will be relayed to ``figure.canvas.print_figure``.
774 780 """
775 781 from IPython.core.interactiveshell import InteractiveShell
776 782 from IPython.core.pylabtools import select_figure_formats
777 783 from IPython.kernel.zmq.pylab.config import InlineBackend
778 784 # build kwargs, starting with InlineBackend config
779 785 kw = {}
780 786 cfg = InlineBackend.instance()
781 787 kw.update(cfg.print_figure_kwargs)
782 788 kw.update(**kwargs)
783 789 shell = InteractiveShell.instance()
784 790 select_figure_formats(shell, formats, **kw)
785 791
786 792 @skip_doctest
787 793 def set_matplotlib_close(close=True):
788 794 """Set whether the inline backend closes all figures automatically or not.
789 795
790 796 By default, the inline backend used in the IPython Notebook will close all
791 797 matplotlib figures automatically after each cell is run. This means that
792 798 plots in different cells won't interfere. Sometimes, you may want to make
793 799 a plot in one cell and then refine it in later cells. This can be accomplished
794 800 by::
795 801
796 802 In [1]: set_matplotlib_close(False)
797 803
798 804 To set this in your config files use the following::
799 805
800 806 c.InlineBackend.close_figures = False
801 807
802 808 Parameters
803 809 ----------
804 810 close : bool
805 811 Should all matplotlib figures be automatically closed after each cell is
806 812 run?
807 813 """
808 814 from IPython.kernel.zmq.pylab.config import InlineBackend
809 815 cfg = InlineBackend.instance()
810 816 cfg.close_figures = close
811 817
@@ -1,530 +1,533 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 __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument',
11 'FileLink', 'FileLinks']
12
10 13
11 14 class Audio(DisplayObject):
12 15 """Create an audio object.
13 16
14 17 When this object is returned by an input cell or passed to the
15 18 display function, it will result in Audio controls being displayed
16 19 in the frontend (only works in the notebook).
17 20
18 21 Parameters
19 22 ----------
20 23 data : numpy array, list, unicode, str or bytes
21 24 Can be one of
22 25
23 26 * Numpy 1d array containing the desired waveform (mono)
24 27 * Numpy 2d array containing waveforms for each channel.
25 28 Shape=(NCHAN, NSAMPLES). For the standard channel order, see
26 29 http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
27 30 * List of float or integer representing the waveform (mono)
28 31 * String containing the filename
29 32 * Bytestring containing raw PCM data or
30 33 * URL pointing to a file on the web.
31 34
32 35 If the array option is used the waveform will be normalized.
33 36
34 37 If a filename or url is used the format support will be browser
35 38 dependent.
36 39 url : unicode
37 40 A URL to download the data from.
38 41 filename : unicode
39 42 Path to a local file to load the data from.
40 43 embed : boolean
41 44 Should the image data be embedded using a data URI (True) or should
42 45 the original source be referenced. Set this to True if you want the
43 46 audio to playable later with no internet connection in the notebook.
44 47
45 48 Default is `True`, unless the keyword argument `url` is set, then
46 49 default value is `False`.
47 50 rate : integer
48 51 The sampling rate of the raw data.
49 52 Only required when data parameter is being used as an array
50 53 autoplay : bool
51 54 Set to True if the audio should immediately start playing.
52 55 Default is `False`.
53 56
54 57 Examples
55 58 --------
56 59 ::
57 60
58 61 # Generate a sound
59 62 import numpy as np
60 63 framerate = 44100
61 64 t = np.linspace(0,5,framerate*5)
62 65 data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t))
63 66 Audio(data,rate=framerate)
64 67
65 68 # Can also do stereo or more channels
66 69 dataleft = np.sin(2*np.pi*220*t)
67 70 dataright = np.sin(2*np.pi*224*t)
68 71 Audio([dataleft, dataright],rate=framerate)
69 72
70 73 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # From URL
71 74 Audio(url="http://www.w3schools.com/html/horse.ogg")
72 75
73 76 Audio('/path/to/sound.wav') # From file
74 77 Audio(filename='/path/to/sound.ogg')
75 78
76 79 Audio(b'RAW_WAV_DATA..) # From bytes
77 80 Audio(data=b'RAW_WAV_DATA..)
78 81
79 82 """
80 83 _read_flags = 'rb'
81 84
82 85 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False):
83 86 if filename is None and url is None and data is None:
84 87 raise ValueError("No image data found. Expecting filename, url, or data.")
85 88 if embed is False and url is None:
86 89 raise ValueError("No url found. Expecting url when embed=False")
87 90
88 91 if url is not None and embed is not True:
89 92 self.embed = False
90 93 else:
91 94 self.embed = True
92 95 self.autoplay = autoplay
93 96 super(Audio, self).__init__(data=data, url=url, filename=filename)
94 97
95 98 if self.data is not None and not isinstance(self.data, bytes):
96 99 self.data = self._make_wav(data,rate)
97 100
98 101 def reload(self):
99 102 """Reload the raw data from file or URL."""
100 103 import mimetypes
101 104 if self.embed:
102 105 super(Audio, self).reload()
103 106
104 107 if self.filename is not None:
105 108 self.mimetype = mimetypes.guess_type(self.filename)[0]
106 109 elif self.url is not None:
107 110 self.mimetype = mimetypes.guess_type(self.url)[0]
108 111 else:
109 112 self.mimetype = "audio/wav"
110 113
111 114 def _make_wav(self, data, rate):
112 115 """ Transform a numpy array to a PCM bytestring """
113 116 import struct
114 117 from io import BytesIO
115 118 import wave
116 119
117 120 try:
118 121 import numpy as np
119 122
120 123 data = np.array(data, dtype=float)
121 124 if len(data.shape) == 1:
122 125 nchan = 1
123 126 elif len(data.shape) == 2:
124 127 # In wave files,channels are interleaved. E.g.,
125 128 # "L1R1L2R2..." for stereo. See
126 129 # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
127 130 # for channel ordering
128 131 nchan = data.shape[0]
129 132 data = data.T.ravel()
130 133 else:
131 134 raise ValueError('Array audio input must be a 1D or 2D array')
132 135 scaled = np.int16(data/np.max(np.abs(data))*32767).tolist()
133 136 except ImportError:
134 137 # check that it is a "1D" list
135 138 idata = iter(data) # fails if not an iterable
136 139 try:
137 140 iter(idata.next())
138 141 raise TypeError('Only lists of mono audio are '
139 142 'supported if numpy is not installed')
140 143 except TypeError:
141 144 # this means it's not a nested list, which is what we want
142 145 pass
143 146 maxabsvalue = float(max([abs(x) for x in data]))
144 147 scaled = [int(x/maxabsvalue*32767) for x in data]
145 148 nchan = 1
146 149
147 150 fp = BytesIO()
148 151 waveobj = wave.open(fp,mode='wb')
149 152 waveobj.setnchannels(nchan)
150 153 waveobj.setframerate(rate)
151 154 waveobj.setsampwidth(2)
152 155 waveobj.setcomptype('NONE','NONE')
153 156 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
154 157 val = fp.getvalue()
155 158 waveobj.close()
156 159
157 160 return val
158 161
159 162 def _data_and_metadata(self):
160 163 """shortcut for returning metadata with url information, if defined"""
161 164 md = {}
162 165 if self.url:
163 166 md['url'] = self.url
164 167 if md:
165 168 return self.data, md
166 169 else:
167 170 return self.data
168 171
169 172 def _repr_html_(self):
170 173 src = """
171 174 <audio controls="controls" {autoplay}>
172 175 <source src="{src}" type="{type}" />
173 176 Your browser does not support the audio element.
174 177 </audio>
175 178 """
176 179 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
177 180
178 181 def src_attr(self):
179 182 import base64
180 183 if self.embed and (self.data is not None):
181 184 data = base64=base64.b64encode(self.data).decode('ascii')
182 185 return """data:{type};base64,{base64}""".format(type=self.mimetype,
183 186 base64=data)
184 187 elif self.url is not None:
185 188 return self.url
186 189 else:
187 190 return ""
188 191
189 192 def autoplay_attr(self):
190 193 if(self.autoplay):
191 194 return 'autoplay="autoplay"'
192 195 else:
193 196 return ''
194 197
195 198 class IFrame(object):
196 199 """
197 200 Generic class to embed an iframe in an IPython notebook
198 201 """
199 202
200 203 iframe = """
201 204 <iframe
202 205 width="{width}"
203 206 height={height}"
204 207 src="{src}{params}"
205 208 frameborder="0"
206 209 allowfullscreen
207 210 ></iframe>
208 211 """
209 212
210 213 def __init__(self, src, width, height, **kwargs):
211 214 self.src = src
212 215 self.width = width
213 216 self.height = height
214 217 self.params = kwargs
215 218
216 219 def _repr_html_(self):
217 220 """return the embed iframe"""
218 221 if self.params:
219 222 try:
220 223 from urllib.parse import urlencode # Py 3
221 224 except ImportError:
222 225 from urllib import urlencode
223 226 params = "?" + urlencode(self.params)
224 227 else:
225 228 params = ""
226 229 return self.iframe.format(src=self.src,
227 230 width=self.width,
228 231 height=self.height,
229 232 params=params)
230 233
231 234 class YouTubeVideo(IFrame):
232 235 """Class for embedding a YouTube Video in an IPython session, based on its video id.
233 236
234 237 e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would
235 238 do::
236 239
237 240 vid = YouTubeVideo("foo")
238 241 display(vid)
239 242
240 243 To start from 30 seconds::
241 244
242 245 vid = YouTubeVideo("abc", start=30)
243 246 display(vid)
244 247
245 248 To calculate seconds from time as hours, minutes, seconds use
246 249 :class:`datetime.timedelta`::
247 250
248 251 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
249 252
250 253 Other parameters can be provided as documented at
251 254 https://developers.google.com/youtube/player_parameters#parameter-subheader
252 255 """
253 256
254 257 def __init__(self, id, width=400, height=300, **kwargs):
255 258 src = "https://www.youtube.com/embed/{0}".format(id)
256 259 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
257 260
258 261 class VimeoVideo(IFrame):
259 262 """
260 263 Class for embedding a Vimeo video in an IPython session, based on its video id.
261 264 """
262 265
263 266 def __init__(self, id, width=400, height=300, **kwargs):
264 267 src="https://player.vimeo.com/video/{0}".format(id)
265 268 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
266 269
267 270 class ScribdDocument(IFrame):
268 271 """
269 272 Class for embedding a Scribd document in an IPython session
270 273
271 274 Use the start_page params to specify a starting point in the document
272 275 Use the view_mode params to specify display type one off scroll | slideshow | book
273 276
274 277 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
275 278
276 279 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
277 280 """
278 281
279 282 def __init__(self, id, width=400, height=300, **kwargs):
280 283 src="https://www.scribd.com/embeds/{0}/content".format(id)
281 284 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
282 285
283 286 class FileLink(object):
284 287 """Class for embedding a local file link in an IPython session, based on path
285 288
286 289 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
287 290
288 291 you would do::
289 292
290 293 local_file = FileLink("my/data.txt")
291 294 display(local_file)
292 295
293 296 or in the HTML notebook, just::
294 297
295 298 FileLink("my/data.txt")
296 299 """
297 300
298 301 html_link_str = "<a href='%s' target='_blank'>%s</a>"
299 302
300 303 def __init__(self,
301 304 path,
302 305 url_prefix='',
303 306 result_html_prefix='',
304 307 result_html_suffix='<br>'):
305 308 """
306 309 Parameters
307 310 ----------
308 311 path : str
309 312 path to the file or directory that should be formatted
310 313 directory_prefix : str
311 314 prefix to be prepended to all files to form a working link [default:
312 315 'files']
313 316 result_html_prefix : str
314 317 text to append to beginning to link [default: none]
315 318 result_html_suffix : str
316 319 text to append at the end of link [default: '<br>']
317 320 """
318 321 if isdir(path):
319 322 raise ValueError("Cannot display a directory using FileLink. "
320 323 "Use FileLinks to display '%s'." % path)
321 324 self.path = path
322 325 self.url_prefix = url_prefix
323 326 self.result_html_prefix = result_html_prefix
324 327 self.result_html_suffix = result_html_suffix
325 328
326 329 def _format_path(self):
327 330 fp = ''.join([self.url_prefix,self.path])
328 331 return ''.join([self.result_html_prefix,
329 332 self.html_link_str % (fp, self.path),
330 333 self.result_html_suffix])
331 334
332 335 def _repr_html_(self):
333 336 """return html link to file
334 337 """
335 338 if not exists(self.path):
336 339 return ("Path (<tt>%s</tt>) doesn't exist. "
337 340 "It may still be in the process of "
338 341 "being generated, or you may have the "
339 342 "incorrect path." % self.path)
340 343
341 344 return self._format_path()
342 345
343 346 def __repr__(self):
344 347 """return absolute path to file
345 348 """
346 349 return abspath(self.path)
347 350
348 351 class FileLinks(FileLink):
349 352 """Class for embedding local file links in an IPython session, based on path
350 353
351 354 e.g. to embed links to files that were generated in the IPython notebook
352 355 under ``my/data``, you would do::
353 356
354 357 local_files = FileLinks("my/data")
355 358 display(local_files)
356 359
357 360 or in the HTML notebook, just::
358 361
359 362 FileLinks("my/data")
360 363 """
361 364 def __init__(self,
362 365 path,
363 366 url_prefix='',
364 367 included_suffixes=None,
365 368 result_html_prefix='',
366 369 result_html_suffix='<br>',
367 370 notebook_display_formatter=None,
368 371 terminal_display_formatter=None):
369 372 """
370 373 See :class:`FileLink` for the ``path``, ``url_prefix``,
371 374 ``result_html_prefix`` and ``result_html_suffix`` parameters.
372 375
373 376 included_suffixes : list
374 377 Filename suffixes to include when formatting output [default: include
375 378 all files]
376 379
377 380 notebook_display_formatter : function
378 381 Used to format links for display in the notebook. See discussion of
379 382 formatter functions below.
380 383
381 384 terminal_display_formatter : function
382 385 Used to format links for display in the terminal. See discussion of
383 386 formatter functions below.
384 387
385 388 Formatter functions must be of the form::
386 389
387 390 f(dirname, fnames, included_suffixes)
388 391
389 392 dirname : str
390 393 The name of a directory
391 394 fnames : list
392 395 The files in that directory
393 396 included_suffixes : list
394 397 The file suffixes that should be included in the output (passing None
395 398 meansto include all suffixes in the output in the built-in formatters)
396 399
397 400 The function should return a list of lines that will be printed in the
398 401 notebook (if passing notebook_display_formatter) or the terminal (if
399 402 passing terminal_display_formatter). This function is iterated over for
400 403 each directory in self.path. Default formatters are in place, can be
401 404 passed here to support alternative formatting.
402 405
403 406 """
404 407 if isfile(path):
405 408 raise ValueError("Cannot display a file using FileLinks. "
406 409 "Use FileLink to display '%s'." % path)
407 410 self.included_suffixes = included_suffixes
408 411 # remove trailing slashs for more consistent output formatting
409 412 path = path.rstrip('/')
410 413
411 414 self.path = path
412 415 self.url_prefix = url_prefix
413 416 self.result_html_prefix = result_html_prefix
414 417 self.result_html_suffix = result_html_suffix
415 418
416 419 self.notebook_display_formatter = \
417 420 notebook_display_formatter or self._get_notebook_display_formatter()
418 421 self.terminal_display_formatter = \
419 422 terminal_display_formatter or self._get_terminal_display_formatter()
420 423
421 424 def _get_display_formatter(self,
422 425 dirname_output_format,
423 426 fname_output_format,
424 427 fp_format,
425 428 fp_cleaner=None):
426 429 """ generate built-in formatter function
427 430
428 431 this is used to define both the notebook and terminal built-in
429 432 formatters as they only differ by some wrapper text for each entry
430 433
431 434 dirname_output_format: string to use for formatting directory
432 435 names, dirname will be substituted for a single "%s" which
433 436 must appear in this string
434 437 fname_output_format: string to use for formatting file names,
435 438 if a single "%s" appears in the string, fname will be substituted
436 439 if two "%s" appear in the string, the path to fname will be
437 440 substituted for the first and fname will be substituted for the
438 441 second
439 442 fp_format: string to use for formatting filepaths, must contain
440 443 exactly two "%s" and the dirname will be subsituted for the first
441 444 and fname will be substituted for the second
442 445 """
443 446 def f(dirname, fnames, included_suffixes=None):
444 447 result = []
445 448 # begin by figuring out which filenames, if any,
446 449 # are going to be displayed
447 450 display_fnames = []
448 451 for fname in fnames:
449 452 if (isfile(join(dirname,fname)) and
450 453 (included_suffixes == None or
451 454 splitext(fname)[1] in included_suffixes)):
452 455 display_fnames.append(fname)
453 456
454 457 if len(display_fnames) == 0:
455 458 # if there are no filenames to display, don't print anything
456 459 # (not even the directory name)
457 460 pass
458 461 else:
459 462 # otherwise print the formatted directory name followed by
460 463 # the formatted filenames
461 464 dirname_output_line = dirname_output_format % dirname
462 465 result.append(dirname_output_line)
463 466 for fname in display_fnames:
464 467 fp = fp_format % (dirname,fname)
465 468 if fp_cleaner is not None:
466 469 fp = fp_cleaner(fp)
467 470 try:
468 471 # output can include both a filepath and a filename...
469 472 fname_output_line = fname_output_format % (fp, fname)
470 473 except TypeError:
471 474 # ... or just a single filepath
472 475 fname_output_line = fname_output_format % fname
473 476 result.append(fname_output_line)
474 477 return result
475 478 return f
476 479
477 480 def _get_notebook_display_formatter(self,
478 481 spacer="&nbsp;&nbsp;"):
479 482 """ generate function to use for notebook formatting
480 483 """
481 484 dirname_output_format = \
482 485 self.result_html_prefix + "%s/" + self.result_html_suffix
483 486 fname_output_format = \
484 487 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
485 488 fp_format = self.url_prefix + '%s/%s'
486 489 if sep == "\\":
487 490 # Working on a platform where the path separator is "\", so
488 491 # must convert these to "/" for generating a URI
489 492 def fp_cleaner(fp):
490 493 # Replace all occurences of backslash ("\") with a forward
491 494 # slash ("/") - this is necessary on windows when a path is
492 495 # provided as input, but we must link to a URI
493 496 return fp.replace('\\','/')
494 497 else:
495 498 fp_cleaner = None
496 499
497 500 return self._get_display_formatter(dirname_output_format,
498 501 fname_output_format,
499 502 fp_format,
500 503 fp_cleaner)
501 504
502 505 def _get_terminal_display_formatter(self,
503 506 spacer=" "):
504 507 """ generate function to use for terminal formatting
505 508 """
506 509 dirname_output_format = "%s/"
507 510 fname_output_format = spacer + "%s"
508 511 fp_format = '%s/%s'
509 512
510 513 return self._get_display_formatter(dirname_output_format,
511 514 fname_output_format,
512 515 fp_format)
513 516
514 517 def _format_path(self):
515 518 result_lines = []
516 519 walked_dir = list(walk(self.path))
517 520 walked_dir.sort()
518 521 for dirname, subdirs, fnames in walked_dir:
519 522 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
520 523 return '\n'.join(result_lines)
521 524
522 525 def __repr__(self):
523 526 """return newline-separated absolute paths
524 527 """
525 528 result_lines = []
526 529 walked_dir = list(walk(self.path))
527 530 walked_dir.sort()
528 531 for dirname, subdirs, fnames in walked_dir:
529 532 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
530 533 return '\n'.join(result_lines)
@@ -1,58 +1,62 b''
1 1 #!/usr/bin/env python
2 2 """Script to auto-generate our API docs.
3 3 """
4 4 # stdlib imports
5 5 import os
6 6 import sys
7 7
8 8 # local imports
9 9 sys.path.append(os.path.abspath('sphinxext'))
10 10 from apigen import ApiDocWriter
11 11
12 12 #*****************************************************************************
13 13 if __name__ == '__main__':
14 14 pjoin = os.path.join
15 15 package = 'IPython'
16 16 outdir = pjoin('source','api','generated')
17 17 docwriter = ApiDocWriter(package,rst_extension='.rst')
18 18 # You have to escape the . here because . is a special char for regexps.
19 19 # You must do make clean if you change this!
20 20 docwriter.package_skip_patterns += [r'\.external$',
21 21 # Extensions are documented elsewhere.
22 22 r'\.extensions',
23 23 r'\.config\.profile',
24 24 # These should be accessed via nbformat.current
25 25 r'\.nbformat\.v\d+',
26 26 ]
27 27
28 28 # The inputhook* modules often cause problems on import, such as trying to
29 29 # load incompatible Qt bindings. It's easiest to leave them all out. The
30 30 # main API is in the inputhook module, which is documented.
31 31 docwriter.module_skip_patterns += [ r'\.lib\.inputhook.+',
32 32 r'\.ipdoctest',
33 33 r'\.testing\.plugin',
34 34 # This just prints a deprecation msg:
35 35 r'\.frontend$',
36 36 # We document this manually.
37 37 r'\.utils\.py3compat',
38 38 # These are exposed by nbformat.current
39 39 r'\.nbformat\.convert',
40 40 r'\.nbformat\.validator',
41 # These are exposed in display
42 r'\.core\.display',
43 r'\.lib\.display',
41 44 ]
42 45
43 46 # These modules import functions and classes from other places to expose
44 47 # them as part of the public API. They must have __all__ defined. The
45 48 # non-API modules they import from should be excluded by the skip patterns
46 49 # above.
47 50 docwriter.names_from__all__.update({
48 51 'IPython.nbformat.current',
52 'IPython.display',
49 53 })
50 54
51 55 # Now, generate the outputs
52 56 docwriter.write_api_docs(outdir)
53 57 # Write index with .txt extension - we can include it, but Sphinx won't try
54 58 # to compile it
55 59 docwriter.write_index(outdir, 'gen.txt',
56 60 relative_to = pjoin('source','api')
57 61 )
58 62 print ('%d files written' % len(docwriter.written_modules))
General Comments 0
You need to be logged in to leave comments. Login now