##// END OF EJS Templates
JSON formatter expects JSONable dict/list...
Min RK -
Show More
@@ -1,937 +1,948 b''
1 1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats.
2 """Top-level display functions for displaying object in different formats."""
3 3
4 Authors:
5
6 * Brian Granger
7 """
8
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2013 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
19 6
20 7 from __future__ import print_function
21 8
9 import json
10 import mimetypes
22 11 import os
23 12 import struct
24 import mimetypes
13 import warnings
25 14
26 15 from IPython.core.formatters import _safe_get_formatter_method
27 16 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
28 17 unicode_type)
29 18 from IPython.testing.skipdoctest import skip_doctest
30 19
31 20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
32 21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
33 22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
34 23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
35 24 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
36 25 'publish_display_data']
37 26
38 27 #-----------------------------------------------------------------------------
39 28 # utility functions
40 29 #-----------------------------------------------------------------------------
41 30
42 31 def _safe_exists(path):
43 32 """Check path, but don't let exceptions raise"""
44 33 try:
45 34 return os.path.exists(path)
46 35 except Exception:
47 36 return False
48 37
49 38 def _merge(d1, d2):
50 39 """Like update, but merges sub-dicts instead of clobbering at the top level.
51 40
52 41 Updates d1 in-place
53 42 """
54 43
55 44 if not isinstance(d2, dict) or not isinstance(d1, dict):
56 45 return d2
57 46 for key, value in d2.items():
58 47 d1[key] = _merge(d1.get(key), value)
59 48 return d1
60 49
61 50 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
62 51 """internal implementation of all display_foo methods
63 52
64 53 Parameters
65 54 ----------
66 55 mimetype : str
67 56 The mimetype to be published (e.g. 'image/png')
68 57 objs : tuple of objects
69 58 The Python objects to display, or if raw=True raw text data to
70 59 display.
71 60 raw : bool
72 61 Are the data objects raw data or Python objects that need to be
73 62 formatted before display? [default: False]
74 63 metadata : dict (optional)
75 64 Metadata to be associated with the specific mimetype output.
76 65 """
77 66 if metadata:
78 67 metadata = {mimetype: metadata}
79 68 if raw:
80 69 # turn list of pngdata into list of { 'image/png': pngdata }
81 70 objs = [ {mimetype: obj} for obj in objs ]
82 71 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
83 72
84 73 #-----------------------------------------------------------------------------
85 74 # Main functions
86 75 #-----------------------------------------------------------------------------
87 76
88 77 def publish_display_data(data, metadata=None, source=None):
89 78 """Publish data and metadata to all frontends.
90 79
91 80 See the ``display_data`` message in the messaging documentation for
92 81 more details about this message type.
93 82
94 83 The following MIME types are currently implemented:
95 84
96 85 * text/plain
97 86 * text/html
98 87 * text/markdown
99 88 * text/latex
100 89 * application/json
101 90 * application/javascript
102 91 * image/png
103 92 * image/jpeg
104 93 * image/svg+xml
105 94
106 95 Parameters
107 96 ----------
108 97 data : dict
109 98 A dictionary having keys that are valid MIME types (like
110 99 'text/plain' or 'image/svg+xml') and values that are the data for
111 100 that MIME type. The data itself must be a JSON'able data
112 101 structure. Minimally all data should have the 'text/plain' data,
113 102 which can be displayed by all frontends. If more than the plain
114 103 text is given, it is up to the frontend to decide which
115 104 representation to use.
116 105 metadata : dict
117 106 A dictionary for metadata related to the data. This can contain
118 107 arbitrary key, value pairs that frontends can use to interpret
119 108 the data. mime-type keys matching those in data can be used
120 109 to specify metadata about particular representations.
121 110 source : str, deprecated
122 111 Unused.
123 112 """
124 113 from IPython.core.interactiveshell import InteractiveShell
125 114 InteractiveShell.instance().display_pub.publish(
126 115 data=data,
127 116 metadata=metadata,
128 117 )
129 118
130 119 def display(*objs, **kwargs):
131 120 """Display a Python object in all frontends.
132 121
133 122 By default all representations will be computed and sent to the frontends.
134 123 Frontends can decide which representation is used and how.
135 124
136 125 Parameters
137 126 ----------
138 127 objs : tuple of objects
139 128 The Python objects to display.
140 129 raw : bool, optional
141 130 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
142 131 or Python objects that need to be formatted before display? [default: False]
143 132 include : list or tuple, optional
144 133 A list of format type strings (MIME types) to include in the
145 134 format data dict. If this is set *only* the format types included
146 135 in this list will be computed.
147 136 exclude : list or tuple, optional
148 137 A list of format type strings (MIME types) to exclude in the format
149 138 data dict. If this is set all format types will be computed,
150 139 except for those included in this argument.
151 140 metadata : dict, optional
152 141 A dictionary of metadata to associate with the output.
153 142 mime-type keys in this dictionary will be associated with the individual
154 143 representation formats, if they exist.
155 144 """
156 145 raw = kwargs.get('raw', False)
157 146 include = kwargs.get('include')
158 147 exclude = kwargs.get('exclude')
159 148 metadata = kwargs.get('metadata')
160 149
161 150 from IPython.core.interactiveshell import InteractiveShell
162 151
163 152 if not raw:
164 153 format = InteractiveShell.instance().display_formatter.format
165 154
166 155 for obj in objs:
167 156 if raw:
168 157 publish_display_data(data=obj, metadata=metadata)
169 158 else:
170 159 format_dict, md_dict = format(obj, include=include, exclude=exclude)
171 160 if not format_dict:
172 161 # nothing to display (e.g. _ipython_display_ took over)
173 162 continue
174 163 if metadata:
175 164 # kwarg-specified metadata gets precedence
176 165 _merge(md_dict, metadata)
177 166 publish_display_data(data=format_dict, metadata=md_dict)
178 167
179 168
180 169 def display_pretty(*objs, **kwargs):
181 170 """Display the pretty (default) representation of an object.
182 171
183 172 Parameters
184 173 ----------
185 174 objs : tuple of objects
186 175 The Python objects to display, or if raw=True raw text data to
187 176 display.
188 177 raw : bool
189 178 Are the data objects raw data or Python objects that need to be
190 179 formatted before display? [default: False]
191 180 metadata : dict (optional)
192 181 Metadata to be associated with the specific mimetype output.
193 182 """
194 183 _display_mimetype('text/plain', objs, **kwargs)
195 184
196 185
197 186 def display_html(*objs, **kwargs):
198 187 """Display the HTML representation of an object.
199 188
200 189 Parameters
201 190 ----------
202 191 objs : tuple of objects
203 192 The Python objects to display, or if raw=True raw HTML data to
204 193 display.
205 194 raw : bool
206 195 Are the data objects raw data or Python objects that need to be
207 196 formatted before display? [default: False]
208 197 metadata : dict (optional)
209 198 Metadata to be associated with the specific mimetype output.
210 199 """
211 200 _display_mimetype('text/html', objs, **kwargs)
212 201
213 202
214 203 def display_markdown(*objs, **kwargs):
215 204 """Displays the Markdown representation of an object.
216 205
217 206 Parameters
218 207 ----------
219 208 objs : tuple of objects
220 209 The Python objects to display, or if raw=True raw markdown data to
221 210 display.
222 211 raw : bool
223 212 Are the data objects raw data or Python objects that need to be
224 213 formatted before display? [default: False]
225 214 metadata : dict (optional)
226 215 Metadata to be associated with the specific mimetype output.
227 216 """
228 217
229 218 _display_mimetype('text/markdown', objs, **kwargs)
230 219
231 220
232 221 def display_svg(*objs, **kwargs):
233 222 """Display the SVG representation of an object.
234 223
235 224 Parameters
236 225 ----------
237 226 objs : tuple of objects
238 227 The Python objects to display, or if raw=True raw svg data to
239 228 display.
240 229 raw : bool
241 230 Are the data objects raw data or Python objects that need to be
242 231 formatted before display? [default: False]
243 232 metadata : dict (optional)
244 233 Metadata to be associated with the specific mimetype output.
245 234 """
246 235 _display_mimetype('image/svg+xml', objs, **kwargs)
247 236
248 237
249 238 def display_png(*objs, **kwargs):
250 239 """Display the PNG representation of an object.
251 240
252 241 Parameters
253 242 ----------
254 243 objs : tuple of objects
255 244 The Python objects to display, or if raw=True raw png data to
256 245 display.
257 246 raw : bool
258 247 Are the data objects raw data or Python objects that need to be
259 248 formatted before display? [default: False]
260 249 metadata : dict (optional)
261 250 Metadata to be associated with the specific mimetype output.
262 251 """
263 252 _display_mimetype('image/png', objs, **kwargs)
264 253
265 254
266 255 def display_jpeg(*objs, **kwargs):
267 256 """Display the JPEG representation of an object.
268 257
269 258 Parameters
270 259 ----------
271 260 objs : tuple of objects
272 261 The Python objects to display, or if raw=True raw JPEG data to
273 262 display.
274 263 raw : bool
275 264 Are the data objects raw data or Python objects that need to be
276 265 formatted before display? [default: False]
277 266 metadata : dict (optional)
278 267 Metadata to be associated with the specific mimetype output.
279 268 """
280 269 _display_mimetype('image/jpeg', objs, **kwargs)
281 270
282 271
283 272 def display_latex(*objs, **kwargs):
284 273 """Display the LaTeX representation of an object.
285 274
286 275 Parameters
287 276 ----------
288 277 objs : tuple of objects
289 278 The Python objects to display, or if raw=True raw latex data to
290 279 display.
291 280 raw : bool
292 281 Are the data objects raw data or Python objects that need to be
293 282 formatted before display? [default: False]
294 283 metadata : dict (optional)
295 284 Metadata to be associated with the specific mimetype output.
296 285 """
297 286 _display_mimetype('text/latex', objs, **kwargs)
298 287
299 288
300 289 def display_json(*objs, **kwargs):
301 290 """Display the JSON representation of an object.
302 291
303 292 Note that not many frontends support displaying JSON.
304 293
305 294 Parameters
306 295 ----------
307 296 objs : tuple of objects
308 297 The Python objects to display, or if raw=True raw json data to
309 298 display.
310 299 raw : bool
311 300 Are the data objects raw data or Python objects that need to be
312 301 formatted before display? [default: False]
313 302 metadata : dict (optional)
314 303 Metadata to be associated with the specific mimetype output.
315 304 """
316 305 _display_mimetype('application/json', objs, **kwargs)
317 306
318 307
319 308 def display_javascript(*objs, **kwargs):
320 309 """Display the Javascript representation of an object.
321 310
322 311 Parameters
323 312 ----------
324 313 objs : tuple of objects
325 314 The Python objects to display, or if raw=True raw javascript data to
326 315 display.
327 316 raw : bool
328 317 Are the data objects raw data or Python objects that need to be
329 318 formatted before display? [default: False]
330 319 metadata : dict (optional)
331 320 Metadata to be associated with the specific mimetype output.
332 321 """
333 322 _display_mimetype('application/javascript', objs, **kwargs)
334 323
335 324
336 325 def display_pdf(*objs, **kwargs):
337 326 """Display the PDF representation of an object.
338 327
339 328 Parameters
340 329 ----------
341 330 objs : tuple of objects
342 331 The Python objects to display, or if raw=True raw javascript data to
343 332 display.
344 333 raw : bool
345 334 Are the data objects raw data or Python objects that need to be
346 335 formatted before display? [default: False]
347 336 metadata : dict (optional)
348 337 Metadata to be associated with the specific mimetype output.
349 338 """
350 339 _display_mimetype('application/pdf', objs, **kwargs)
351 340
352 341
353 342 #-----------------------------------------------------------------------------
354 343 # Smart classes
355 344 #-----------------------------------------------------------------------------
356 345
357 346
358 347 class DisplayObject(object):
359 348 """An object that wraps data to be displayed."""
360 349
361 350 _read_flags = 'r'
362 351 _show_mem_addr = False
363 352
364 353 def __init__(self, data=None, url=None, filename=None):
365 354 """Create a display object given raw data.
366 355
367 356 When this object is returned by an expression or passed to the
368 357 display function, it will result in the data being displayed
369 358 in the frontend. The MIME type of the data should match the
370 359 subclasses used, so the Png subclass should be used for 'image/png'
371 360 data. If the data is a URL, the data will first be downloaded
372 361 and then displayed. If
373 362
374 363 Parameters
375 364 ----------
376 365 data : unicode, str or bytes
377 366 The raw data or a URL or file to load the data from
378 367 url : unicode
379 368 A URL to download the data from.
380 369 filename : unicode
381 370 Path to a local file to load the data from.
382 371 """
383 372 if data is not None and isinstance(data, string_types):
384 373 if data.startswith('http') and url is None:
385 374 url = data
386 375 filename = None
387 376 data = None
388 377 elif _safe_exists(data) and filename is None:
389 378 url = None
390 379 filename = data
391 380 data = None
392 381
393 382 self.data = data
394 383 self.url = url
395 384 self.filename = None if filename is None else unicode_type(filename)
396 385
397 386 self.reload()
398 387 self._check_data()
399 388
400 389 def __repr__(self):
401 390 if not self._show_mem_addr:
402 391 cls = self.__class__
403 392 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
404 393 else:
405 394 r = super(DisplayObject, self).__repr__()
406 395 return r
407 396
408 397 def _check_data(self):
409 398 """Override in subclasses if there's something to check."""
410 399 pass
411 400
412 401 def reload(self):
413 402 """Reload the raw data from file or URL."""
414 403 if self.filename is not None:
415 404 with open(self.filename, self._read_flags) as f:
416 405 self.data = f.read()
417 406 elif self.url is not None:
418 407 try:
419 408 try:
420 409 from urllib.request import urlopen # Py3
421 410 except ImportError:
422 411 from urllib2 import urlopen
423 412 response = urlopen(self.url)
424 413 self.data = response.read()
425 414 # extract encoding from header, if there is one:
426 415 encoding = None
427 416 for sub in response.headers['content-type'].split(';'):
428 417 sub = sub.strip()
429 418 if sub.startswith('charset'):
430 419 encoding = sub.split('=')[-1].strip()
431 420 break
432 421 # decode data, if an encoding was specified
433 422 if encoding:
434 423 self.data = self.data.decode(encoding, 'replace')
435 424 except:
436 425 self.data = None
437 426
438 427 class TextDisplayObject(DisplayObject):
439 428 """Validate that display data is text"""
440 429 def _check_data(self):
441 430 if self.data is not None and not isinstance(self.data, string_types):
442 431 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
443 432
444 433 class Pretty(TextDisplayObject):
445 434
446 435 def _repr_pretty_(self):
447 436 return self.data
448 437
449 438
450 439 class HTML(TextDisplayObject):
451 440
452 441 def _repr_html_(self):
453 442 return self.data
454 443
455 444 def __html__(self):
456 445 """
457 446 This method exists to inform other HTML-using modules (e.g. Markupsafe,
458 447 htmltag, etc) that this object is HTML and does not need things like
459 448 special characters (<>&) escaped.
460 449 """
461 450 return self._repr_html_()
462 451
463 452
464 453 class Markdown(TextDisplayObject):
465 454
466 455 def _repr_markdown_(self):
467 456 return self.data
468 457
469 458
470 459 class Math(TextDisplayObject):
471 460
472 461 def _repr_latex_(self):
473 462 s = self.data.strip('$')
474 463 return "$$%s$$" % s
475 464
476 465
477 466 class Latex(TextDisplayObject):
478 467
479 468 def _repr_latex_(self):
480 469 return self.data
481 470
482 471
483 472 class SVG(DisplayObject):
484 473
485 474 # wrap data in a property, which extracts the <svg> tag, discarding
486 475 # document headers
487 476 _data = None
488 477
489 478 @property
490 479 def data(self):
491 480 return self._data
492 481
493 482 @data.setter
494 483 def data(self, svg):
495 484 if svg is None:
496 485 self._data = None
497 486 return
498 487 # parse into dom object
499 488 from xml.dom import minidom
500 489 svg = cast_bytes_py2(svg)
501 490 x = minidom.parseString(svg)
502 491 # get svg tag (should be 1)
503 492 found_svg = x.getElementsByTagName('svg')
504 493 if found_svg:
505 494 svg = found_svg[0].toxml()
506 495 else:
507 496 # fallback on the input, trust the user
508 497 # but this is probably an error.
509 498 pass
510 499 svg = cast_unicode(svg)
511 500 self._data = svg
512 501
513 502 def _repr_svg_(self):
514 503 return self.data
515 504
516 505
517 class JSON(TextDisplayObject):
506 class JSON(DisplayObject):
507 """JSON expects a JSON-able dict or list
508
509 not an already-serialized JSON string.
510
511 Scalar types (None, number, string) are not allowed, only dict or list containers.
512 """
513 # wrap data in a property, which warns about passing already-serialized JSON
514 _data = None
515 def _check_data(self):
516 if self.data is not None and not isinstance(self.data, (dict, list)):
517 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
518
519 @property
520 def data(self):
521 return self._data
522
523 @data.setter
524 def data(self, data):
525 if isinstance(data, string_types):
526 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
527 data = json.loads(data)
528 self._data = data
518 529
519 530 def _repr_json_(self):
520 531 return self.data
521 532
522 533 css_t = """$("head").append($("<link/>").attr({
523 534 rel: "stylesheet",
524 535 type: "text/css",
525 536 href: "%s"
526 537 }));
527 538 """
528 539
529 540 lib_t1 = """$.getScript("%s", function () {
530 541 """
531 542 lib_t2 = """});
532 543 """
533 544
534 545 class Javascript(TextDisplayObject):
535 546
536 547 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
537 548 """Create a Javascript display object given raw data.
538 549
539 550 When this object is returned by an expression or passed to the
540 551 display function, it will result in the data being displayed
541 552 in the frontend. If the data is a URL, the data will first be
542 553 downloaded and then displayed.
543 554
544 555 In the Notebook, the containing element will be available as `element`,
545 556 and jQuery will be available. Content appended to `element` will be
546 557 visible in the output area.
547 558
548 559 Parameters
549 560 ----------
550 561 data : unicode, str or bytes
551 562 The Javascript source code or a URL to download it from.
552 563 url : unicode
553 564 A URL to download the data from.
554 565 filename : unicode
555 566 Path to a local file to load the data from.
556 567 lib : list or str
557 568 A sequence of Javascript library URLs to load asynchronously before
558 569 running the source code. The full URLs of the libraries should
559 570 be given. A single Javascript library URL can also be given as a
560 571 string.
561 572 css: : list or str
562 573 A sequence of css files to load before running the source code.
563 574 The full URLs of the css files should be given. A single css URL
564 575 can also be given as a string.
565 576 """
566 577 if isinstance(lib, string_types):
567 578 lib = [lib]
568 579 elif lib is None:
569 580 lib = []
570 581 if isinstance(css, string_types):
571 582 css = [css]
572 583 elif css is None:
573 584 css = []
574 585 if not isinstance(lib, (list,tuple)):
575 586 raise TypeError('expected sequence, got: %r' % lib)
576 587 if not isinstance(css, (list,tuple)):
577 588 raise TypeError('expected sequence, got: %r' % css)
578 589 self.lib = lib
579 590 self.css = css
580 591 super(Javascript, self).__init__(data=data, url=url, filename=filename)
581 592
582 593 def _repr_javascript_(self):
583 594 r = ''
584 595 for c in self.css:
585 596 r += css_t % c
586 597 for l in self.lib:
587 598 r += lib_t1 % l
588 599 r += self.data
589 600 r += lib_t2*len(self.lib)
590 601 return r
591 602
592 603 # constants for identifying png/jpeg data
593 604 _PNG = b'\x89PNG\r\n\x1a\n'
594 605 _JPEG = b'\xff\xd8'
595 606
596 607 def _pngxy(data):
597 608 """read the (width, height) from a PNG header"""
598 609 ihdr = data.index(b'IHDR')
599 610 # next 8 bytes are width/height
600 611 w4h4 = data[ihdr+4:ihdr+12]
601 612 return struct.unpack('>ii', w4h4)
602 613
603 614 def _jpegxy(data):
604 615 """read the (width, height) from a JPEG header"""
605 616 # adapted from http://www.64lines.com/jpeg-width-height
606 617
607 618 idx = 4
608 619 while True:
609 620 block_size = struct.unpack('>H', data[idx:idx+2])[0]
610 621 idx = idx + block_size
611 622 if data[idx:idx+2] == b'\xFF\xC0':
612 623 # found Start of Frame
613 624 iSOF = idx
614 625 break
615 626 else:
616 627 # read another block
617 628 idx += 2
618 629
619 630 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
620 631 return w, h
621 632
622 633 class Image(DisplayObject):
623 634
624 635 _read_flags = 'rb'
625 636 _FMT_JPEG = u'jpeg'
626 637 _FMT_PNG = u'png'
627 638 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
628 639
629 640 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
630 641 """Create a PNG/JPEG image object given raw data.
631 642
632 643 When this object is returned by an input cell or passed to the
633 644 display function, it will result in the image being displayed
634 645 in the frontend.
635 646
636 647 Parameters
637 648 ----------
638 649 data : unicode, str or bytes
639 650 The raw image data or a URL or filename to load the data from.
640 651 This always results in embedded image data.
641 652 url : unicode
642 653 A URL to download the data from. If you specify `url=`,
643 654 the image data will not be embedded unless you also specify `embed=True`.
644 655 filename : unicode
645 656 Path to a local file to load the data from.
646 657 Images from a file are always embedded.
647 658 format : unicode
648 659 The format of the image data (png/jpeg/jpg). If a filename or URL is given
649 660 for format will be inferred from the filename extension.
650 661 embed : bool
651 662 Should the image data be embedded using a data URI (True) or be
652 663 loaded using an <img> tag. Set this to True if you want the image
653 664 to be viewable later with no internet connection in the notebook.
654 665
655 666 Default is `True`, unless the keyword argument `url` is set, then
656 667 default value is `False`.
657 668
658 669 Note that QtConsole is not able to display images if `embed` is set to `False`
659 670 width : int
660 671 Width to which to constrain the image in html
661 672 height : int
662 673 Height to which to constrain the image in html
663 674 retina : bool
664 675 Automatically set the width and height to half of the measured
665 676 width and height.
666 677 This only works for embedded images because it reads the width/height
667 678 from image data.
668 679 For non-embedded images, you can just set the desired display width
669 680 and height directly.
670 681
671 682 Examples
672 683 --------
673 684 # embedded image data, works in qtconsole and notebook
674 685 # when passed positionally, the first arg can be any of raw image data,
675 686 # a URL, or a filename from which to load image data.
676 687 # The result is always embedding image data for inline images.
677 688 Image('http://www.google.fr/images/srpr/logo3w.png')
678 689 Image('/path/to/image.jpg')
679 690 Image(b'RAW_PNG_DATA...')
680 691
681 692 # Specifying Image(url=...) does not embed the image data,
682 693 # it only generates `<img>` tag with a link to the source.
683 694 # This will not work in the qtconsole or offline.
684 695 Image(url='http://www.google.fr/images/srpr/logo3w.png')
685 696
686 697 """
687 698 if filename is not None:
688 699 ext = self._find_ext(filename)
689 700 elif url is not None:
690 701 ext = self._find_ext(url)
691 702 elif data is None:
692 703 raise ValueError("No image data found. Expecting filename, url, or data.")
693 704 elif isinstance(data, string_types) and (
694 705 data.startswith('http') or _safe_exists(data)
695 706 ):
696 707 ext = self._find_ext(data)
697 708 else:
698 709 ext = None
699 710
700 711 if ext is not None:
701 712 format = ext.lower()
702 713 if ext == u'jpg' or ext == u'jpeg':
703 714 format = self._FMT_JPEG
704 715 if ext == u'png':
705 716 format = self._FMT_PNG
706 717 elif isinstance(data, bytes) and format == 'png':
707 718 # infer image type from image data header,
708 719 # only if format might not have been specified.
709 720 if data[:2] == _JPEG:
710 721 format = 'jpeg'
711 722
712 723 self.format = unicode_type(format).lower()
713 724 self.embed = embed if embed is not None else (url is None)
714 725
715 726 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
716 727 raise ValueError("Cannot embed the '%s' image format" % (self.format))
717 728 self.width = width
718 729 self.height = height
719 730 self.retina = retina
720 731 super(Image, self).__init__(data=data, url=url, filename=filename)
721 732
722 733 if retina:
723 734 self._retina_shape()
724 735
725 736 def _retina_shape(self):
726 737 """load pixel-doubled width and height from image data"""
727 738 if not self.embed:
728 739 return
729 740 if self.format == 'png':
730 741 w, h = _pngxy(self.data)
731 742 elif self.format == 'jpeg':
732 743 w, h = _jpegxy(self.data)
733 744 else:
734 745 # retina only supports png
735 746 return
736 747 self.width = w // 2
737 748 self.height = h // 2
738 749
739 750 def reload(self):
740 751 """Reload the raw data from file or URL."""
741 752 if self.embed:
742 753 super(Image,self).reload()
743 754 if self.retina:
744 755 self._retina_shape()
745 756
746 757 def _repr_html_(self):
747 758 if not self.embed:
748 759 width = height = ''
749 760 if self.width:
750 761 width = ' width="%d"' % self.width
751 762 if self.height:
752 763 height = ' height="%d"' % self.height
753 764 return u'<img src="%s"%s%s/>' % (self.url, width, height)
754 765
755 766 def _data_and_metadata(self):
756 767 """shortcut for returning metadata with shape information, if defined"""
757 768 md = {}
758 769 if self.width:
759 770 md['width'] = self.width
760 771 if self.height:
761 772 md['height'] = self.height
762 773 if md:
763 774 return self.data, md
764 775 else:
765 776 return self.data
766 777
767 778 def _repr_png_(self):
768 779 if self.embed and self.format == u'png':
769 780 return self._data_and_metadata()
770 781
771 782 def _repr_jpeg_(self):
772 783 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
773 784 return self._data_and_metadata()
774 785
775 786 def _find_ext(self, s):
776 787 return unicode_type(s.split('.')[-1].lower())
777 788
778 789 class Video(DisplayObject):
779 790
780 791 def __init__(self, data=None, url=None, filename=None, embed=None, mimetype=None):
781 792 """Create a video object given raw data or an URL.
782 793
783 794 When this object is returned by an input cell or passed to the
784 795 display function, it will result in the video being displayed
785 796 in the frontend.
786 797
787 798 Parameters
788 799 ----------
789 800 data : unicode, str or bytes
790 801 The raw image data or a URL or filename to load the data from.
791 802 This always results in embedded image data.
792 803 url : unicode
793 804 A URL to download the data from. If you specify `url=`,
794 805 the image data will not be embedded unless you also specify `embed=True`.
795 806 filename : unicode
796 807 Path to a local file to load the data from.
797 808 Videos from a file are always embedded.
798 809 embed : bool
799 810 Should the image data be embedded using a data URI (True) or be
800 811 loaded using an <img> tag. Set this to True if you want the image
801 812 to be viewable later with no internet connection in the notebook.
802 813
803 814 Default is `True`, unless the keyword argument `url` is set, then
804 815 default value is `False`.
805 816
806 817 Note that QtConsole is not able to display images if `embed` is set to `False`
807 818 mimetype: unicode
808 819 Specify the mimetype in case you load in a encoded video.
809 820 Examples
810 821 --------
811 822 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
812 823 Video('path/to/video.mp4')
813 824 Video('path/to/video.mp4', embed=False)
814 825 """
815 826 if url is None and (data.startswith('http') or data.startswith('https')):
816 827 url = data
817 828 data = None
818 829 embed = False
819 830 elif os.path.exists(data):
820 831 filename = data
821 832 data = None
822 833
823 834 self.mimetype = mimetype
824 835 self.embed = embed if embed is not None else (filename is not None)
825 836 super(Video, self).__init__(data=data, url=url, filename=filename)
826 837
827 838 def _repr_html_(self):
828 839 # External URLs and potentially local files are not embedded into the
829 840 # notebook output.
830 841 if not self.embed:
831 842 url = self.url if self.url is not None else self.filename
832 843 output = """<video src="{0}" controls>
833 844 Your browser does not support the <code>video</code> element.
834 845 </video>""".format(url)
835 846 return output
836 847 # Embedded videos uses base64 encoded videos.
837 848 if self.filename is not None:
838 849 mimetypes.init()
839 850 mimetype, encoding = mimetypes.guess_type(self.filename)
840 851
841 852 video = open(self.filename, 'rb').read()
842 853 video_encoded = video.encode('base64')
843 854 else:
844 855 video_encoded = self.data
845 856 mimetype = self.mimetype
846 857 output = """<video controls>
847 858 <source src="data:{0};base64,{1}" type="{0}">
848 859 Your browser does not support the video tag.
849 860 </video>""".format(mimetype, video_encoded)
850 861 return output
851 862
852 863 def reload(self):
853 864 # TODO
854 865 pass
855 866
856 867 def _repr_png_(self):
857 868 # TODO
858 869 pass
859 870 def _repr_jpeg_(self):
860 871 # TODO
861 872 pass
862 873
863 874 def clear_output(wait=False):
864 875 """Clear the output of the current cell receiving output.
865 876
866 877 Parameters
867 878 ----------
868 879 wait : bool [default: false]
869 880 Wait to clear the output until new output is available to replace it."""
870 881 from IPython.core.interactiveshell import InteractiveShell
871 882 if InteractiveShell.initialized():
872 883 InteractiveShell.instance().display_pub.clear_output(wait)
873 884 else:
874 885 from IPython.utils import io
875 886 print('\033[2K\r', file=io.stdout, end='')
876 887 io.stdout.flush()
877 888 print('\033[2K\r', file=io.stderr, end='')
878 889 io.stderr.flush()
879 890
880 891
881 892 @skip_doctest
882 893 def set_matplotlib_formats(*formats, **kwargs):
883 894 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
884 895
885 896 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
886 897
887 898 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
888 899
889 900 To set this in your config files use the following::
890 901
891 902 c.InlineBackend.figure_formats = {'png', 'jpeg'}
892 903 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
893 904
894 905 Parameters
895 906 ----------
896 907 *formats : strs
897 908 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
898 909 **kwargs :
899 910 Keyword args will be relayed to ``figure.canvas.print_figure``.
900 911 """
901 912 from IPython.core.interactiveshell import InteractiveShell
902 913 from IPython.core.pylabtools import select_figure_formats
903 914 from IPython.kernel.zmq.pylab.config import InlineBackend
904 915 # build kwargs, starting with InlineBackend config
905 916 kw = {}
906 917 cfg = InlineBackend.instance()
907 918 kw.update(cfg.print_figure_kwargs)
908 919 kw.update(**kwargs)
909 920 shell = InteractiveShell.instance()
910 921 select_figure_formats(shell, formats, **kw)
911 922
912 923 @skip_doctest
913 924 def set_matplotlib_close(close=True):
914 925 """Set whether the inline backend closes all figures automatically or not.
915 926
916 927 By default, the inline backend used in the IPython Notebook will close all
917 928 matplotlib figures automatically after each cell is run. This means that
918 929 plots in different cells won't interfere. Sometimes, you may want to make
919 930 a plot in one cell and then refine it in later cells. This can be accomplished
920 931 by::
921 932
922 933 In [1]: set_matplotlib_close(False)
923 934
924 935 To set this in your config files use the following::
925 936
926 937 c.InlineBackend.close_figures = False
927 938
928 939 Parameters
929 940 ----------
930 941 close : bool
931 942 Should all matplotlib figures be automatically closed after each cell is
932 943 run?
933 944 """
934 945 from IPython.kernel.zmq.pylab.config import InlineBackend
935 946 cfg = InlineBackend.instance()
936 947 cfg.close_figures = close
937 948
@@ -1,938 +1,970 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Display formatters.
3 3
4 4 Inheritance diagram:
5 5
6 6 .. inheritance-diagram:: IPython.core.formatters
7 7 :parts: 3
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 import abc
14 14 import inspect
15 import json
15 16 import sys
16 17 import traceback
17 18 import warnings
18 19
19 20 from IPython.external.decorator import decorator
20 21
21 22 from IPython.config.configurable import Configurable
22 23 from IPython.core.getipython import get_ipython
23 24 from IPython.lib import pretty
24 25 from IPython.utils.traitlets import (
25 26 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
26 27 ForwardDeclaredInstance,
27 28 )
28 29 from IPython.utils.py3compat import (
29 30 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
30 31 )
31 32
32 33 if PY3:
33 34 from io import StringIO
34 35 else:
35 36 from StringIO import StringIO
36 37
37 38
38 39 #-----------------------------------------------------------------------------
39 40 # The main DisplayFormatter class
40 41 #-----------------------------------------------------------------------------
41 42
42 43
43 44 def _safe_get_formatter_method(obj, name):
44 45 """Safely get a formatter method
45 46
46 47 - Classes cannot have formatter methods, only instance
47 48 - protect against proxy objects that claim to have everything
48 49 """
49 50 if inspect.isclass(obj):
50 51 # repr methods only make sense on instances, not classes
51 52 return None
52 53 method = pretty._safe_getattr(obj, name, None)
53 54 if callable(method):
54 55 # obj claims to have repr method...
55 56 if callable(pretty._safe_getattr(obj, '_ipython_canary_method_should_not_exist_', None)):
56 57 # ...but don't trust proxy objects that claim to have everything
57 58 return None
58 59 return method
59 60
60 61
61 62 class DisplayFormatter(Configurable):
62 63
63 64 # When set to true only the default plain text formatter will be used.
64 65 plain_text_only = Bool(False, config=True)
65 66 def _plain_text_only_changed(self, name, old, new):
66 67 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
67 68
68 69 Use DisplayFormatter.active_types = ['text/plain']
69 70 for the same effect.
70 71 """, DeprecationWarning)
71 72 if new:
72 73 self.active_types = ['text/plain']
73 74 else:
74 75 self.active_types = self.format_types
75 76
76 77 active_types = List(Unicode, config=True,
77 78 help="""List of currently active mime-types to display.
78 79 You can use this to set a white-list for formats to display.
79 80
80 81 Most users will not need to change this value.
81 82 """)
82 83 def _active_types_default(self):
83 84 return self.format_types
84 85
85 86 def _active_types_changed(self, name, old, new):
86 87 for key, formatter in self.formatters.items():
87 88 if key in new:
88 89 formatter.enabled = True
89 90 else:
90 91 formatter.enabled = False
91 92
92 93 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
93 94 def _ipython_display_formatter_default(self):
94 95 return IPythonDisplayFormatter(parent=self)
95 96
96 97 # A dict of formatter whose keys are format types (MIME types) and whose
97 98 # values are subclasses of BaseFormatter.
98 99 formatters = Dict()
99 100 def _formatters_default(self):
100 101 """Activate the default formatters."""
101 102 formatter_classes = [
102 103 PlainTextFormatter,
103 104 HTMLFormatter,
104 105 MarkdownFormatter,
105 106 SVGFormatter,
106 107 PNGFormatter,
107 108 PDFFormatter,
108 109 JPEGFormatter,
109 110 LatexFormatter,
110 111 JSONFormatter,
111 112 JavascriptFormatter
112 113 ]
113 114 d = {}
114 115 for cls in formatter_classes:
115 116 f = cls(parent=self)
116 117 d[f.format_type] = f
117 118 return d
118 119
119 120 def format(self, obj, include=None, exclude=None):
120 121 """Return a format data dict for an object.
121 122
122 123 By default all format types will be computed.
123 124
124 125 The following MIME types are currently implemented:
125 126
126 127 * text/plain
127 128 * text/html
128 129 * text/markdown
129 130 * text/latex
130 131 * application/json
131 132 * application/javascript
132 133 * application/pdf
133 134 * image/png
134 135 * image/jpeg
135 136 * image/svg+xml
136 137
137 138 Parameters
138 139 ----------
139 140 obj : object
140 141 The Python object whose format data will be computed.
141 142 include : list or tuple, optional
142 143 A list of format type strings (MIME types) to include in the
143 144 format data dict. If this is set *only* the format types included
144 145 in this list will be computed.
145 146 exclude : list or tuple, optional
146 147 A list of format type string (MIME types) to exclude in the format
147 148 data dict. If this is set all format types will be computed,
148 149 except for those included in this argument.
149 150
150 151 Returns
151 152 -------
152 153 (format_dict, metadata_dict) : tuple of two dicts
153 154
154 155 format_dict is a dictionary of key/value pairs, one of each format that was
155 156 generated for the object. The keys are the format types, which
156 157 will usually be MIME type strings and the values and JSON'able
157 158 data structure containing the raw data for the representation in
158 159 that format.
159 160
160 161 metadata_dict is a dictionary of metadata about each mime-type output.
161 162 Its keys will be a strict subset of the keys in format_dict.
162 163 """
163 164 format_dict = {}
164 165 md_dict = {}
165 166
166 167 if self.ipython_display_formatter(obj):
167 168 # object handled itself, don't proceed
168 169 return {}, {}
169 170
170 171 for format_type, formatter in self.formatters.items():
171 172 if include and format_type not in include:
172 173 continue
173 174 if exclude and format_type in exclude:
174 175 continue
175 176
176 177 md = None
177 178 try:
178 179 data = formatter(obj)
179 180 except:
180 181 # FIXME: log the exception
181 182 raise
182 183
183 184 # formatters can return raw data or (data, metadata)
184 185 if isinstance(data, tuple) and len(data) == 2:
185 186 data, md = data
186 187
187 188 if data is not None:
188 189 format_dict[format_type] = data
189 190 if md is not None:
190 191 md_dict[format_type] = md
191 192
192 193 return format_dict, md_dict
193 194
194 195 @property
195 196 def format_types(self):
196 197 """Return the format types (MIME types) of the active formatters."""
197 198 return list(self.formatters.keys())
198 199
199 200
200 201 #-----------------------------------------------------------------------------
201 202 # Formatters for specific format types (text, html, svg, etc.)
202 203 #-----------------------------------------------------------------------------
203 204
204 205
205 206 def _safe_repr(obj):
206 207 """Try to return a repr of an object
207 208
208 209 always returns a string, at least.
209 210 """
210 211 try:
211 212 return repr(obj)
212 213 except Exception as e:
213 214 return "un-repr-able object (%r)" % e
214 215
215 216
216 217 class FormatterWarning(UserWarning):
217 218 """Warning class for errors in formatters"""
218 219
219 220 @decorator
220 221 def warn_format_error(method, self, *args, **kwargs):
221 222 """decorator for warning on failed format call"""
222 223 try:
223 224 r = method(self, *args, **kwargs)
224 225 except NotImplementedError:
225 226 # don't warn on NotImplementedErrors
226 227 return None
227 228 except Exception:
228 229 exc_info = sys.exc_info()
229 230 ip = get_ipython()
230 231 if ip is not None:
231 232 ip.showtraceback(exc_info)
232 233 else:
233 234 traceback.print_exception(*exc_info)
234 235 return None
235 if r is None or isinstance(r, self._return_type) or \
236 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
237 return r
238 else:
239 warnings.warn(
240 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
241 (self.format_type, type(r), self._return_type, _safe_repr(args[0])),
242 FormatterWarning
243 )
236 return self._check_return(r, args[0])
244 237
245 238
246 239 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
247 240 """ Abstract base class for Formatters.
248 241
249 242 A formatter is a callable class that is responsible for computing the
250 243 raw format data for a particular format type (MIME type). For example,
251 244 an HTML formatter would have a format type of `text/html` and would return
252 245 the HTML representation of the object when called.
253 246 """
254 247
255 248 # The format type of the data returned, usually a MIME type.
256 249 format_type = 'text/plain'
257 250
258 251 # Is the formatter enabled...
259 252 enabled = True
260 253
261 254 @abc.abstractmethod
262 @warn_format_error
263 255 def __call__(self, obj):
264 256 """Return a JSON'able representation of the object.
265 257
266 258 If the object cannot be formatted by this formatter,
267 259 warn and return None.
268 260 """
269 261 return repr(obj)
270 262
271 263
272 264 def _mod_name_key(typ):
273 265 """Return a (__module__, __name__) tuple for a type.
274 266
275 267 Used as key in Formatter.deferred_printers.
276 268 """
277 269 module = getattr(typ, '__module__', None)
278 270 name = getattr(typ, '__name__', None)
279 271 return (module, name)
280 272
281 273
282 274 def _get_type(obj):
283 275 """Return the type of an instance (old and new-style)"""
284 276 return getattr(obj, '__class__', None) or type(obj)
285 277
286 278 _raise_key_error = object()
287 279
288 280
289 281 class BaseFormatter(Configurable):
290 282 """A base formatter class that is configurable.
291 283
292 284 This formatter should usually be used as the base class of all formatters.
293 285 It is a traited :class:`Configurable` class and includes an extensible
294 286 API for users to determine how their objects are formatted. The following
295 287 logic is used to find a function to format an given object.
296 288
297 289 1. The object is introspected to see if it has a method with the name
298 290 :attr:`print_method`. If is does, that object is passed to that method
299 291 for formatting.
300 292 2. If no print method is found, three internal dictionaries are consulted
301 293 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
302 294 and :attr:`deferred_printers`.
303 295
304 296 Users should use these dictionaries to register functions that will be
305 297 used to compute the format data for their objects (if those objects don't
306 298 have the special print methods). The easiest way of using these
307 299 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
308 300 methods.
309 301
310 302 If no function/callable is found to compute the format data, ``None`` is
311 303 returned and this format type is not used.
312 304 """
313 305
314 306 format_type = Unicode('text/plain')
315 307 _return_type = string_types
316 308
317 309 enabled = Bool(True, config=True)
318 310
319 311 print_method = ObjectName('__repr__')
320 312
321 313 # The singleton printers.
322 314 # Maps the IDs of the builtin singleton objects to the format functions.
323 315 singleton_printers = Dict(config=True)
324 316
325 317 # The type-specific printers.
326 318 # Map type objects to the format functions.
327 319 type_printers = Dict(config=True)
328 320
329 321 # The deferred-import type-specific printers.
330 322 # Map (modulename, classname) pairs to the format functions.
331 323 deferred_printers = Dict(config=True)
332 324
333 325 @warn_format_error
334 326 def __call__(self, obj):
335 327 """Compute the format for an object."""
336 328 if self.enabled:
337 329 # lookup registered printer
338 330 try:
339 331 printer = self.lookup(obj)
340 332 except KeyError:
341 333 pass
342 334 else:
343 335 return printer(obj)
344 336 # Finally look for special method names
345 337 method = _safe_get_formatter_method(obj, self.print_method)
346 338 if method is not None:
347 339 return method()
348 340 return None
349 341 else:
350 342 return None
351 343
352 344 def __contains__(self, typ):
353 345 """map in to lookup_by_type"""
354 346 try:
355 347 self.lookup_by_type(typ)
356 348 except KeyError:
357 349 return False
358 350 else:
359 351 return True
360 352
353 def _check_return(self, r, obj):
354 """Check that a return value is appropriate
355
356 Return the value if so, None otherwise, warning if invalid.
357 """
358 if r is None or isinstance(r, self._return_type) or \
359 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
360 return r
361 else:
362 warnings.warn(
363 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
364 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
365 FormatterWarning
366 )
367
361 368 def lookup(self, obj):
362 369 """Look up the formatter for a given instance.
363 370
364 371 Parameters
365 372 ----------
366 373 obj : object instance
367 374
368 375 Returns
369 376 -------
370 377 f : callable
371 378 The registered formatting callable for the type.
372 379
373 380 Raises
374 381 ------
375 382 KeyError if the type has not been registered.
376 383 """
377 384 # look for singleton first
378 385 obj_id = id(obj)
379 386 if obj_id in self.singleton_printers:
380 387 return self.singleton_printers[obj_id]
381 388 # then lookup by type
382 389 return self.lookup_by_type(_get_type(obj))
383 390
384 391 def lookup_by_type(self, typ):
385 392 """Look up the registered formatter for a type.
386 393
387 394 Parameters
388 395 ----------
389 396 typ : type or '__module__.__name__' string for a type
390 397
391 398 Returns
392 399 -------
393 400 f : callable
394 401 The registered formatting callable for the type.
395 402
396 403 Raises
397 404 ------
398 405 KeyError if the type has not been registered.
399 406 """
400 407 if isinstance(typ, string_types):
401 408 typ_key = tuple(typ.rsplit('.',1))
402 409 if typ_key not in self.deferred_printers:
403 410 # We may have it cached in the type map. We will have to
404 411 # iterate over all of the types to check.
405 412 for cls in self.type_printers:
406 413 if _mod_name_key(cls) == typ_key:
407 414 return self.type_printers[cls]
408 415 else:
409 416 return self.deferred_printers[typ_key]
410 417 else:
411 418 for cls in pretty._get_mro(typ):
412 419 if cls in self.type_printers or self._in_deferred_types(cls):
413 420 return self.type_printers[cls]
414 421
415 422 # If we have reached here, the lookup failed.
416 423 raise KeyError("No registered printer for {0!r}".format(typ))
417 424
418 425 def for_type(self, typ, func=None):
419 426 """Add a format function for a given type.
420 427
421 428 Parameters
422 429 -----------
423 430 typ : type or '__module__.__name__' string for a type
424 431 The class of the object that will be formatted using `func`.
425 432 func : callable
426 433 A callable for computing the format data.
427 434 `func` will be called with the object to be formatted,
428 435 and will return the raw data in this formatter's format.
429 436 Subclasses may use a different call signature for the
430 437 `func` argument.
431 438
432 439 If `func` is None or not specified, there will be no change,
433 440 only returning the current value.
434 441
435 442 Returns
436 443 -------
437 444 oldfunc : callable
438 445 The currently registered callable.
439 446 If you are registering a new formatter,
440 447 this will be the previous value (to enable restoring later).
441 448 """
442 449 # if string given, interpret as 'pkg.module.class_name'
443 450 if isinstance(typ, string_types):
444 451 type_module, type_name = typ.rsplit('.', 1)
445 452 return self.for_type_by_name(type_module, type_name, func)
446 453
447 454 try:
448 455 oldfunc = self.lookup_by_type(typ)
449 456 except KeyError:
450 457 oldfunc = None
451 458
452 459 if func is not None:
453 460 self.type_printers[typ] = func
454 461
455 462 return oldfunc
456 463
457 464 def for_type_by_name(self, type_module, type_name, func=None):
458 465 """Add a format function for a type specified by the full dotted
459 466 module and name of the type, rather than the type of the object.
460 467
461 468 Parameters
462 469 ----------
463 470 type_module : str
464 471 The full dotted name of the module the type is defined in, like
465 472 ``numpy``.
466 473 type_name : str
467 474 The name of the type (the class name), like ``dtype``
468 475 func : callable
469 476 A callable for computing the format data.
470 477 `func` will be called with the object to be formatted,
471 478 and will return the raw data in this formatter's format.
472 479 Subclasses may use a different call signature for the
473 480 `func` argument.
474 481
475 482 If `func` is None or unspecified, there will be no change,
476 483 only returning the current value.
477 484
478 485 Returns
479 486 -------
480 487 oldfunc : callable
481 488 The currently registered callable.
482 489 If you are registering a new formatter,
483 490 this will be the previous value (to enable restoring later).
484 491 """
485 492 key = (type_module, type_name)
486 493
487 494 try:
488 495 oldfunc = self.lookup_by_type("%s.%s" % key)
489 496 except KeyError:
490 497 oldfunc = None
491 498
492 499 if func is not None:
493 500 self.deferred_printers[key] = func
494 501 return oldfunc
495 502
496 503 def pop(self, typ, default=_raise_key_error):
497 504 """Pop a formatter for the given type.
498 505
499 506 Parameters
500 507 ----------
501 508 typ : type or '__module__.__name__' string for a type
502 509 default : object
503 510 value to be returned if no formatter is registered for typ.
504 511
505 512 Returns
506 513 -------
507 514 obj : object
508 515 The last registered object for the type.
509 516
510 517 Raises
511 518 ------
512 519 KeyError if the type is not registered and default is not specified.
513 520 """
514 521
515 522 if isinstance(typ, string_types):
516 523 typ_key = tuple(typ.rsplit('.',1))
517 524 if typ_key not in self.deferred_printers:
518 525 # We may have it cached in the type map. We will have to
519 526 # iterate over all of the types to check.
520 527 for cls in self.type_printers:
521 528 if _mod_name_key(cls) == typ_key:
522 529 old = self.type_printers.pop(cls)
523 530 break
524 531 else:
525 532 old = default
526 533 else:
527 534 old = self.deferred_printers.pop(typ_key)
528 535 else:
529 536 if typ in self.type_printers:
530 537 old = self.type_printers.pop(typ)
531 538 else:
532 539 old = self.deferred_printers.pop(_mod_name_key(typ), default)
533 540 if old is _raise_key_error:
534 541 raise KeyError("No registered value for {0!r}".format(typ))
535 542 return old
536 543
537 544 def _in_deferred_types(self, cls):
538 545 """
539 546 Check if the given class is specified in the deferred type registry.
540 547
541 548 Successful matches will be moved to the regular type registry for future use.
542 549 """
543 550 mod = getattr(cls, '__module__', None)
544 551 name = getattr(cls, '__name__', None)
545 552 key = (mod, name)
546 553 if key in self.deferred_printers:
547 554 # Move the printer over to the regular registry.
548 555 printer = self.deferred_printers.pop(key)
549 556 self.type_printers[cls] = printer
550 557 return True
551 558 return False
552 559
553 560
554 561 class PlainTextFormatter(BaseFormatter):
555 562 """The default pretty-printer.
556 563
557 564 This uses :mod:`IPython.lib.pretty` to compute the format data of
558 565 the object. If the object cannot be pretty printed, :func:`repr` is used.
559 566 See the documentation of :mod:`IPython.lib.pretty` for details on
560 567 how to write pretty printers. Here is a simple example::
561 568
562 569 def dtype_pprinter(obj, p, cycle):
563 570 if cycle:
564 571 return p.text('dtype(...)')
565 572 if hasattr(obj, 'fields'):
566 573 if obj.fields is None:
567 574 p.text(repr(obj))
568 575 else:
569 576 p.begin_group(7, 'dtype([')
570 577 for i, field in enumerate(obj.descr):
571 578 if i > 0:
572 579 p.text(',')
573 580 p.breakable()
574 581 p.pretty(field)
575 582 p.end_group(7, '])')
576 583 """
577 584
578 585 # The format type of data returned.
579 586 format_type = Unicode('text/plain')
580 587
581 588 # This subclass ignores this attribute as it always need to return
582 589 # something.
583 590 enabled = Bool(True, config=False)
584 591
585 592 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, config=True,
586 593 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
587 594
588 595 Set to 0 to disable truncation.
589 596 """
590 597 )
591 598
592 599 # Look for a _repr_pretty_ methods to use for pretty printing.
593 600 print_method = ObjectName('_repr_pretty_')
594 601
595 602 # Whether to pretty-print or not.
596 603 pprint = Bool(True, config=True)
597 604
598 605 # Whether to be verbose or not.
599 606 verbose = Bool(False, config=True)
600 607
601 608 # The maximum width.
602 609 max_width = Integer(79, config=True)
603 610
604 611 # The newline character.
605 612 newline = Unicode('\n', config=True)
606 613
607 614 # format-string for pprinting floats
608 615 float_format = Unicode('%r')
609 616 # setter for float precision, either int or direct format-string
610 617 float_precision = CUnicode('', config=True)
611 618
612 619 def _float_precision_changed(self, name, old, new):
613 620 """float_precision changed, set float_format accordingly.
614 621
615 622 float_precision can be set by int or str.
616 623 This will set float_format, after interpreting input.
617 624 If numpy has been imported, numpy print precision will also be set.
618 625
619 626 integer `n` sets format to '%.nf', otherwise, format set directly.
620 627
621 628 An empty string returns to defaults (repr for float, 8 for numpy).
622 629
623 630 This parameter can be set via the '%precision' magic.
624 631 """
625 632
626 633 if '%' in new:
627 634 # got explicit format string
628 635 fmt = new
629 636 try:
630 637 fmt%3.14159
631 638 except Exception:
632 639 raise ValueError("Precision must be int or format string, not %r"%new)
633 640 elif new:
634 641 # otherwise, should be an int
635 642 try:
636 643 i = int(new)
637 644 assert i >= 0
638 645 except ValueError:
639 646 raise ValueError("Precision must be int or format string, not %r"%new)
640 647 except AssertionError:
641 648 raise ValueError("int precision must be non-negative, not %r"%i)
642 649
643 650 fmt = '%%.%if'%i
644 651 if 'numpy' in sys.modules:
645 652 # set numpy precision if it has been imported
646 653 import numpy
647 654 numpy.set_printoptions(precision=i)
648 655 else:
649 656 # default back to repr
650 657 fmt = '%r'
651 658 if 'numpy' in sys.modules:
652 659 import numpy
653 660 # numpy default is 8
654 661 numpy.set_printoptions(precision=8)
655 662 self.float_format = fmt
656 663
657 664 # Use the default pretty printers from IPython.lib.pretty.
658 665 def _singleton_printers_default(self):
659 666 return pretty._singleton_pprinters.copy()
660 667
661 668 def _type_printers_default(self):
662 669 d = pretty._type_pprinters.copy()
663 670 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
664 671 return d
665 672
666 673 def _deferred_printers_default(self):
667 674 return pretty._deferred_type_pprinters.copy()
668 675
669 676 #### FormatterABC interface ####
670 677
671 678 @warn_format_error
672 679 def __call__(self, obj):
673 680 """Compute the pretty representation of the object."""
674 681 if not self.pprint:
675 682 return repr(obj)
676 683 else:
677 684 # This uses use StringIO, as cStringIO doesn't handle unicode.
678 685 stream = StringIO()
679 686 # self.newline.encode() is a quick fix for issue gh-597. We need to
680 687 # ensure that stream does not get a mix of unicode and bytestrings,
681 688 # or it will cause trouble.
682 689 printer = pretty.RepresentationPrinter(stream, self.verbose,
683 690 self.max_width, unicode_to_str(self.newline),
684 691 max_seq_length=self.max_seq_length,
685 692 singleton_pprinters=self.singleton_printers,
686 693 type_pprinters=self.type_printers,
687 694 deferred_pprinters=self.deferred_printers)
688 695 printer.pretty(obj)
689 696 printer.flush()
690 697 return stream.getvalue()
691 698
692 699
693 700 class HTMLFormatter(BaseFormatter):
694 701 """An HTML formatter.
695 702
696 703 To define the callables that compute the HTML representation of your
697 704 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
698 705 or :meth:`for_type_by_name` methods to register functions that handle
699 706 this.
700 707
701 708 The return value of this formatter should be a valid HTML snippet that
702 709 could be injected into an existing DOM. It should *not* include the
703 710 ```<html>`` or ```<body>`` tags.
704 711 """
705 712 format_type = Unicode('text/html')
706 713
707 714 print_method = ObjectName('_repr_html_')
708 715
709 716
710 717 class MarkdownFormatter(BaseFormatter):
711 718 """A Markdown formatter.
712 719
713 720 To define the callables that compute the Markdown representation of your
714 721 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
715 722 or :meth:`for_type_by_name` methods to register functions that handle
716 723 this.
717 724
718 725 The return value of this formatter should be a valid Markdown.
719 726 """
720 727 format_type = Unicode('text/markdown')
721 728
722 729 print_method = ObjectName('_repr_markdown_')
723 730
724 731 class SVGFormatter(BaseFormatter):
725 732 """An SVG formatter.
726 733
727 734 To define the callables that compute the SVG representation of your
728 735 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
729 736 or :meth:`for_type_by_name` methods to register functions that handle
730 737 this.
731 738
732 739 The return value of this formatter should be valid SVG enclosed in
733 740 ```<svg>``` tags, that could be injected into an existing DOM. It should
734 741 *not* include the ```<html>`` or ```<body>`` tags.
735 742 """
736 743 format_type = Unicode('image/svg+xml')
737 744
738 745 print_method = ObjectName('_repr_svg_')
739 746
740 747
741 748 class PNGFormatter(BaseFormatter):
742 749 """A PNG formatter.
743 750
744 751 To define the callables that compute the PNG representation of your
745 752 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
746 753 or :meth:`for_type_by_name` methods to register functions that handle
747 754 this.
748 755
749 756 The return value of this formatter should be raw PNG data, *not*
750 757 base64 encoded.
751 758 """
752 759 format_type = Unicode('image/png')
753 760
754 761 print_method = ObjectName('_repr_png_')
755 762
756 763 _return_type = (bytes, unicode_type)
757 764
758 765
759 766 class JPEGFormatter(BaseFormatter):
760 767 """A JPEG formatter.
761 768
762 769 To define the callables that compute the JPEG representation of your
763 770 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
764 771 or :meth:`for_type_by_name` methods to register functions that handle
765 772 this.
766 773
767 774 The return value of this formatter should be raw JPEG data, *not*
768 775 base64 encoded.
769 776 """
770 777 format_type = Unicode('image/jpeg')
771 778
772 779 print_method = ObjectName('_repr_jpeg_')
773 780
774 781 _return_type = (bytes, unicode_type)
775 782
776 783
777 784 class LatexFormatter(BaseFormatter):
778 785 """A LaTeX formatter.
779 786
780 787 To define the callables that compute the LaTeX representation of your
781 788 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
782 789 or :meth:`for_type_by_name` methods to register functions that handle
783 790 this.
784 791
785 792 The return value of this formatter should be a valid LaTeX equation,
786 793 enclosed in either ```$```, ```$$``` or another LaTeX equation
787 794 environment.
788 795 """
789 796 format_type = Unicode('text/latex')
790 797
791 798 print_method = ObjectName('_repr_latex_')
792 799
793 800
794 801 class JSONFormatter(BaseFormatter):
795 802 """A JSON string formatter.
796 803
797 To define the callables that compute the JSON string representation of
804 To define the callables that compute the JSONable representation of
798 805 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
799 806 or :meth:`for_type_by_name` methods to register functions that handle
800 807 this.
801 808
802 The return value of this formatter should be a valid JSON string.
809 The return value of this formatter should be a JSONable list or dict.
810 JSON scalars (None, number, string) are not allowed, only dict or list containers.
803 811 """
804 812 format_type = Unicode('application/json')
813 _return_type = (list, dict)
805 814
806 815 print_method = ObjectName('_repr_json_')
816
817 def _check_return(self, r, obj):
818 """Check that a return value is appropriate
819
820 Return the value if so, None otherwise, warning if invalid.
821 """
822 if r is None:
823 return
824 md = None
825 if isinstance(r, tuple):
826 # unpack data, metadata tuple for type checking on first element
827 r, md = r
828
829 # handle deprecated JSON-as-string form from IPython < 3
830 if isinstance(r, string_types):
831 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
832 FormatterWarning)
833 r = json.loads(r)
834
835 if md is not None:
836 # put the tuple back together
837 r = (r, md)
838 return super(JSONFormatter, self)._check_return(r, obj)
807 839
808 840
809 841 class JavascriptFormatter(BaseFormatter):
810 842 """A Javascript formatter.
811 843
812 844 To define the callables that compute the Javascript representation of
813 845 your objects, define a :meth:`_repr_javascript_` method or use the
814 846 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
815 847 that handle this.
816 848
817 849 The return value of this formatter should be valid Javascript code and
818 850 should *not* be enclosed in ```<script>``` tags.
819 851 """
820 852 format_type = Unicode('application/javascript')
821 853
822 854 print_method = ObjectName('_repr_javascript_')
823 855
824 856
825 857 class PDFFormatter(BaseFormatter):
826 858 """A PDF formatter.
827 859
828 860 To define the callables that compute the PDF representation of your
829 861 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
830 862 or :meth:`for_type_by_name` methods to register functions that handle
831 863 this.
832 864
833 865 The return value of this formatter should be raw PDF data, *not*
834 866 base64 encoded.
835 867 """
836 868 format_type = Unicode('application/pdf')
837 869
838 870 print_method = ObjectName('_repr_pdf_')
839 871
840 872 _return_type = (bytes, unicode_type)
841 873
842 874 class IPythonDisplayFormatter(BaseFormatter):
843 875 """A Formatter for objects that know how to display themselves.
844 876
845 877 To define the callables that compute the representation of your
846 878 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
847 879 or :meth:`for_type_by_name` methods to register functions that handle
848 880 this. Unlike mime-type displays, this method should not return anything,
849 881 instead calling any appropriate display methods itself.
850 882
851 883 This display formatter has highest priority.
852 884 If it fires, no other display formatter will be called.
853 885 """
854 886 print_method = ObjectName('_ipython_display_')
855 887 _return_type = (type(None), bool)
856 888
857 889
858 890 @warn_format_error
859 891 def __call__(self, obj):
860 892 """Compute the format for an object."""
861 893 if self.enabled:
862 894 # lookup registered printer
863 895 try:
864 896 printer = self.lookup(obj)
865 897 except KeyError:
866 898 pass
867 899 else:
868 900 printer(obj)
869 901 return True
870 902 # Finally look for special method names
871 903 method = _safe_get_formatter_method(obj, self.print_method)
872 904 if method is not None:
873 905 method()
874 906 return True
875 907
876 908
877 909 FormatterABC.register(BaseFormatter)
878 910 FormatterABC.register(PlainTextFormatter)
879 911 FormatterABC.register(HTMLFormatter)
880 912 FormatterABC.register(MarkdownFormatter)
881 913 FormatterABC.register(SVGFormatter)
882 914 FormatterABC.register(PNGFormatter)
883 915 FormatterABC.register(PDFFormatter)
884 916 FormatterABC.register(JPEGFormatter)
885 917 FormatterABC.register(LatexFormatter)
886 918 FormatterABC.register(JSONFormatter)
887 919 FormatterABC.register(JavascriptFormatter)
888 920 FormatterABC.register(IPythonDisplayFormatter)
889 921
890 922
891 923 def format_display_data(obj, include=None, exclude=None):
892 924 """Return a format data dict for an object.
893 925
894 926 By default all format types will be computed.
895 927
896 928 The following MIME types are currently implemented:
897 929
898 930 * text/plain
899 931 * text/html
900 932 * text/markdown
901 933 * text/latex
902 934 * application/json
903 935 * application/javascript
904 936 * application/pdf
905 937 * image/png
906 938 * image/jpeg
907 939 * image/svg+xml
908 940
909 941 Parameters
910 942 ----------
911 943 obj : object
912 944 The Python object whose format data will be computed.
913 945
914 946 Returns
915 947 -------
916 948 format_dict : dict
917 949 A dictionary of key/value pairs, one or each format that was
918 950 generated for the object. The keys are the format types, which
919 951 will usually be MIME type strings and the values and JSON'able
920 952 data structure containing the raw data for the representation in
921 953 that format.
922 954 include : list or tuple, optional
923 955 A list of format type strings (MIME types) to include in the
924 956 format data dict. If this is set *only* the format types included
925 957 in this list will be computed.
926 958 exclude : list or tuple, optional
927 959 A list of format type string (MIME types) to exclue in the format
928 960 data dict. If this is set all format types will be computed,
929 961 except for those included in this argument.
930 962 """
931 963 from IPython.core.interactiveshell import InteractiveShell
932 964
933 965 InteractiveShell.instance().display_formatter.format(
934 966 obj,
935 967 include,
936 968 exclude
937 969 )
938 970
@@ -1,611 +1,611 b''
1 1 """Implementation of basic magic functions."""
2 2
3 3 from __future__ import print_function
4 4
5 5 import io
6 6 import json
7 7 import sys
8 8 from pprint import pformat
9 9
10 10 from IPython.core import magic_arguments, page
11 11 from IPython.core.error import UsageError
12 12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 13 from IPython.utils.text import format_screen, dedent, indent
14 14 from IPython.testing.skipdoctest import skip_doctest
15 15 from IPython.utils.ipstruct import Struct
16 16 from IPython.utils.path import unquote_filename
17 17 from IPython.utils.py3compat import unicode_type
18 18 from IPython.utils.warn import warn, error
19 19
20 20
21 21 class MagicsDisplay(object):
22 22 def __init__(self, magics_manager):
23 23 self.magics_manager = magics_manager
24 24
25 25 def _lsmagic(self):
26 26 """The main implementation of the %lsmagic"""
27 27 mesc = magic_escapes['line']
28 28 cesc = magic_escapes['cell']
29 29 mman = self.magics_manager
30 30 magics = mman.lsmagic()
31 31 out = ['Available line magics:',
32 32 mesc + (' '+mesc).join(sorted(magics['line'])),
33 33 '',
34 34 'Available cell magics:',
35 35 cesc + (' '+cesc).join(sorted(magics['cell'])),
36 36 '',
37 37 mman.auto_status()]
38 38 return '\n'.join(out)
39 39
40 40 def _repr_pretty_(self, p, cycle):
41 41 p.text(self._lsmagic())
42 42
43 43 def __str__(self):
44 44 return self._lsmagic()
45 45
46 46 def _jsonable(self):
47 47 """turn magics dict into jsonable dict of the same structure
48 48
49 49 replaces object instances with their class names as strings
50 50 """
51 51 magic_dict = {}
52 52 mman = self.magics_manager
53 53 magics = mman.lsmagic()
54 54 for key, subdict in magics.items():
55 55 d = {}
56 56 magic_dict[key] = d
57 57 for name, obj in subdict.items():
58 58 try:
59 59 classname = obj.__self__.__class__.__name__
60 60 except AttributeError:
61 61 classname = 'Other'
62 62
63 63 d[name] = classname
64 64 return magic_dict
65 65
66 66 def _repr_json_(self):
67 return json.dumps(self._jsonable())
67 return self._jsonable()
68 68
69 69
70 70 @magics_class
71 71 class BasicMagics(Magics):
72 72 """Magics that provide central IPython functionality.
73 73
74 74 These are various magics that don't fit into specific categories but that
75 75 are all part of the base 'IPython experience'."""
76 76
77 77 @magic_arguments.magic_arguments()
78 78 @magic_arguments.argument(
79 79 '-l', '--line', action='store_true',
80 80 help="""Create a line magic alias."""
81 81 )
82 82 @magic_arguments.argument(
83 83 '-c', '--cell', action='store_true',
84 84 help="""Create a cell magic alias."""
85 85 )
86 86 @magic_arguments.argument(
87 87 'name',
88 88 help="""Name of the magic to be created."""
89 89 )
90 90 @magic_arguments.argument(
91 91 'target',
92 92 help="""Name of the existing line or cell magic."""
93 93 )
94 94 @line_magic
95 95 def alias_magic(self, line=''):
96 96 """Create an alias for an existing line or cell magic.
97 97
98 98 Examples
99 99 --------
100 100 ::
101 101
102 102 In [1]: %alias_magic t timeit
103 103 Created `%t` as an alias for `%timeit`.
104 104 Created `%%t` as an alias for `%%timeit`.
105 105
106 106 In [2]: %t -n1 pass
107 107 1 loops, best of 3: 954 ns per loop
108 108
109 109 In [3]: %%t -n1
110 110 ...: pass
111 111 ...:
112 112 1 loops, best of 3: 954 ns per loop
113 113
114 114 In [4]: %alias_magic --cell whereami pwd
115 115 UsageError: Cell magic function `%%pwd` not found.
116 116 In [5]: %alias_magic --line whereami pwd
117 117 Created `%whereami` as an alias for `%pwd`.
118 118
119 119 In [6]: %whereami
120 120 Out[6]: u'/home/testuser'
121 121 """
122 122 args = magic_arguments.parse_argstring(self.alias_magic, line)
123 123 shell = self.shell
124 124 mman = self.shell.magics_manager
125 125 escs = ''.join(magic_escapes.values())
126 126
127 127 target = args.target.lstrip(escs)
128 128 name = args.name.lstrip(escs)
129 129
130 130 # Find the requested magics.
131 131 m_line = shell.find_magic(target, 'line')
132 132 m_cell = shell.find_magic(target, 'cell')
133 133 if args.line and m_line is None:
134 134 raise UsageError('Line magic function `%s%s` not found.' %
135 135 (magic_escapes['line'], target))
136 136 if args.cell and m_cell is None:
137 137 raise UsageError('Cell magic function `%s%s` not found.' %
138 138 (magic_escapes['cell'], target))
139 139
140 140 # If --line and --cell are not specified, default to the ones
141 141 # that are available.
142 142 if not args.line and not args.cell:
143 143 if not m_line and not m_cell:
144 144 raise UsageError(
145 145 'No line or cell magic with name `%s` found.' % target
146 146 )
147 147 args.line = bool(m_line)
148 148 args.cell = bool(m_cell)
149 149
150 150 if args.line:
151 151 mman.register_alias(name, target, 'line')
152 152 print('Created `%s%s` as an alias for `%s%s`.' % (
153 153 magic_escapes['line'], name,
154 154 magic_escapes['line'], target))
155 155
156 156 if args.cell:
157 157 mman.register_alias(name, target, 'cell')
158 158 print('Created `%s%s` as an alias for `%s%s`.' % (
159 159 magic_escapes['cell'], name,
160 160 magic_escapes['cell'], target))
161 161
162 162 @line_magic
163 163 def lsmagic(self, parameter_s=''):
164 164 """List currently available magic functions."""
165 165 return MagicsDisplay(self.shell.magics_manager)
166 166
167 167 def _magic_docs(self, brief=False, rest=False):
168 168 """Return docstrings from magic functions."""
169 169 mman = self.shell.magics_manager
170 170 docs = mman.lsmagic_docs(brief, missing='No documentation')
171 171
172 172 if rest:
173 173 format_string = '**%s%s**::\n\n%s\n\n'
174 174 else:
175 175 format_string = '%s%s:\n%s\n'
176 176
177 177 return ''.join(
178 178 [format_string % (magic_escapes['line'], fname,
179 179 indent(dedent(fndoc)))
180 180 for fname, fndoc in sorted(docs['line'].items())]
181 181 +
182 182 [format_string % (magic_escapes['cell'], fname,
183 183 indent(dedent(fndoc)))
184 184 for fname, fndoc in sorted(docs['cell'].items())]
185 185 )
186 186
187 187 @line_magic
188 188 def magic(self, parameter_s=''):
189 189 """Print information about the magic function system.
190 190
191 191 Supported formats: -latex, -brief, -rest
192 192 """
193 193
194 194 mode = ''
195 195 try:
196 196 mode = parameter_s.split()[0][1:]
197 197 if mode == 'rest':
198 198 rest_docs = []
199 199 except IndexError:
200 200 pass
201 201
202 202 brief = (mode == 'brief')
203 203 rest = (mode == 'rest')
204 204 magic_docs = self._magic_docs(brief, rest)
205 205
206 206 if mode == 'latex':
207 207 print(self.format_latex(magic_docs))
208 208 return
209 209 else:
210 210 magic_docs = format_screen(magic_docs)
211 211
212 212 out = ["""
213 213 IPython's 'magic' functions
214 214 ===========================
215 215
216 216 The magic function system provides a series of functions which allow you to
217 217 control the behavior of IPython itself, plus a lot of system-type
218 218 features. There are two kinds of magics, line-oriented and cell-oriented.
219 219
220 220 Line magics are prefixed with the % character and work much like OS
221 221 command-line calls: they get as an argument the rest of the line, where
222 222 arguments are passed without parentheses or quotes. For example, this will
223 223 time the given statement::
224 224
225 225 %timeit range(1000)
226 226
227 227 Cell magics are prefixed with a double %%, and they are functions that get as
228 228 an argument not only the rest of the line, but also the lines below it in a
229 229 separate argument. These magics are called with two arguments: the rest of the
230 230 call line and the body of the cell, consisting of the lines below the first.
231 231 For example::
232 232
233 233 %%timeit x = numpy.random.randn((100, 100))
234 234 numpy.linalg.svd(x)
235 235
236 236 will time the execution of the numpy svd routine, running the assignment of x
237 237 as part of the setup phase, which is not timed.
238 238
239 239 In a line-oriented client (the terminal or Qt console IPython), starting a new
240 240 input with %% will automatically enter cell mode, and IPython will continue
241 241 reading input until a blank line is given. In the notebook, simply type the
242 242 whole cell as one entity, but keep in mind that the %% escape can only be at
243 243 the very start of the cell.
244 244
245 245 NOTE: If you have 'automagic' enabled (via the command line option or with the
246 246 %automagic function), you don't need to type in the % explicitly for line
247 247 magics; cell magics always require an explicit '%%' escape. By default,
248 248 IPython ships with automagic on, so you should only rarely need the % escape.
249 249
250 250 Example: typing '%cd mydir' (without the quotes) changes you working directory
251 251 to 'mydir', if it exists.
252 252
253 253 For a list of the available magic functions, use %lsmagic. For a description
254 254 of any of them, type %magic_name?, e.g. '%cd?'.
255 255
256 256 Currently the magic system has the following functions:""",
257 257 magic_docs,
258 258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
259 259 str(self.lsmagic()),
260 260 ]
261 261 page.page('\n'.join(out))
262 262
263 263
264 264 @line_magic
265 265 def page(self, parameter_s=''):
266 266 """Pretty print the object and display it through a pager.
267 267
268 268 %page [options] OBJECT
269 269
270 270 If no object is given, use _ (last output).
271 271
272 272 Options:
273 273
274 274 -r: page str(object), don't pretty-print it."""
275 275
276 276 # After a function contributed by Olivier Aubert, slightly modified.
277 277
278 278 # Process options/args
279 279 opts, args = self.parse_options(parameter_s, 'r')
280 280 raw = 'r' in opts
281 281
282 282 oname = args and args or '_'
283 283 info = self.shell._ofind(oname)
284 284 if info['found']:
285 285 txt = (raw and str or pformat)( info['obj'] )
286 286 page.page(txt)
287 287 else:
288 288 print('Object `%s` not found' % oname)
289 289
290 290 @line_magic
291 291 def profile(self, parameter_s=''):
292 292 """Print your currently active IPython profile.
293 293
294 294 See Also
295 295 --------
296 296 prun : run code using the Python profiler
297 297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
298 298 """
299 299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
300 300 from IPython.core.application import BaseIPythonApplication
301 301 if BaseIPythonApplication.initialized():
302 302 print(BaseIPythonApplication.instance().profile)
303 303 else:
304 304 error("profile is an application-level value, but you don't appear to be in an IPython application")
305 305
306 306 @line_magic
307 307 def pprint(self, parameter_s=''):
308 308 """Toggle pretty printing on/off."""
309 309 ptformatter = self.shell.display_formatter.formatters['text/plain']
310 310 ptformatter.pprint = bool(1 - ptformatter.pprint)
311 311 print('Pretty printing has been turned',
312 312 ['OFF','ON'][ptformatter.pprint])
313 313
314 314 @line_magic
315 315 def colors(self, parameter_s=''):
316 316 """Switch color scheme for prompts, info system and exception handlers.
317 317
318 318 Currently implemented schemes: NoColor, Linux, LightBG.
319 319
320 320 Color scheme names are not case-sensitive.
321 321
322 322 Examples
323 323 --------
324 324 To get a plain black and white terminal::
325 325
326 326 %colors nocolor
327 327 """
328 328 def color_switch_err(name):
329 329 warn('Error changing %s color schemes.\n%s' %
330 330 (name, sys.exc_info()[1]))
331 331
332 332
333 333 new_scheme = parameter_s.strip()
334 334 if not new_scheme:
335 335 raise UsageError(
336 336 "%colors: you must specify a color scheme. See '%colors?'")
337 337 # local shortcut
338 338 shell = self.shell
339 339
340 340 import IPython.utils.rlineimpl as readline
341 341
342 342 if not shell.colors_force and \
343 343 not readline.have_readline and \
344 344 (sys.platform == "win32" or sys.platform == "cli"):
345 345 msg = """\
346 346 Proper color support under MS Windows requires the pyreadline library.
347 347 You can find it at:
348 348 http://ipython.org/pyreadline.html
349 349
350 350 Defaulting color scheme to 'NoColor'"""
351 351 new_scheme = 'NoColor'
352 352 warn(msg)
353 353
354 354 # readline option is 0
355 355 if not shell.colors_force and not shell.has_readline:
356 356 new_scheme = 'NoColor'
357 357
358 358 # Set prompt colors
359 359 try:
360 360 shell.prompt_manager.color_scheme = new_scheme
361 361 except:
362 362 color_switch_err('prompt')
363 363 else:
364 364 shell.colors = \
365 365 shell.prompt_manager.color_scheme_table.active_scheme_name
366 366 # Set exception colors
367 367 try:
368 368 shell.InteractiveTB.set_colors(scheme = new_scheme)
369 369 shell.SyntaxTB.set_colors(scheme = new_scheme)
370 370 except:
371 371 color_switch_err('exception')
372 372
373 373 # Set info (for 'object?') colors
374 374 if shell.color_info:
375 375 try:
376 376 shell.inspector.set_active_scheme(new_scheme)
377 377 except:
378 378 color_switch_err('object inspector')
379 379 else:
380 380 shell.inspector.set_active_scheme('NoColor')
381 381
382 382 @line_magic
383 383 def xmode(self, parameter_s=''):
384 384 """Switch modes for the exception handlers.
385 385
386 386 Valid modes: Plain, Context and Verbose.
387 387
388 388 If called without arguments, acts as a toggle."""
389 389
390 390 def xmode_switch_err(name):
391 391 warn('Error changing %s exception modes.\n%s' %
392 392 (name,sys.exc_info()[1]))
393 393
394 394 shell = self.shell
395 395 new_mode = parameter_s.strip().capitalize()
396 396 try:
397 397 shell.InteractiveTB.set_mode(mode=new_mode)
398 398 print('Exception reporting mode:',shell.InteractiveTB.mode)
399 399 except:
400 400 xmode_switch_err('user')
401 401
402 402 @line_magic
403 403 def quickref(self,arg):
404 404 """ Show a quick reference sheet """
405 405 from IPython.core.usage import quick_reference
406 406 qr = quick_reference + self._magic_docs(brief=True)
407 407 page.page(qr)
408 408
409 409 @line_magic
410 410 def doctest_mode(self, parameter_s=''):
411 411 """Toggle doctest mode on and off.
412 412
413 413 This mode is intended to make IPython behave as much as possible like a
414 414 plain Python shell, from the perspective of how its prompts, exceptions
415 415 and output look. This makes it easy to copy and paste parts of a
416 416 session into doctests. It does so by:
417 417
418 418 - Changing the prompts to the classic ``>>>`` ones.
419 419 - Changing the exception reporting mode to 'Plain'.
420 420 - Disabling pretty-printing of output.
421 421
422 422 Note that IPython also supports the pasting of code snippets that have
423 423 leading '>>>' and '...' prompts in them. This means that you can paste
424 424 doctests from files or docstrings (even if they have leading
425 425 whitespace), and the code will execute correctly. You can then use
426 426 '%history -t' to see the translated history; this will give you the
427 427 input after removal of all the leading prompts and whitespace, which
428 428 can be pasted back into an editor.
429 429
430 430 With these features, you can switch into this mode easily whenever you
431 431 need to do testing and changes to doctests, without having to leave
432 432 your existing IPython session.
433 433 """
434 434
435 435 # Shorthands
436 436 shell = self.shell
437 437 pm = shell.prompt_manager
438 438 meta = shell.meta
439 439 disp_formatter = self.shell.display_formatter
440 440 ptformatter = disp_formatter.formatters['text/plain']
441 441 # dstore is a data store kept in the instance metadata bag to track any
442 442 # changes we make, so we can undo them later.
443 443 dstore = meta.setdefault('doctest_mode',Struct())
444 444 save_dstore = dstore.setdefault
445 445
446 446 # save a few values we'll need to recover later
447 447 mode = save_dstore('mode',False)
448 448 save_dstore('rc_pprint',ptformatter.pprint)
449 449 save_dstore('xmode',shell.InteractiveTB.mode)
450 450 save_dstore('rc_separate_out',shell.separate_out)
451 451 save_dstore('rc_separate_out2',shell.separate_out2)
452 452 save_dstore('rc_prompts_pad_left',pm.justify)
453 453 save_dstore('rc_separate_in',shell.separate_in)
454 454 save_dstore('rc_active_types',disp_formatter.active_types)
455 455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
456 456
457 457 if mode == False:
458 458 # turn on
459 459 pm.in_template = '>>> '
460 460 pm.in2_template = '... '
461 461 pm.out_template = ''
462 462
463 463 # Prompt separators like plain python
464 464 shell.separate_in = ''
465 465 shell.separate_out = ''
466 466 shell.separate_out2 = ''
467 467
468 468 pm.justify = False
469 469
470 470 ptformatter.pprint = False
471 471 disp_formatter.active_types = ['text/plain']
472 472
473 473 shell.magic('xmode Plain')
474 474 else:
475 475 # turn off
476 476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
477 477
478 478 shell.separate_in = dstore.rc_separate_in
479 479
480 480 shell.separate_out = dstore.rc_separate_out
481 481 shell.separate_out2 = dstore.rc_separate_out2
482 482
483 483 pm.justify = dstore.rc_prompts_pad_left
484 484
485 485 ptformatter.pprint = dstore.rc_pprint
486 486 disp_formatter.active_types = dstore.rc_active_types
487 487
488 488 shell.magic('xmode ' + dstore.xmode)
489 489
490 490 # Store new mode and inform
491 491 dstore.mode = bool(1-int(mode))
492 492 mode_label = ['OFF','ON'][dstore.mode]
493 493 print('Doctest mode is:', mode_label)
494 494
495 495 @line_magic
496 496 def gui(self, parameter_s=''):
497 497 """Enable or disable IPython GUI event loop integration.
498 498
499 499 %gui [GUINAME]
500 500
501 501 This magic replaces IPython's threaded shells that were activated
502 502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
503 503 can now be enabled at runtime and keyboard
504 504 interrupts should work without any problems. The following toolkits
505 505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
506 506
507 507 %gui wx # enable wxPython event loop integration
508 508 %gui qt4|qt # enable PyQt4 event loop integration
509 509 %gui qt5 # enable PyQt5 event loop integration
510 510 %gui gtk # enable PyGTK event loop integration
511 511 %gui gtk3 # enable Gtk3 event loop integration
512 512 %gui tk # enable Tk event loop integration
513 513 %gui osx # enable Cocoa event loop integration
514 514 # (requires %matplotlib 1.1)
515 515 %gui # disable all event loop integration
516 516
517 517 WARNING: after any of these has been called you can simply create
518 518 an application object, but DO NOT start the event loop yourself, as
519 519 we have already handled that.
520 520 """
521 521 opts, arg = self.parse_options(parameter_s, '')
522 522 if arg=='': arg = None
523 523 try:
524 524 return self.shell.enable_gui(arg)
525 525 except Exception as e:
526 526 # print simple error message, rather than traceback if we can't
527 527 # hook up the GUI
528 528 error(str(e))
529 529
530 530 @skip_doctest
531 531 @line_magic
532 532 def precision(self, s=''):
533 533 """Set floating point precision for pretty printing.
534 534
535 535 Can set either integer precision or a format string.
536 536
537 537 If numpy has been imported and precision is an int,
538 538 numpy display precision will also be set, via ``numpy.set_printoptions``.
539 539
540 540 If no argument is given, defaults will be restored.
541 541
542 542 Examples
543 543 --------
544 544 ::
545 545
546 546 In [1]: from math import pi
547 547
548 548 In [2]: %precision 3
549 549 Out[2]: u'%.3f'
550 550
551 551 In [3]: pi
552 552 Out[3]: 3.142
553 553
554 554 In [4]: %precision %i
555 555 Out[4]: u'%i'
556 556
557 557 In [5]: pi
558 558 Out[5]: 3
559 559
560 560 In [6]: %precision %e
561 561 Out[6]: u'%e'
562 562
563 563 In [7]: pi**10
564 564 Out[7]: 9.364805e+04
565 565
566 566 In [8]: %precision
567 567 Out[8]: u'%r'
568 568
569 569 In [9]: pi**10
570 570 Out[9]: 93648.047476082982
571 571 """
572 572 ptformatter = self.shell.display_formatter.formatters['text/plain']
573 573 ptformatter.float_precision = s
574 574 return ptformatter.float_format
575 575
576 576 @magic_arguments.magic_arguments()
577 577 @magic_arguments.argument(
578 578 '-e', '--export', action='store_true', default=False,
579 579 help='Export IPython history as a notebook. The filename argument '
580 580 'is used to specify the notebook name and format. For example '
581 581 'a filename of notebook.ipynb will result in a notebook name '
582 582 'of "notebook" and a format of "json". Likewise using a ".py" '
583 583 'file extension will write the notebook as a Python script'
584 584 )
585 585 @magic_arguments.argument(
586 586 'filename', type=unicode_type,
587 587 help='Notebook name or filename'
588 588 )
589 589 @line_magic
590 590 def notebook(self, s):
591 591 """Export and convert IPython notebooks.
592 592
593 593 This function can export the current IPython history to a notebook file.
594 594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
595 595 To export the history to "foo.py" do "%notebook -e foo.py".
596 596 """
597 597 args = magic_arguments.parse_argstring(self.notebook, s)
598 598
599 599 from IPython.nbformat import write, v4
600 600 args.filename = unquote_filename(args.filename)
601 601 if args.export:
602 602 cells = []
603 603 hist = list(self.shell.history_manager.get_range())
604 604 for session, execution_count, input in hist[:-1]:
605 605 cells.append(v4.new_code_cell(
606 606 execution_count=execution_count,
607 607 source=source
608 608 ))
609 609 nb = v4.new_notebook(cells=cells)
610 610 with io.open(args.filename, 'w', encoding='utf-8') as f:
611 611 write(nb, f, version=4)
@@ -1,132 +1,148 b''
1 #-----------------------------------------------------------------------------
2 # Copyright (C) 2010-2011 The IPython Development Team.
3 #
4 # Distributed under the terms of the BSD License.
5 #
6 # The full license is in the file COPYING.txt, distributed with this software.
7 #-----------------------------------------------------------------------------
1 # Copyright (c) IPython Development Team.
2 # Distributed under the terms of the Modified BSD License.
3
4 import json
8 5 import os
6 import warnings
9 7
10 8 import nose.tools as nt
11 9
12 10 from IPython.core import display
13 11 from IPython.core.getipython import get_ipython
14 12 from IPython.utils import path as ipath
15 13
16 14 import IPython.testing.decorators as dec
17 15
18 16 def test_image_size():
19 17 """Simple test for display.Image(args, width=x,height=y)"""
20 18 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
21 19 img = display.Image(url=thisurl, width=200, height=200)
22 20 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
23 21 img = display.Image(url=thisurl, width=200)
24 22 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
25 23 img = display.Image(url=thisurl)
26 24 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
27 25
28 26 def test_retina_png():
29 27 here = os.path.dirname(__file__)
30 28 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
31 29 nt.assert_equal(img.height, 1)
32 30 nt.assert_equal(img.width, 1)
33 31 data, md = img._repr_png_()
34 32 nt.assert_equal(md['width'], 1)
35 33 nt.assert_equal(md['height'], 1)
36 34
37 35 def test_retina_jpeg():
38 36 here = os.path.dirname(__file__)
39 37 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
40 38 nt.assert_equal(img.height, 1)
41 39 nt.assert_equal(img.width, 1)
42 40 data, md = img._repr_jpeg_()
43 41 nt.assert_equal(md['width'], 1)
44 42 nt.assert_equal(md['height'], 1)
45 43
46 44 def test_image_filename_defaults():
47 45 '''test format constraint, and validity of jpeg and png'''
48 46 tpath = ipath.get_ipython_package_dir()
49 47 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.gif'),
50 48 embed=True)
51 49 nt.assert_raises(ValueError, display.Image)
52 50 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
53 51 from IPython.html import DEFAULT_STATIC_FILES_PATH
54 52 # check boths paths to allow packages to test at build and install time
55 53 imgfile = os.path.join(tpath, 'html/static/base/images/logo.png')
56 54 if not os.path.exists(imgfile):
57 55 imgfile = os.path.join(DEFAULT_STATIC_FILES_PATH, 'base/images/logo.png')
58 56 img = display.Image(filename=imgfile)
59 57 nt.assert_equal('png', img.format)
60 58 nt.assert_is_not_none(img._repr_png_())
61 59 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
62 60 nt.assert_equal('jpeg', img.format)
63 61 nt.assert_is_none(img._repr_jpeg_())
64 62
65 63 def _get_inline_config():
66 64 from IPython.kernel.zmq.pylab.config import InlineBackend
67 65 return InlineBackend.instance()
68 66
69 67 @dec.skip_without('matplotlib')
70 68 def test_set_matplotlib_close():
71 69 cfg = _get_inline_config()
72 70 cfg.close_figures = False
73 71 display.set_matplotlib_close()
74 72 assert cfg.close_figures
75 73 display.set_matplotlib_close(False)
76 74 assert not cfg.close_figures
77 75
78 76 _fmt_mime_map = {
79 77 'png': 'image/png',
80 78 'jpeg': 'image/jpeg',
81 79 'pdf': 'application/pdf',
82 80 'retina': 'image/png',
83 81 'svg': 'image/svg+xml',
84 82 }
85 83
86 84 @dec.skip_without('matplotlib')
87 85 def test_set_matplotlib_formats():
88 86 from matplotlib.figure import Figure
89 87 formatters = get_ipython().display_formatter.formatters
90 88 for formats in [
91 89 ('png',),
92 90 ('pdf', 'svg'),
93 91 ('jpeg', 'retina', 'png'),
94 92 (),
95 93 ]:
96 94 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
97 95 display.set_matplotlib_formats(*formats)
98 96 for mime, f in formatters.items():
99 97 if mime in active_mimes:
100 98 nt.assert_in(Figure, f)
101 99 else:
102 100 nt.assert_not_in(Figure, f)
103 101
104 102 @dec.skip_without('matplotlib')
105 103 def test_set_matplotlib_formats_kwargs():
106 104 from matplotlib.figure import Figure
107 105 ip = get_ipython()
108 106 cfg = _get_inline_config()
109 107 cfg.print_figure_kwargs.update(dict(foo='bar'))
110 108 kwargs = dict(quality=10)
111 109 display.set_matplotlib_formats('png', **kwargs)
112 110 formatter = ip.display_formatter.formatters['image/png']
113 111 f = formatter.lookup_by_type(Figure)
114 112 cell = f.__closure__[0].cell_contents
115 113 expected = kwargs
116 114 expected.update(cfg.print_figure_kwargs)
117 115 nt.assert_equal(cell, expected)
118 116
119 117 def test_displayobject_repr():
120 118 h = display.HTML('<br />')
121 119 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
122 120 h._show_mem_addr = True
123 121 nt.assert_equal(repr(h), object.__repr__(h))
124 122 h._show_mem_addr = False
125 123 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
126 124
127 125 j = display.Javascript('')
128 126 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
129 127 j._show_mem_addr = True
130 128 nt.assert_equal(repr(j), object.__repr__(j))
131 129 j._show_mem_addr = False
132 130 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
131
132 def test_json():
133 d = {'a': 5}
134 lis = [d]
135 j = display.JSON(d)
136 nt.assert_equal(j._repr_json_(), d)
137 with warnings.catch_warnings(record=True) as w:
138 j = display.JSON(json.dumps(d))
139 assert len(w) == 1
140 nt.assert_equal(j._repr_json_(), d)
141 j = display.JSON(lis)
142 nt.assert_equal(j._repr_json_(), lis)
143 with warnings.catch_warnings(record=True) as w:
144 j = display.JSON(json.dumps(lis))
145 assert len(w) == 1
146 nt.assert_equal(j._repr_json_(), lis)
147
148 No newline at end of file
@@ -1,420 +1,433 b''
1 1 """Tests for the Formatters."""
2 2
3 import warnings
3 4 from math import pi
4 5
5 6 try:
6 7 import numpy
7 8 except:
8 9 numpy = None
9 10 import nose.tools as nt
10 11
12 from IPython import get_ipython
11 13 from IPython.config import Config
12 14 from IPython.core.formatters import (
13 15 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
14 DisplayFormatter,
16 DisplayFormatter, JSONFormatter,
15 17 )
16 18 from IPython.utils.io import capture_output
17 19
18 20 class A(object):
19 21 def __repr__(self):
20 22 return 'A()'
21 23
22 24 class B(A):
23 25 def __repr__(self):
24 26 return 'B()'
25 27
26 28 class C:
27 29 pass
28 30
29 31 class BadRepr(object):
30 32 def __repr__(self):
31 33 raise ValueError("bad repr")
32 34
33 35 class BadPretty(object):
34 36 _repr_pretty_ = None
35 37
36 38 class GoodPretty(object):
37 39 def _repr_pretty_(self, pp, cycle):
38 40 pp.text('foo')
39 41
40 42 def __repr__(self):
41 43 return 'GoodPretty()'
42 44
43 45 def foo_printer(obj, pp, cycle):
44 46 pp.text('foo')
45 47
46 48 def test_pretty():
47 49 f = PlainTextFormatter()
48 50 f.for_type(A, foo_printer)
49 51 nt.assert_equal(f(A()), 'foo')
50 52 nt.assert_equal(f(B()), 'foo')
51 53 nt.assert_equal(f(GoodPretty()), 'foo')
52 54 # Just don't raise an exception for the following:
53 55 f(BadPretty())
54 56
55 57 f.pprint = False
56 58 nt.assert_equal(f(A()), 'A()')
57 59 nt.assert_equal(f(B()), 'B()')
58 60 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
59 61
60 62
61 63 def test_deferred():
62 64 f = PlainTextFormatter()
63 65
64 66 def test_precision():
65 67 """test various values for float_precision."""
66 68 f = PlainTextFormatter()
67 69 nt.assert_equal(f(pi), repr(pi))
68 70 f.float_precision = 0
69 71 if numpy:
70 72 po = numpy.get_printoptions()
71 73 nt.assert_equal(po['precision'], 0)
72 74 nt.assert_equal(f(pi), '3')
73 75 f.float_precision = 2
74 76 if numpy:
75 77 po = numpy.get_printoptions()
76 78 nt.assert_equal(po['precision'], 2)
77 79 nt.assert_equal(f(pi), '3.14')
78 80 f.float_precision = '%g'
79 81 if numpy:
80 82 po = numpy.get_printoptions()
81 83 nt.assert_equal(po['precision'], 2)
82 84 nt.assert_equal(f(pi), '3.14159')
83 85 f.float_precision = '%e'
84 86 nt.assert_equal(f(pi), '3.141593e+00')
85 87 f.float_precision = ''
86 88 if numpy:
87 89 po = numpy.get_printoptions()
88 90 nt.assert_equal(po['precision'], 8)
89 91 nt.assert_equal(f(pi), repr(pi))
90 92
91 93 def test_bad_precision():
92 94 """test various invalid values for float_precision."""
93 95 f = PlainTextFormatter()
94 96 def set_fp(p):
95 97 f.float_precision=p
96 98 nt.assert_raises(ValueError, set_fp, '%')
97 99 nt.assert_raises(ValueError, set_fp, '%.3f%i')
98 100 nt.assert_raises(ValueError, set_fp, 'foo')
99 101 nt.assert_raises(ValueError, set_fp, -1)
100 102
101 103 def test_for_type():
102 104 f = PlainTextFormatter()
103 105
104 106 # initial return, None
105 107 nt.assert_is(f.for_type(C, foo_printer), None)
106 108 # no func queries
107 109 nt.assert_is(f.for_type(C), foo_printer)
108 110 # shouldn't change anything
109 111 nt.assert_is(f.for_type(C), foo_printer)
110 112 # None should do the same
111 113 nt.assert_is(f.for_type(C, None), foo_printer)
112 114 nt.assert_is(f.for_type(C, None), foo_printer)
113 115
114 116 def test_for_type_string():
115 117 f = PlainTextFormatter()
116 118
117 119 mod = C.__module__
118 120
119 121 type_str = '%s.%s' % (C.__module__, 'C')
120 122
121 123 # initial return, None
122 124 nt.assert_is(f.for_type(type_str, foo_printer), None)
123 125 # no func queries
124 126 nt.assert_is(f.for_type(type_str), foo_printer)
125 127 nt.assert_in(_mod_name_key(C), f.deferred_printers)
126 128 nt.assert_is(f.for_type(C), foo_printer)
127 129 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
128 130 nt.assert_in(C, f.type_printers)
129 131
130 132 def test_for_type_by_name():
131 133 f = PlainTextFormatter()
132 134
133 135 mod = C.__module__
134 136
135 137 # initial return, None
136 138 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
137 139 # no func queries
138 140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
139 141 # shouldn't change anything
140 142 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
141 143 # None should do the same
142 144 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
143 145 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
144 146
145 147 def test_lookup():
146 148 f = PlainTextFormatter()
147 149
148 150 f.for_type(C, foo_printer)
149 151 nt.assert_is(f.lookup(C()), foo_printer)
150 152 with nt.assert_raises(KeyError):
151 153 f.lookup(A())
152 154
153 155 def test_lookup_string():
154 156 f = PlainTextFormatter()
155 157 type_str = '%s.%s' % (C.__module__, 'C')
156 158
157 159 f.for_type(type_str, foo_printer)
158 160 nt.assert_is(f.lookup(C()), foo_printer)
159 161 # should move from deferred to imported dict
160 162 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
161 163 nt.assert_in(C, f.type_printers)
162 164
163 165 def test_lookup_by_type():
164 166 f = PlainTextFormatter()
165 167 f.for_type(C, foo_printer)
166 168 nt.assert_is(f.lookup_by_type(C), foo_printer)
167 169 type_str = '%s.%s' % (C.__module__, 'C')
168 170 with nt.assert_raises(KeyError):
169 171 f.lookup_by_type(A)
170 172
171 173 def test_lookup_by_type_string():
172 174 f = PlainTextFormatter()
173 175 type_str = '%s.%s' % (C.__module__, 'C')
174 176 f.for_type(type_str, foo_printer)
175 177
176 178 # verify insertion
177 179 nt.assert_in(_mod_name_key(C), f.deferred_printers)
178 180 nt.assert_not_in(C, f.type_printers)
179 181
180 182 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
181 183 # lookup by string doesn't cause import
182 184 nt.assert_in(_mod_name_key(C), f.deferred_printers)
183 185 nt.assert_not_in(C, f.type_printers)
184 186
185 187 nt.assert_is(f.lookup_by_type(C), foo_printer)
186 188 # should move from deferred to imported dict
187 189 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
188 190 nt.assert_in(C, f.type_printers)
189 191
190 192 def test_in_formatter():
191 193 f = PlainTextFormatter()
192 194 f.for_type(C, foo_printer)
193 195 type_str = '%s.%s' % (C.__module__, 'C')
194 196 nt.assert_in(C, f)
195 197 nt.assert_in(type_str, f)
196 198
197 199 def test_string_in_formatter():
198 200 f = PlainTextFormatter()
199 201 type_str = '%s.%s' % (C.__module__, 'C')
200 202 f.for_type(type_str, foo_printer)
201 203 nt.assert_in(type_str, f)
202 204 nt.assert_in(C, f)
203 205
204 206 def test_pop():
205 207 f = PlainTextFormatter()
206 208 f.for_type(C, foo_printer)
207 209 nt.assert_is(f.lookup_by_type(C), foo_printer)
208 210 nt.assert_is(f.pop(C, None), foo_printer)
209 211 f.for_type(C, foo_printer)
210 212 nt.assert_is(f.pop(C), foo_printer)
211 213 with nt.assert_raises(KeyError):
212 214 f.lookup_by_type(C)
213 215 with nt.assert_raises(KeyError):
214 216 f.pop(C)
215 217 with nt.assert_raises(KeyError):
216 218 f.pop(A)
217 219 nt.assert_is(f.pop(A, None), None)
218 220
219 221 def test_pop_string():
220 222 f = PlainTextFormatter()
221 223 type_str = '%s.%s' % (C.__module__, 'C')
222 224
223 225 with nt.assert_raises(KeyError):
224 226 f.pop(type_str)
225 227
226 228 f.for_type(type_str, foo_printer)
227 229 f.pop(type_str)
228 230 with nt.assert_raises(KeyError):
229 231 f.lookup_by_type(C)
230 232 with nt.assert_raises(KeyError):
231 233 f.pop(type_str)
232 234
233 235 f.for_type(C, foo_printer)
234 236 nt.assert_is(f.pop(type_str, None), foo_printer)
235 237 with nt.assert_raises(KeyError):
236 238 f.lookup_by_type(C)
237 239 with nt.assert_raises(KeyError):
238 240 f.pop(type_str)
239 241 nt.assert_is(f.pop(type_str, None), None)
240 242
241 243
242 244 def test_error_method():
243 245 f = HTMLFormatter()
244 246 class BadHTML(object):
245 247 def _repr_html_(self):
246 248 raise ValueError("Bad HTML")
247 249 bad = BadHTML()
248 250 with capture_output() as captured:
249 251 result = f(bad)
250 252 nt.assert_is(result, None)
251 253 nt.assert_in("Traceback", captured.stdout)
252 254 nt.assert_in("Bad HTML", captured.stdout)
253 255 nt.assert_in("_repr_html_", captured.stdout)
254 256
255 257 def test_nowarn_notimplemented():
256 258 f = HTMLFormatter()
257 259 class HTMLNotImplemented(object):
258 260 def _repr_html_(self):
259 261 raise NotImplementedError
260 262 h = HTMLNotImplemented()
261 263 with capture_output() as captured:
262 264 result = f(h)
263 265 nt.assert_is(result, None)
264 266 nt.assert_equal("", captured.stderr)
265 267 nt.assert_equal("", captured.stdout)
266 268
267 269 def test_warn_error_for_type():
268 270 f = HTMLFormatter()
269 271 f.for_type(int, lambda i: name_error)
270 272 with capture_output() as captured:
271 273 result = f(5)
272 274 nt.assert_is(result, None)
273 275 nt.assert_in("Traceback", captured.stdout)
274 276 nt.assert_in("NameError", captured.stdout)
275 277 nt.assert_in("name_error", captured.stdout)
276 278
277 279 def test_error_pretty_method():
278 280 f = PlainTextFormatter()
279 281 class BadPretty(object):
280 282 def _repr_pretty_(self):
281 283 return "hello"
282 284 bad = BadPretty()
283 285 with capture_output() as captured:
284 286 result = f(bad)
285 287 nt.assert_is(result, None)
286 288 nt.assert_in("Traceback", captured.stdout)
287 289 nt.assert_in("_repr_pretty_", captured.stdout)
288 290 nt.assert_in("given", captured.stdout)
289 291 nt.assert_in("argument", captured.stdout)
290 292
291 293
292 294 def test_bad_repr_traceback():
293 295 f = PlainTextFormatter()
294 296 bad = BadRepr()
295 297 with capture_output() as captured:
296 298 result = f(bad)
297 299 # catches error, returns None
298 300 nt.assert_is(result, None)
299 301 nt.assert_in("Traceback", captured.stdout)
300 302 nt.assert_in("__repr__", captured.stdout)
301 303 nt.assert_in("ValueError", captured.stdout)
302 304
303 305
304 306 class MakePDF(object):
305 307 def _repr_pdf_(self):
306 308 return 'PDF'
307 309
308 310 def test_pdf_formatter():
309 311 pdf = MakePDF()
310 312 f = PDFFormatter()
311 313 nt.assert_equal(f(pdf), 'PDF')
312 314
313 315 def test_print_method_bound():
314 316 f = HTMLFormatter()
315 317 class MyHTML(object):
316 318 def _repr_html_(self):
317 319 return "hello"
318 320 with capture_output() as captured:
319 321 result = f(MyHTML)
320 322 nt.assert_is(result, None)
321 323 nt.assert_not_in("FormatterWarning", captured.stderr)
322 324
323 325 with capture_output() as captured:
324 326 result = f(MyHTML())
325 327 nt.assert_equal(result, "hello")
326 328 nt.assert_equal(captured.stderr, "")
327 329
328 330 def test_print_method_weird():
329 331
330 332 class TextMagicHat(object):
331 333 def __getattr__(self, key):
332 334 return key
333 335
334 336 f = HTMLFormatter()
335 337
336 338 text_hat = TextMagicHat()
337 339 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
338 340 with capture_output() as captured:
339 341 result = f(text_hat)
340 342
341 343 nt.assert_is(result, None)
342 344 nt.assert_not_in("FormatterWarning", captured.stderr)
343 345
344 346 class CallableMagicHat(object):
345 347 def __getattr__(self, key):
346 348 return lambda : key
347 349
348 350 call_hat = CallableMagicHat()
349 351 with capture_output() as captured:
350 352 result = f(call_hat)
351 353
352 354 nt.assert_equal(result, None)
353 355
354 356 class BadReprArgs(object):
355 357 def _repr_html_(self, extra, args):
356 358 return "html"
357 359
358 360 bad = BadReprArgs()
359 361 with capture_output() as captured:
360 362 result = f(bad)
361 363
362 364 nt.assert_is(result, None)
363 365 nt.assert_not_in("FormatterWarning", captured.stderr)
364 366
365 367
366 368 def test_format_config():
367 369 """config objects don't pretend to support fancy reprs with lazy attrs"""
368 370 f = HTMLFormatter()
369 371 cfg = Config()
370 372 with capture_output() as captured:
371 373 result = f(cfg)
372 374 nt.assert_is(result, None)
373 375 nt.assert_equal(captured.stderr, "")
374 376
375 377 with capture_output() as captured:
376 378 result = f(Config)
377 379 nt.assert_is(result, None)
378 380 nt.assert_equal(captured.stderr, "")
379 381
380 382 def test_pretty_max_seq_length():
381 383 f = PlainTextFormatter(max_seq_length=1)
382 384 lis = list(range(3))
383 385 text = f(lis)
384 386 nt.assert_equal(text, '[0, ...]')
385 387 f.max_seq_length = 0
386 388 text = f(lis)
387 389 nt.assert_equal(text, '[0, 1, 2]')
388 390 text = f(list(range(1024)))
389 391 lines = text.splitlines()
390 392 nt.assert_equal(len(lines), 1024)
391 393
392 394
393 395 def test_ipython_display_formatter():
394 396 """Objects with _ipython_display_ defined bypass other formatters"""
395 397 f = get_ipython().display_formatter
396 398 catcher = []
397 399 class SelfDisplaying(object):
398 400 def _ipython_display_(self):
399 401 catcher.append(self)
400 402
401 403 class NotSelfDisplaying(object):
402 404 def __repr__(self):
403 405 return "NotSelfDisplaying"
404 406
405 407 def _ipython_display_(self):
406 408 raise NotImplementedError
407 409
408 410 yes = SelfDisplaying()
409 411 no = NotSelfDisplaying()
410 412
411 413 d, md = f.format(no)
412 414 nt.assert_equal(d, {'text/plain': repr(no)})
413 415 nt.assert_equal(md, {})
414 416 nt.assert_equal(catcher, [])
415 417
416 418 d, md = f.format(yes)
417 419 nt.assert_equal(d, {})
418 420 nt.assert_equal(md, {})
419 421 nt.assert_equal(catcher, [yes])
420 422
423 def test_json_as_string_deprecated():
424 class JSONString(object):
425 def _repr_json_(self):
426 return '{}'
427
428 f = JSONFormatter()
429 with warnings.catch_warnings(record=True) as w:
430 d = f(JSONString())
431 nt.assert_equal(d, {})
432 nt.assert_equal(len(w), 1)
433 No newline at end of file
@@ -1,982 +1,994 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6 from __future__ import absolute_import
7 7
8 8 import io
9 9 import os
10 10 import sys
11 import warnings
11 12 from unittest import TestCase, skipIf
12 13
13 14 try:
14 15 from importlib import invalidate_caches # Required from Python 3.3
15 16 except ImportError:
16 17 def invalidate_caches():
17 18 pass
18 19
19 20 import nose.tools as nt
20 21
22 from IPython import get_ipython
21 23 from IPython.core import magic
22 24 from IPython.core.error import UsageError
23 25 from IPython.core.magic import (Magics, magics_class, line_magic,
24 26 cell_magic, line_cell_magic,
25 27 register_line_magic, register_cell_magic,
26 28 register_line_cell_magic)
27 29 from IPython.core.magics import execution, script, code
28 30 from IPython.testing import decorators as dec
29 31 from IPython.testing import tools as tt
30 32 from IPython.utils import py3compat
31 33 from IPython.utils.io import capture_output
32 34 from IPython.utils.tempdir import TemporaryDirectory
33 35 from IPython.utils.process import find_cmd
34 36
35 37 if py3compat.PY3:
36 38 from io import StringIO
37 39 else:
38 40 from StringIO import StringIO
39 41
40 42
41 43 @magic.magics_class
42 44 class DummyMagics(magic.Magics): pass
43 45
44 46 def test_extract_code_ranges():
45 47 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
46 48 expected = [(0, 1),
47 49 (2, 3),
48 50 (4, 6),
49 51 (6, 9),
50 52 (9, 14),
51 53 (16, None),
52 54 (None, 9),
53 55 (9, None),
54 56 (None, 13),
55 57 (None, None)]
56 58 actual = list(code.extract_code_ranges(instr))
57 59 nt.assert_equal(actual, expected)
58 60
59 61 def test_extract_symbols():
60 62 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
61 63 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
62 64 expected = [([], ['a']),
63 65 (["def b():\n return 42\n"], []),
64 66 (["class A: pass\n"], []),
65 67 (["class A: pass\n", "def b():\n return 42\n"], []),
66 68 (["class A: pass\n"], ['a']),
67 69 ([], ['z'])]
68 70 for symbols, exp in zip(symbols_args, expected):
69 71 nt.assert_equal(code.extract_symbols(source, symbols), exp)
70 72
71 73
72 74 def test_extract_symbols_raises_exception_with_non_python_code():
73 75 source = ("=begin A Ruby program :)=end\n"
74 76 "def hello\n"
75 77 "puts 'Hello world'\n"
76 78 "end")
77 79 with nt.assert_raises(SyntaxError):
78 80 code.extract_symbols(source, "hello")
79 81
80 82 def test_config():
81 83 """ test that config magic does not raise
82 84 can happen if Configurable init is moved too early into
83 85 Magics.__init__ as then a Config object will be registerd as a
84 86 magic.
85 87 """
86 88 ## should not raise.
87 89 _ip.magic('config')
88 90
89 91 def test_rehashx():
90 92 # clear up everything
91 93 _ip = get_ipython()
92 94 _ip.alias_manager.clear_aliases()
93 95 del _ip.db['syscmdlist']
94 96
95 97 _ip.magic('rehashx')
96 98 # Practically ALL ipython development systems will have more than 10 aliases
97 99
98 100 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
99 101 for name, cmd in _ip.alias_manager.aliases:
100 102 # we must strip dots from alias names
101 103 nt.assert_not_in('.', name)
102 104
103 105 # rehashx must fill up syscmdlist
104 106 scoms = _ip.db['syscmdlist']
105 107 nt.assert_true(len(scoms) > 10)
106 108
107 109
108 110 def test_magic_parse_options():
109 111 """Test that we don't mangle paths when parsing magic options."""
110 112 ip = get_ipython()
111 113 path = 'c:\\x'
112 114 m = DummyMagics(ip)
113 115 opts = m.parse_options('-f %s' % path,'f:')[0]
114 116 # argv splitting is os-dependent
115 117 if os.name == 'posix':
116 118 expected = 'c:x'
117 119 else:
118 120 expected = path
119 121 nt.assert_equal(opts['f'], expected)
120 122
121 123 def test_magic_parse_long_options():
122 124 """Magic.parse_options can handle --foo=bar long options"""
123 125 ip = get_ipython()
124 126 m = DummyMagics(ip)
125 127 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
126 128 nt.assert_in('foo', opts)
127 129 nt.assert_in('bar', opts)
128 130 nt.assert_equal(opts['bar'], "bubble")
129 131
130 132
131 133 @dec.skip_without('sqlite3')
132 134 def doctest_hist_f():
133 135 """Test %hist -f with temporary filename.
134 136
135 137 In [9]: import tempfile
136 138
137 139 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
138 140
139 141 In [11]: %hist -nl -f $tfile 3
140 142
141 143 In [13]: import os; os.unlink(tfile)
142 144 """
143 145
144 146
145 147 @dec.skip_without('sqlite3')
146 148 def doctest_hist_r():
147 149 """Test %hist -r
148 150
149 151 XXX - This test is not recording the output correctly. For some reason, in
150 152 testing mode the raw history isn't getting populated. No idea why.
151 153 Disabling the output checking for now, though at least we do run it.
152 154
153 155 In [1]: 'hist' in _ip.lsmagic()
154 156 Out[1]: True
155 157
156 158 In [2]: x=1
157 159
158 160 In [3]: %hist -rl 2
159 161 x=1 # random
160 162 %hist -r 2
161 163 """
162 164
163 165
164 166 @dec.skip_without('sqlite3')
165 167 def doctest_hist_op():
166 168 """Test %hist -op
167 169
168 170 In [1]: class b(float):
169 171 ...: pass
170 172 ...:
171 173
172 174 In [2]: class s(object):
173 175 ...: def __str__(self):
174 176 ...: return 's'
175 177 ...:
176 178
177 179 In [3]:
178 180
179 181 In [4]: class r(b):
180 182 ...: def __repr__(self):
181 183 ...: return 'r'
182 184 ...:
183 185
184 186 In [5]: class sr(s,r): pass
185 187 ...:
186 188
187 189 In [6]:
188 190
189 191 In [7]: bb=b()
190 192
191 193 In [8]: ss=s()
192 194
193 195 In [9]: rr=r()
194 196
195 197 In [10]: ssrr=sr()
196 198
197 199 In [11]: 4.5
198 200 Out[11]: 4.5
199 201
200 202 In [12]: str(ss)
201 203 Out[12]: 's'
202 204
203 205 In [13]:
204 206
205 207 In [14]: %hist -op
206 208 >>> class b:
207 209 ... pass
208 210 ...
209 211 >>> class s(b):
210 212 ... def __str__(self):
211 213 ... return 's'
212 214 ...
213 215 >>>
214 216 >>> class r(b):
215 217 ... def __repr__(self):
216 218 ... return 'r'
217 219 ...
218 220 >>> class sr(s,r): pass
219 221 >>>
220 222 >>> bb=b()
221 223 >>> ss=s()
222 224 >>> rr=r()
223 225 >>> ssrr=sr()
224 226 >>> 4.5
225 227 4.5
226 228 >>> str(ss)
227 229 's'
228 230 >>>
229 231 """
230 232
231 233 def test_hist_pof():
232 234 ip = get_ipython()
233 235 ip.run_cell(u"1+2", store_history=True)
234 236 #raise Exception(ip.history_manager.session_number)
235 237 #raise Exception(list(ip.history_manager._get_range_session()))
236 238 with TemporaryDirectory() as td:
237 239 tf = os.path.join(td, 'hist.py')
238 240 ip.run_line_magic('history', '-pof %s' % tf)
239 241 assert os.path.isfile(tf)
240 242
241 243
242 244 @dec.skip_without('sqlite3')
243 245 def test_macro():
244 246 ip = get_ipython()
245 247 ip.history_manager.reset() # Clear any existing history.
246 248 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
247 249 for i, cmd in enumerate(cmds, start=1):
248 250 ip.history_manager.store_inputs(i, cmd)
249 251 ip.magic("macro test 1-3")
250 252 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
251 253
252 254 # List macros
253 255 nt.assert_in("test", ip.magic("macro"))
254 256
255 257
256 258 @dec.skip_without('sqlite3')
257 259 def test_macro_run():
258 260 """Test that we can run a multi-line macro successfully."""
259 261 ip = get_ipython()
260 262 ip.history_manager.reset()
261 263 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
262 264 "%macro test 2-3"]
263 265 for cmd in cmds:
264 266 ip.run_cell(cmd, store_history=True)
265 267 nt.assert_equal(ip.user_ns["test"].value,
266 268 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
267 269 with tt.AssertPrints("12"):
268 270 ip.run_cell("test")
269 271 with tt.AssertPrints("13"):
270 272 ip.run_cell("test")
271 273
272 274
273 275 def test_magic_magic():
274 276 """Test %magic"""
275 277 ip = get_ipython()
276 278 with capture_output() as captured:
277 279 ip.magic("magic")
278 280
279 281 stdout = captured.stdout
280 282 nt.assert_in('%magic', stdout)
281 283 nt.assert_in('IPython', stdout)
282 284 nt.assert_in('Available', stdout)
283 285
284 286
285 287 @dec.skipif_not_numpy
286 288 def test_numpy_reset_array_undec():
287 289 "Test '%reset array' functionality"
288 290 _ip.ex('import numpy as np')
289 291 _ip.ex('a = np.empty(2)')
290 292 nt.assert_in('a', _ip.user_ns)
291 293 _ip.magic('reset -f array')
292 294 nt.assert_not_in('a', _ip.user_ns)
293 295
294 296 def test_reset_out():
295 297 "Test '%reset out' magic"
296 298 _ip.run_cell("parrot = 'dead'", store_history=True)
297 299 # test '%reset -f out', make an Out prompt
298 300 _ip.run_cell("parrot", store_history=True)
299 301 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
300 302 _ip.magic('reset -f out')
301 303 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
302 304 nt.assert_equal(len(_ip.user_ns['Out']), 0)
303 305
304 306 def test_reset_in():
305 307 "Test '%reset in' magic"
306 308 # test '%reset -f in'
307 309 _ip.run_cell("parrot", store_history=True)
308 310 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
309 311 _ip.magic('%reset -f in')
310 312 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
311 313 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
312 314
313 315 def test_reset_dhist():
314 316 "Test '%reset dhist' magic"
315 317 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
316 318 _ip.magic('cd ' + os.path.dirname(nt.__file__))
317 319 _ip.magic('cd -')
318 320 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
319 321 _ip.magic('reset -f dhist')
320 322 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
321 323 _ip.run_cell("_dh = [d for d in tmp]") #restore
322 324
323 325 def test_reset_in_length():
324 326 "Test that '%reset in' preserves In[] length"
325 327 _ip.run_cell("print 'foo'")
326 328 _ip.run_cell("reset -f in")
327 329 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
328 330
329 331 def test_tb_syntaxerror():
330 332 """test %tb after a SyntaxError"""
331 333 ip = get_ipython()
332 334 ip.run_cell("for")
333 335
334 336 # trap and validate stdout
335 337 save_stdout = sys.stdout
336 338 try:
337 339 sys.stdout = StringIO()
338 340 ip.run_cell("%tb")
339 341 out = sys.stdout.getvalue()
340 342 finally:
341 343 sys.stdout = save_stdout
342 344 # trim output, and only check the last line
343 345 last_line = out.rstrip().splitlines()[-1].strip()
344 346 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
345 347
346 348
347 349 def test_time():
348 350 ip = get_ipython()
349 351
350 352 with tt.AssertPrints("Wall time: "):
351 353 ip.run_cell("%time None")
352 354
353 355 ip.run_cell("def f(kmjy):\n"
354 356 " %time print (2*kmjy)")
355 357
356 358 with tt.AssertPrints("Wall time: "):
357 359 with tt.AssertPrints("hihi", suppress=False):
358 360 ip.run_cell("f('hi')")
359 361
360 362
361 363 @dec.skip_win32
362 364 def test_time2():
363 365 ip = get_ipython()
364 366
365 367 with tt.AssertPrints("CPU times: user "):
366 368 ip.run_cell("%time None")
367 369
368 370 def test_time3():
369 371 """Erroneous magic function calls, issue gh-3334"""
370 372 ip = get_ipython()
371 373 ip.user_ns.pop('run', None)
372 374
373 375 with tt.AssertNotPrints("not found", channel='stderr'):
374 376 ip.run_cell("%%time\n"
375 377 "run = 0\n"
376 378 "run += 1")
377 379
378 380 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
379 381 def test_time_futures():
380 382 "Test %time with __future__ environments"
381 383 ip = get_ipython()
382 384 ip.autocall = 0
383 385 ip.run_cell("from __future__ import division")
384 386 with tt.AssertPrints('0.25'):
385 387 ip.run_line_magic('time', 'print(1/4)')
386 388 ip.compile.reset_compiler_flags()
387 389 with tt.AssertNotPrints('0.25'):
388 390 ip.run_line_magic('time', 'print(1/4)')
389 391
390 392 def test_doctest_mode():
391 393 "Toggle doctest_mode twice, it should be a no-op and run without error"
392 394 _ip.magic('doctest_mode')
393 395 _ip.magic('doctest_mode')
394 396
395 397
396 398 def test_parse_options():
397 399 """Tests for basic options parsing in magics."""
398 400 # These are only the most minimal of tests, more should be added later. At
399 401 # the very least we check that basic text/unicode calls work OK.
400 402 m = DummyMagics(_ip)
401 403 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
402 404 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
403 405
404 406
405 407 def test_dirops():
406 408 """Test various directory handling operations."""
407 409 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
408 410 curpath = py3compat.getcwd
409 411 startdir = py3compat.getcwd()
410 412 ipdir = os.path.realpath(_ip.ipython_dir)
411 413 try:
412 414 _ip.magic('cd "%s"' % ipdir)
413 415 nt.assert_equal(curpath(), ipdir)
414 416 _ip.magic('cd -')
415 417 nt.assert_equal(curpath(), startdir)
416 418 _ip.magic('pushd "%s"' % ipdir)
417 419 nt.assert_equal(curpath(), ipdir)
418 420 _ip.magic('popd')
419 421 nt.assert_equal(curpath(), startdir)
420 422 finally:
421 423 os.chdir(startdir)
422 424
423 425
424 426 def test_xmode():
425 427 # Calling xmode three times should be a no-op
426 428 xmode = _ip.InteractiveTB.mode
427 429 for i in range(3):
428 430 _ip.magic("xmode")
429 431 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
430 432
431 433 def test_reset_hard():
432 434 monitor = []
433 435 class A(object):
434 436 def __del__(self):
435 437 monitor.append(1)
436 438 def __repr__(self):
437 439 return "<A instance>"
438 440
439 441 _ip.user_ns["a"] = A()
440 442 _ip.run_cell("a")
441 443
442 444 nt.assert_equal(monitor, [])
443 445 _ip.magic("reset -f")
444 446 nt.assert_equal(monitor, [1])
445 447
446 448 class TestXdel(tt.TempFileMixin):
447 449 def test_xdel(self):
448 450 """Test that references from %run are cleared by xdel."""
449 451 src = ("class A(object):\n"
450 452 " monitor = []\n"
451 453 " def __del__(self):\n"
452 454 " self.monitor.append(1)\n"
453 455 "a = A()\n")
454 456 self.mktmp(src)
455 457 # %run creates some hidden references...
456 458 _ip.magic("run %s" % self.fname)
457 459 # ... as does the displayhook.
458 460 _ip.run_cell("a")
459 461
460 462 monitor = _ip.user_ns["A"].monitor
461 463 nt.assert_equal(monitor, [])
462 464
463 465 _ip.magic("xdel a")
464 466
465 467 # Check that a's __del__ method has been called.
466 468 nt.assert_equal(monitor, [1])
467 469
468 470 def doctest_who():
469 471 """doctest for %who
470 472
471 473 In [1]: %reset -f
472 474
473 475 In [2]: alpha = 123
474 476
475 477 In [3]: beta = 'beta'
476 478
477 479 In [4]: %who int
478 480 alpha
479 481
480 482 In [5]: %who str
481 483 beta
482 484
483 485 In [6]: %whos
484 486 Variable Type Data/Info
485 487 ----------------------------
486 488 alpha int 123
487 489 beta str beta
488 490
489 491 In [7]: %who_ls
490 492 Out[7]: ['alpha', 'beta']
491 493 """
492 494
493 495 def test_whos():
494 496 """Check that whos is protected against objects where repr() fails."""
495 497 class A(object):
496 498 def __repr__(self):
497 499 raise Exception()
498 500 _ip.user_ns['a'] = A()
499 501 _ip.magic("whos")
500 502
501 503 @py3compat.u_format
502 504 def doctest_precision():
503 505 """doctest for %precision
504 506
505 507 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
506 508
507 509 In [2]: %precision 5
508 510 Out[2]: {u}'%.5f'
509 511
510 512 In [3]: f.float_format
511 513 Out[3]: {u}'%.5f'
512 514
513 515 In [4]: %precision %e
514 516 Out[4]: {u}'%e'
515 517
516 518 In [5]: f(3.1415927)
517 519 Out[5]: {u}'3.141593e+00'
518 520 """
519 521
520 522 def test_psearch():
521 523 with tt.AssertPrints("dict.fromkeys"):
522 524 _ip.run_cell("dict.fr*?")
523 525
524 526 def test_timeit_shlex():
525 527 """test shlex issues with timeit (#1109)"""
526 528 _ip.ex("def f(*a,**kw): pass")
527 529 _ip.magic('timeit -n1 "this is a bug".count(" ")')
528 530 _ip.magic('timeit -r1 -n1 f(" ", 1)')
529 531 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
530 532 _ip.magic('timeit -r1 -n1 ("a " + "b")')
531 533 _ip.magic('timeit -r1 -n1 f("a " + "b")')
532 534 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
533 535
534 536
535 537 def test_timeit_arguments():
536 538 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
537 539 _ip.magic("timeit ('#')")
538 540
539 541
540 542 def test_timeit_special_syntax():
541 543 "Test %%timeit with IPython special syntax"
542 544 @register_line_magic
543 545 def lmagic(line):
544 546 ip = get_ipython()
545 547 ip.user_ns['lmagic_out'] = line
546 548
547 549 # line mode test
548 550 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
549 551 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
550 552 # cell mode test
551 553 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
552 554 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
553 555
554 556 def test_timeit_return():
555 557 """
556 558 test wether timeit -o return object
557 559 """
558 560
559 561 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
560 562 assert(res is not None)
561 563
562 564 def test_timeit_quiet():
563 565 """
564 566 test quiet option of timeit magic
565 567 """
566 568 with tt.AssertNotPrints("loops"):
567 569 _ip.run_cell("%timeit -n1 -r1 -q 1")
568 570
569 571 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
570 572 def test_timeit_futures():
571 573 "Test %timeit with __future__ environments"
572 574 ip = get_ipython()
573 575 ip.run_cell("from __future__ import division")
574 576 with tt.AssertPrints('0.25'):
575 577 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
576 578 ip.compile.reset_compiler_flags()
577 579 with tt.AssertNotPrints('0.25'):
578 580 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
579 581
580 582 @dec.skipif(execution.profile is None)
581 583 def test_prun_special_syntax():
582 584 "Test %%prun with IPython special syntax"
583 585 @register_line_magic
584 586 def lmagic(line):
585 587 ip = get_ipython()
586 588 ip.user_ns['lmagic_out'] = line
587 589
588 590 # line mode test
589 591 _ip.run_line_magic('prun', '-q %lmagic my line')
590 592 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
591 593 # cell mode test
592 594 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
593 595 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
594 596
595 597 @dec.skipif(execution.profile is None)
596 598 def test_prun_quotes():
597 599 "Test that prun does not clobber string escapes (GH #1302)"
598 600 _ip.magic(r"prun -q x = '\t'")
599 601 nt.assert_equal(_ip.user_ns['x'], '\t')
600 602
601 603 def test_extension():
602 604 tmpdir = TemporaryDirectory()
603 605 orig_ipython_dir = _ip.ipython_dir
604 606 try:
605 607 _ip.ipython_dir = tmpdir.name
606 608 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
607 609 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
608 610 _ip.magic("install_ext %s" % url)
609 611 _ip.user_ns.pop('arq', None)
610 612 invalidate_caches() # Clear import caches
611 613 _ip.magic("load_ext daft_extension")
612 614 nt.assert_equal(_ip.user_ns['arq'], 185)
613 615 _ip.magic("unload_ext daft_extension")
614 616 assert 'arq' not in _ip.user_ns
615 617 finally:
616 618 _ip.ipython_dir = orig_ipython_dir
617 619 tmpdir.cleanup()
618 620
619 621
620 622 # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf
621 623 @skipIf(dec.module_not_available('IPython.nbformat'), 'nbformat not importable')
622 624 class NotebookExportMagicTests(TestCase):
623 625 def test_notebook_export_json(self):
624 626 with TemporaryDirectory() as td:
625 627 outfile = os.path.join(td, "nb.ipynb")
626 628 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
627 629 _ip.magic("notebook -e %s" % outfile)
628 630
629 631
630 632 class TestEnv(TestCase):
631 633
632 634 def test_env(self):
633 635 env = _ip.magic("env")
634 636 self.assertTrue(isinstance(env, dict))
635 637
636 638 def test_env_get_set_simple(self):
637 639 env = _ip.magic("env var val1")
638 640 self.assertEqual(env, None)
639 641 self.assertEqual(os.environ['var'], 'val1')
640 642 self.assertEqual(_ip.magic("env var"), 'val1')
641 643 env = _ip.magic("env var=val2")
642 644 self.assertEqual(env, None)
643 645 self.assertEqual(os.environ['var'], 'val2')
644 646
645 647 def test_env_get_set_complex(self):
646 648 env = _ip.magic("env var 'val1 '' 'val2")
647 649 self.assertEqual(env, None)
648 650 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
649 651 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
650 652 env = _ip.magic('env var=val2 val3="val4')
651 653 self.assertEqual(env, None)
652 654 self.assertEqual(os.environ['var'], 'val2 val3="val4')
653 655
654 656 def test_env_set_bad_input(self):
655 657 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
656 658
657 659 def test_env_set_whitespace(self):
658 660 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
659 661
660 662
661 663 class CellMagicTestCase(TestCase):
662 664
663 665 def check_ident(self, magic):
664 666 # Manually called, we get the result
665 667 out = _ip.run_cell_magic(magic, 'a', 'b')
666 668 nt.assert_equal(out, ('a','b'))
667 669 # Via run_cell, it goes into the user's namespace via displayhook
668 670 _ip.run_cell('%%' + magic +' c\nd')
669 671 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
670 672
671 673 def test_cell_magic_func_deco(self):
672 674 "Cell magic using simple decorator"
673 675 @register_cell_magic
674 676 def cellm(line, cell):
675 677 return line, cell
676 678
677 679 self.check_ident('cellm')
678 680
679 681 def test_cell_magic_reg(self):
680 682 "Cell magic manually registered"
681 683 def cellm(line, cell):
682 684 return line, cell
683 685
684 686 _ip.register_magic_function(cellm, 'cell', 'cellm2')
685 687 self.check_ident('cellm2')
686 688
687 689 def test_cell_magic_class(self):
688 690 "Cell magics declared via a class"
689 691 @magics_class
690 692 class MyMagics(Magics):
691 693
692 694 @cell_magic
693 695 def cellm3(self, line, cell):
694 696 return line, cell
695 697
696 698 _ip.register_magics(MyMagics)
697 699 self.check_ident('cellm3')
698 700
699 701 def test_cell_magic_class2(self):
700 702 "Cell magics declared via a class, #2"
701 703 @magics_class
702 704 class MyMagics2(Magics):
703 705
704 706 @cell_magic('cellm4')
705 707 def cellm33(self, line, cell):
706 708 return line, cell
707 709
708 710 _ip.register_magics(MyMagics2)
709 711 self.check_ident('cellm4')
710 712 # Check that nothing is registered as 'cellm33'
711 713 c33 = _ip.find_cell_magic('cellm33')
712 714 nt.assert_equal(c33, None)
713 715
714 716 def test_file():
715 717 """Basic %%file"""
716 718 ip = get_ipython()
717 719 with TemporaryDirectory() as td:
718 720 fname = os.path.join(td, 'file1')
719 721 ip.run_cell_magic("file", fname, u'\n'.join([
720 722 'line1',
721 723 'line2',
722 724 ]))
723 725 with open(fname) as f:
724 726 s = f.read()
725 727 nt.assert_in('line1\n', s)
726 728 nt.assert_in('line2', s)
727 729
728 730 def test_file_var_expand():
729 731 """%%file $filename"""
730 732 ip = get_ipython()
731 733 with TemporaryDirectory() as td:
732 734 fname = os.path.join(td, 'file1')
733 735 ip.user_ns['filename'] = fname
734 736 ip.run_cell_magic("file", '$filename', u'\n'.join([
735 737 'line1',
736 738 'line2',
737 739 ]))
738 740 with open(fname) as f:
739 741 s = f.read()
740 742 nt.assert_in('line1\n', s)
741 743 nt.assert_in('line2', s)
742 744
743 745 def test_file_unicode():
744 746 """%%file with unicode cell"""
745 747 ip = get_ipython()
746 748 with TemporaryDirectory() as td:
747 749 fname = os.path.join(td, 'file1')
748 750 ip.run_cell_magic("file", fname, u'\n'.join([
749 751 u'linΓ©1',
750 752 u'linΓ©2',
751 753 ]))
752 754 with io.open(fname, encoding='utf-8') as f:
753 755 s = f.read()
754 756 nt.assert_in(u'linΓ©1\n', s)
755 757 nt.assert_in(u'linΓ©2', s)
756 758
757 759 def test_file_amend():
758 760 """%%file -a amends files"""
759 761 ip = get_ipython()
760 762 with TemporaryDirectory() as td:
761 763 fname = os.path.join(td, 'file2')
762 764 ip.run_cell_magic("file", fname, u'\n'.join([
763 765 'line1',
764 766 'line2',
765 767 ]))
766 768 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
767 769 'line3',
768 770 'line4',
769 771 ]))
770 772 with open(fname) as f:
771 773 s = f.read()
772 774 nt.assert_in('line1\n', s)
773 775 nt.assert_in('line3\n', s)
774 776
775 777
776 778 def test_script_config():
777 779 ip = get_ipython()
778 780 ip.config.ScriptMagics.script_magics = ['whoda']
779 781 sm = script.ScriptMagics(shell=ip)
780 782 nt.assert_in('whoda', sm.magics['cell'])
781 783
782 784 @dec.skip_win32
783 785 def test_script_out():
784 786 ip = get_ipython()
785 787 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
786 788 nt.assert_equal(ip.user_ns['output'], 'hi\n')
787 789
788 790 @dec.skip_win32
789 791 def test_script_err():
790 792 ip = get_ipython()
791 793 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
792 794 nt.assert_equal(ip.user_ns['error'], 'hello\n')
793 795
794 796 @dec.skip_win32
795 797 def test_script_out_err():
796 798 ip = get_ipython()
797 799 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
798 800 nt.assert_equal(ip.user_ns['output'], 'hi\n')
799 801 nt.assert_equal(ip.user_ns['error'], 'hello\n')
800 802
801 803 @dec.skip_win32
802 804 def test_script_bg_out():
803 805 ip = get_ipython()
804 806 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
805 807 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
806 808
807 809 @dec.skip_win32
808 810 def test_script_bg_err():
809 811 ip = get_ipython()
810 812 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
811 813 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
812 814
813 815 @dec.skip_win32
814 816 def test_script_bg_out_err():
815 817 ip = get_ipython()
816 818 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
817 819 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
818 820 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
819 821
820 822 def test_script_defaults():
821 823 ip = get_ipython()
822 824 for cmd in ['sh', 'bash', 'perl', 'ruby']:
823 825 try:
824 826 find_cmd(cmd)
825 827 except Exception:
826 828 pass
827 829 else:
828 830 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
829 831
830 832
831 833 @magics_class
832 834 class FooFoo(Magics):
833 835 """class with both %foo and %%foo magics"""
834 836 @line_magic('foo')
835 837 def line_foo(self, line):
836 838 "I am line foo"
837 839 pass
838 840
839 841 @cell_magic("foo")
840 842 def cell_foo(self, line, cell):
841 843 "I am cell foo, not line foo"
842 844 pass
843 845
844 846 def test_line_cell_info():
845 847 """%%foo and %foo magics are distinguishable to inspect"""
846 848 ip = get_ipython()
847 849 ip.magics_manager.register(FooFoo)
848 850 oinfo = ip.object_inspect('foo')
849 851 nt.assert_true(oinfo['found'])
850 852 nt.assert_true(oinfo['ismagic'])
851 853
852 854 oinfo = ip.object_inspect('%%foo')
853 855 nt.assert_true(oinfo['found'])
854 856 nt.assert_true(oinfo['ismagic'])
855 857 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
856 858
857 859 oinfo = ip.object_inspect('%foo')
858 860 nt.assert_true(oinfo['found'])
859 861 nt.assert_true(oinfo['ismagic'])
860 862 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
861 863
862 864 def test_multiple_magics():
863 865 ip = get_ipython()
864 866 foo1 = FooFoo(ip)
865 867 foo2 = FooFoo(ip)
866 868 mm = ip.magics_manager
867 869 mm.register(foo1)
868 870 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
869 871 mm.register(foo2)
870 872 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
871 873
872 874 def test_alias_magic():
873 875 """Test %alias_magic."""
874 876 ip = get_ipython()
875 877 mm = ip.magics_manager
876 878
877 879 # Basic operation: both cell and line magics are created, if possible.
878 880 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
879 881 nt.assert_in('timeit_alias', mm.magics['line'])
880 882 nt.assert_in('timeit_alias', mm.magics['cell'])
881 883
882 884 # --cell is specified, line magic not created.
883 885 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
884 886 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
885 887 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
886 888
887 889 # Test that line alias is created successfully.
888 890 ip.run_line_magic('alias_magic', '--line env_alias env')
889 891 nt.assert_equal(ip.run_line_magic('env', ''),
890 892 ip.run_line_magic('env_alias', ''))
891 893
892 894 def test_save():
893 895 """Test %save."""
894 896 ip = get_ipython()
895 897 ip.history_manager.reset() # Clear any existing history.
896 898 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
897 899 for i, cmd in enumerate(cmds, start=1):
898 900 ip.history_manager.store_inputs(i, cmd)
899 901 with TemporaryDirectory() as tmpdir:
900 902 file = os.path.join(tmpdir, "testsave.py")
901 903 ip.run_line_magic("save", "%s 1-10" % file)
902 904 with open(file) as f:
903 905 content = f.read()
904 906 nt.assert_equal(content.count(cmds[0]), 1)
905 907 nt.assert_in('coding: utf-8', content)
906 908 ip.run_line_magic("save", "-a %s 1-10" % file)
907 909 with open(file) as f:
908 910 content = f.read()
909 911 nt.assert_equal(content.count(cmds[0]), 2)
910 912 nt.assert_in('coding: utf-8', content)
911 913
912 914
913 915 def test_store():
914 916 """Test %store."""
915 917 ip = get_ipython()
916 918 ip.run_line_magic('load_ext', 'storemagic')
917 919
918 920 # make sure the storage is empty
919 921 ip.run_line_magic('store', '-z')
920 922 ip.user_ns['var'] = 42
921 923 ip.run_line_magic('store', 'var')
922 924 ip.user_ns['var'] = 39
923 925 ip.run_line_magic('store', '-r')
924 926 nt.assert_equal(ip.user_ns['var'], 42)
925 927
926 928 ip.run_line_magic('store', '-d var')
927 929 ip.user_ns['var'] = 39
928 930 ip.run_line_magic('store' , '-r')
929 931 nt.assert_equal(ip.user_ns['var'], 39)
930 932
931 933
932 934 def _run_edit_test(arg_s, exp_filename=None,
933 935 exp_lineno=-1,
934 936 exp_contents=None,
935 937 exp_is_temp=None):
936 938 ip = get_ipython()
937 939 M = code.CodeMagics(ip)
938 940 last_call = ['','']
939 941 opts,args = M.parse_options(arg_s,'prxn:')
940 942 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
941 943
942 944 if exp_filename is not None:
943 945 nt.assert_equal(exp_filename, filename)
944 946 if exp_contents is not None:
945 947 with io.open(filename, 'r', encoding='utf-8') as f:
946 948 contents = f.read()
947 949 nt.assert_equal(exp_contents, contents)
948 950 if exp_lineno != -1:
949 951 nt.assert_equal(exp_lineno, lineno)
950 952 if exp_is_temp is not None:
951 953 nt.assert_equal(exp_is_temp, is_temp)
952 954
953 955
954 956 def test_edit_interactive():
955 957 """%edit on interactively defined objects"""
956 958 ip = get_ipython()
957 959 n = ip.execution_count
958 960 ip.run_cell(u"def foo(): return 1", store_history=True)
959 961
960 962 try:
961 963 _run_edit_test("foo")
962 964 except code.InteractivelyDefined as e:
963 965 nt.assert_equal(e.index, n)
964 966 else:
965 967 raise AssertionError("Should have raised InteractivelyDefined")
966 968
967 969
968 970 def test_edit_cell():
969 971 """%edit [cell id]"""
970 972 ip = get_ipython()
971 973
972 974 ip.run_cell(u"def foo(): return 1", store_history=True)
973 975
974 976 # test
975 977 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
976 978
977 979 def test_bookmark():
978 980 ip = get_ipython()
979 981 ip.run_line_magic('bookmark', 'bmname')
980 982 with tt.AssertPrints('bmname'):
981 983 ip.run_line_magic('bookmark', '-l')
982 984 ip.run_line_magic('bookmark', '-d bmname')
985
986 def test_ls_magic():
987 ip = get_ipython()
988 json_formatter = ip.display_formatter.formatters['application/json']
989 json_formatter.enabled = True
990 lsmagic = ip.magic('lsmagic')
991 with warnings.catch_warnings(record=True) as w:
992 j = json_formatter(lsmagic)
993 nt.assert_equal(sorted(j), ['cell', 'line'])
994 nt.assert_equal(w, []) # no warnings
General Comments 0
You need to be logged in to leave comments. Login now