##// END OF EJS Templates
Merge pull request #13820 from jasongrout/mypy...
Jason Grout -
r27873:e783ccd7 merge
parent child Browse files
Show More
@@ -1,658 +1,661 b''
1 1 """Implementation of basic magic functions."""
2 2
3 3
4 4 from logging import error
5 5 import io
6 6 import os
7 7 from pprint import pformat
8 8 import sys
9 9 from warnings import warn
10 10
11 11 from traitlets.utils.importstring import import_item
12 12 from IPython.core import magic_arguments, page
13 13 from IPython.core.error import UsageError
14 14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 15 from IPython.utils.text import format_screen, dedent, indent
16 16 from IPython.testing.skipdoctest import skip_doctest
17 17 from IPython.utils.ipstruct import Struct
18 18
19 19
20 20 class MagicsDisplay(object):
21 21 def __init__(self, magics_manager, ignore=None):
22 22 self.ignore = ignore if ignore else []
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([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 33 '',
34 34 'Available cell magics:',
35 35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
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 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 @skip_doctest
78 78 @magic_arguments.magic_arguments()
79 79 @magic_arguments.argument(
80 80 '-l', '--line', action='store_true',
81 81 help="""Create a line magic alias."""
82 82 )
83 83 @magic_arguments.argument(
84 84 '-c', '--cell', action='store_true',
85 85 help="""Create a cell magic alias."""
86 86 )
87 87 @magic_arguments.argument(
88 88 'name',
89 89 help="""Name of the magic to be created."""
90 90 )
91 91 @magic_arguments.argument(
92 92 'target',
93 93 help="""Name of the existing line or cell magic."""
94 94 )
95 95 @magic_arguments.argument(
96 96 '-p', '--params', default=None,
97 97 help="""Parameters passed to the magic function."""
98 98 )
99 99 @line_magic
100 100 def alias_magic(self, line=''):
101 101 """Create an alias for an existing line or cell magic.
102 102
103 103 Examples
104 104 --------
105 105 ::
106 106
107 107 In [1]: %alias_magic t timeit
108 108 Created `%t` as an alias for `%timeit`.
109 109 Created `%%t` as an alias for `%%timeit`.
110 110
111 111 In [2]: %t -n1 pass
112 112 1 loops, best of 3: 954 ns per loop
113 113
114 114 In [3]: %%t -n1
115 115 ...: pass
116 116 ...:
117 117 1 loops, best of 3: 954 ns per loop
118 118
119 119 In [4]: %alias_magic --cell whereami pwd
120 120 UsageError: Cell magic function `%%pwd` not found.
121 121 In [5]: %alias_magic --line whereami pwd
122 122 Created `%whereami` as an alias for `%pwd`.
123 123
124 124 In [6]: %whereami
125 125 Out[6]: u'/home/testuser'
126 126
127 127 In [7]: %alias_magic h history "-p -l 30" --line
128 128 Created `%h` as an alias for `%history -l 30`.
129 129 """
130 130
131 131 args = magic_arguments.parse_argstring(self.alias_magic, line)
132 132 shell = self.shell
133 133 mman = self.shell.magics_manager
134 134 escs = ''.join(magic_escapes.values())
135 135
136 136 target = args.target.lstrip(escs)
137 137 name = args.name.lstrip(escs)
138 138
139 139 params = args.params
140 140 if (params and
141 141 ((params.startswith('"') and params.endswith('"'))
142 142 or (params.startswith("'") and params.endswith("'")))):
143 143 params = params[1:-1]
144 144
145 145 # Find the requested magics.
146 146 m_line = shell.find_magic(target, 'line')
147 147 m_cell = shell.find_magic(target, 'cell')
148 148 if args.line and m_line is None:
149 149 raise UsageError('Line magic function `%s%s` not found.' %
150 150 (magic_escapes['line'], target))
151 151 if args.cell and m_cell is None:
152 152 raise UsageError('Cell magic function `%s%s` not found.' %
153 153 (magic_escapes['cell'], target))
154 154
155 155 # If --line and --cell are not specified, default to the ones
156 156 # that are available.
157 157 if not args.line and not args.cell:
158 158 if not m_line and not m_cell:
159 159 raise UsageError(
160 160 'No line or cell magic with name `%s` found.' % target
161 161 )
162 162 args.line = bool(m_line)
163 163 args.cell = bool(m_cell)
164 164
165 165 params_str = "" if params is None else " " + params
166 166
167 167 if args.line:
168 168 mman.register_alias(name, target, 'line', params)
169 169 print('Created `%s%s` as an alias for `%s%s%s`.' % (
170 170 magic_escapes['line'], name,
171 171 magic_escapes['line'], target, params_str))
172 172
173 173 if args.cell:
174 174 mman.register_alias(name, target, 'cell', params)
175 175 print('Created `%s%s` as an alias for `%s%s%s`.' % (
176 176 magic_escapes['cell'], name,
177 177 magic_escapes['cell'], target, params_str))
178 178
179 179 @line_magic
180 180 def lsmagic(self, parameter_s=''):
181 181 """List currently available magic functions."""
182 182 return MagicsDisplay(self.shell.magics_manager, ignore=[])
183 183
184 184 def _magic_docs(self, brief=False, rest=False):
185 185 """Return docstrings from magic functions."""
186 186 mman = self.shell.magics_manager
187 187 docs = mman.lsmagic_docs(brief, missing='No documentation')
188 188
189 189 if rest:
190 190 format_string = '**%s%s**::\n\n%s\n\n'
191 191 else:
192 192 format_string = '%s%s:\n%s\n'
193 193
194 194 return ''.join(
195 195 [format_string % (magic_escapes['line'], fname,
196 196 indent(dedent(fndoc)))
197 197 for fname, fndoc in sorted(docs['line'].items())]
198 198 +
199 199 [format_string % (magic_escapes['cell'], fname,
200 200 indent(dedent(fndoc)))
201 201 for fname, fndoc in sorted(docs['cell'].items())]
202 202 )
203 203
204 204 @line_magic
205 205 def magic(self, parameter_s=''):
206 206 """Print information about the magic function system.
207 207
208 208 Supported formats: -latex, -brief, -rest
209 209 """
210 210
211 211 mode = ''
212 212 try:
213 213 mode = parameter_s.split()[0][1:]
214 214 except IndexError:
215 215 pass
216 216
217 217 brief = (mode == 'brief')
218 218 rest = (mode == 'rest')
219 219 magic_docs = self._magic_docs(brief, rest)
220 220
221 221 if mode == 'latex':
222 222 print(self.format_latex(magic_docs))
223 223 return
224 224 else:
225 225 magic_docs = format_screen(magic_docs)
226 226
227 227 out = ["""
228 228 IPython's 'magic' functions
229 229 ===========================
230 230
231 231 The magic function system provides a series of functions which allow you to
232 232 control the behavior of IPython itself, plus a lot of system-type
233 233 features. There are two kinds of magics, line-oriented and cell-oriented.
234 234
235 235 Line magics are prefixed with the % character and work much like OS
236 236 command-line calls: they get as an argument the rest of the line, where
237 237 arguments are passed without parentheses or quotes. For example, this will
238 238 time the given statement::
239 239
240 240 %timeit range(1000)
241 241
242 242 Cell magics are prefixed with a double %%, and they are functions that get as
243 243 an argument not only the rest of the line, but also the lines below it in a
244 244 separate argument. These magics are called with two arguments: the rest of the
245 245 call line and the body of the cell, consisting of the lines below the first.
246 246 For example::
247 247
248 248 %%timeit x = numpy.random.randn((100, 100))
249 249 numpy.linalg.svd(x)
250 250
251 251 will time the execution of the numpy svd routine, running the assignment of x
252 252 as part of the setup phase, which is not timed.
253 253
254 254 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 255 input with %% will automatically enter cell mode, and IPython will continue
256 256 reading input until a blank line is given. In the notebook, simply type the
257 257 whole cell as one entity, but keep in mind that the %% escape can only be at
258 258 the very start of the cell.
259 259
260 260 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 261 %automagic function), you don't need to type in the % explicitly for line
262 262 magics; cell magics always require an explicit '%%' escape. By default,
263 263 IPython ships with automagic on, so you should only rarely need the % escape.
264 264
265 265 Example: typing '%cd mydir' (without the quotes) changes your working directory
266 266 to 'mydir', if it exists.
267 267
268 268 For a list of the available magic functions, use %lsmagic. For a description
269 269 of any of them, type %magic_name?, e.g. '%cd?'.
270 270
271 271 Currently the magic system has the following functions:""",
272 272 magic_docs,
273 273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 274 str(self.lsmagic()),
275 275 ]
276 276 page.page('\n'.join(out))
277 277
278 278
279 279 @line_magic
280 280 def page(self, parameter_s=''):
281 281 """Pretty print the object and display it through a pager.
282 282
283 283 %page [options] OBJECT
284 284
285 285 If no object is given, use _ (last output).
286 286
287 287 Options:
288 288
289 289 -r: page str(object), don't pretty-print it."""
290 290
291 291 # After a function contributed by Olivier Aubert, slightly modified.
292 292
293 293 # Process options/args
294 294 opts, args = self.parse_options(parameter_s, 'r')
295 295 raw = 'r' in opts
296 296
297 297 oname = args and args or '_'
298 298 info = self.shell._ofind(oname)
299 299 if info['found']:
300 txt = (raw and str or pformat)( info['obj'] )
300 if raw:
301 txt = str(info["obj"])
302 else:
303 txt = pformat(info["obj"])
301 304 page.page(txt)
302 305 else:
303 306 print('Object `%s` not found' % oname)
304 307
305 308 @line_magic
306 309 def pprint(self, parameter_s=''):
307 310 """Toggle pretty printing on/off."""
308 311 ptformatter = self.shell.display_formatter.formatters['text/plain']
309 312 ptformatter.pprint = bool(1 - ptformatter.pprint)
310 313 print('Pretty printing has been turned',
311 314 ['OFF','ON'][ptformatter.pprint])
312 315
313 316 @line_magic
314 317 def colors(self, parameter_s=''):
315 318 """Switch color scheme for prompts, info system and exception handlers.
316 319
317 320 Currently implemented schemes: NoColor, Linux, LightBG.
318 321
319 322 Color scheme names are not case-sensitive.
320 323
321 324 Examples
322 325 --------
323 326 To get a plain black and white terminal::
324 327
325 328 %colors nocolor
326 329 """
327 330 def color_switch_err(name):
328 331 warn('Error changing %s color schemes.\n%s' %
329 332 (name, sys.exc_info()[1]), stacklevel=2)
330 333
331 334
332 335 new_scheme = parameter_s.strip()
333 336 if not new_scheme:
334 337 raise UsageError(
335 338 "%colors: you must specify a color scheme. See '%colors?'")
336 339 # local shortcut
337 340 shell = self.shell
338 341
339 342 # Set shell colour scheme
340 343 try:
341 344 shell.colors = new_scheme
342 345 shell.refresh_style()
343 346 except:
344 347 color_switch_err('shell')
345 348
346 349 # Set exception colors
347 350 try:
348 351 shell.InteractiveTB.set_colors(scheme = new_scheme)
349 352 shell.SyntaxTB.set_colors(scheme = new_scheme)
350 353 except:
351 354 color_switch_err('exception')
352 355
353 356 # Set info (for 'object?') colors
354 357 if shell.color_info:
355 358 try:
356 359 shell.inspector.set_active_scheme(new_scheme)
357 360 except:
358 361 color_switch_err('object inspector')
359 362 else:
360 363 shell.inspector.set_active_scheme('NoColor')
361 364
362 365 @line_magic
363 366 def xmode(self, parameter_s=''):
364 367 """Switch modes for the exception handlers.
365 368
366 369 Valid modes: Plain, Context, Verbose, and Minimal.
367 370
368 371 If called without arguments, acts as a toggle.
369 372
370 373 When in verbose mode the value `--show` (and `--hide`)
371 374 will respectively show (or hide) frames with ``__tracebackhide__ =
372 375 True`` value set.
373 376 """
374 377
375 378 def xmode_switch_err(name):
376 379 warn('Error changing %s exception modes.\n%s' %
377 380 (name,sys.exc_info()[1]))
378 381
379 382 shell = self.shell
380 383 if parameter_s.strip() == "--show":
381 384 shell.InteractiveTB.skip_hidden = False
382 385 return
383 386 if parameter_s.strip() == "--hide":
384 387 shell.InteractiveTB.skip_hidden = True
385 388 return
386 389
387 390 new_mode = parameter_s.strip().capitalize()
388 391 try:
389 392 shell.InteractiveTB.set_mode(mode=new_mode)
390 393 print('Exception reporting mode:',shell.InteractiveTB.mode)
391 394 except:
392 395 xmode_switch_err('user')
393 396
394 397 @line_magic
395 398 def quickref(self, arg):
396 399 """ Show a quick reference sheet """
397 400 from IPython.core.usage import quick_reference
398 401 qr = quick_reference + self._magic_docs(brief=True)
399 402 page.page(qr)
400 403
401 404 @line_magic
402 405 def doctest_mode(self, parameter_s=''):
403 406 """Toggle doctest mode on and off.
404 407
405 408 This mode is intended to make IPython behave as much as possible like a
406 409 plain Python shell, from the perspective of how its prompts, exceptions
407 410 and output look. This makes it easy to copy and paste parts of a
408 411 session into doctests. It does so by:
409 412
410 413 - Changing the prompts to the classic ``>>>`` ones.
411 414 - Changing the exception reporting mode to 'Plain'.
412 415 - Disabling pretty-printing of output.
413 416
414 417 Note that IPython also supports the pasting of code snippets that have
415 418 leading '>>>' and '...' prompts in them. This means that you can paste
416 419 doctests from files or docstrings (even if they have leading
417 420 whitespace), and the code will execute correctly. You can then use
418 421 '%history -t' to see the translated history; this will give you the
419 422 input after removal of all the leading prompts and whitespace, which
420 423 can be pasted back into an editor.
421 424
422 425 With these features, you can switch into this mode easily whenever you
423 426 need to do testing and changes to doctests, without having to leave
424 427 your existing IPython session.
425 428 """
426 429
427 430 # Shorthands
428 431 shell = self.shell
429 432 meta = shell.meta
430 433 disp_formatter = self.shell.display_formatter
431 434 ptformatter = disp_formatter.formatters['text/plain']
432 435 # dstore is a data store kept in the instance metadata bag to track any
433 436 # changes we make, so we can undo them later.
434 437 dstore = meta.setdefault('doctest_mode',Struct())
435 438 save_dstore = dstore.setdefault
436 439
437 440 # save a few values we'll need to recover later
438 441 mode = save_dstore('mode',False)
439 442 save_dstore('rc_pprint',ptformatter.pprint)
440 443 save_dstore('xmode',shell.InteractiveTB.mode)
441 444 save_dstore('rc_separate_out',shell.separate_out)
442 445 save_dstore('rc_separate_out2',shell.separate_out2)
443 446 save_dstore('rc_separate_in',shell.separate_in)
444 447 save_dstore('rc_active_types',disp_formatter.active_types)
445 448
446 449 if not mode:
447 450 # turn on
448 451
449 452 # Prompt separators like plain python
450 453 shell.separate_in = ''
451 454 shell.separate_out = ''
452 455 shell.separate_out2 = ''
453 456
454 457
455 458 ptformatter.pprint = False
456 459 disp_formatter.active_types = ['text/plain']
457 460
458 461 shell.magic('xmode Plain')
459 462 else:
460 463 # turn off
461 464 shell.separate_in = dstore.rc_separate_in
462 465
463 466 shell.separate_out = dstore.rc_separate_out
464 467 shell.separate_out2 = dstore.rc_separate_out2
465 468
466 469 ptformatter.pprint = dstore.rc_pprint
467 470 disp_formatter.active_types = dstore.rc_active_types
468 471
469 472 shell.magic('xmode ' + dstore.xmode)
470 473
471 474 # mode here is the state before we switch; switch_doctest_mode takes
472 475 # the mode we're switching to.
473 476 shell.switch_doctest_mode(not mode)
474 477
475 478 # Store new mode and inform
476 479 dstore.mode = bool(not mode)
477 480 mode_label = ['OFF','ON'][dstore.mode]
478 481 print('Doctest mode is:', mode_label)
479 482
480 483 @line_magic
481 484 def gui(self, parameter_s=''):
482 485 """Enable or disable IPython GUI event loop integration.
483 486
484 487 %gui [GUINAME]
485 488
486 489 This magic replaces IPython's threaded shells that were activated
487 490 using the (pylab/wthread/etc.) command line flags. GUI toolkits
488 491 can now be enabled at runtime and keyboard
489 492 interrupts should work without any problems. The following toolkits
490 493 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
491 494
492 495 %gui wx # enable wxPython event loop integration
493 496 %gui qt4|qt # enable PyQt4 event loop integration
494 497 %gui qt5 # enable PyQt5 event loop integration
495 498 %gui gtk # enable PyGTK event loop integration
496 499 %gui gtk3 # enable Gtk3 event loop integration
497 500 %gui gtk4 # enable Gtk4 event loop integration
498 501 %gui tk # enable Tk event loop integration
499 502 %gui osx # enable Cocoa event loop integration
500 503 # (requires %matplotlib 1.1)
501 504 %gui # disable all event loop integration
502 505
503 506 WARNING: after any of these has been called you can simply create
504 507 an application object, but DO NOT start the event loop yourself, as
505 508 we have already handled that.
506 509 """
507 510 opts, arg = self.parse_options(parameter_s, '')
508 511 if arg=='': arg = None
509 512 try:
510 513 return self.shell.enable_gui(arg)
511 514 except Exception as e:
512 515 # print simple error message, rather than traceback if we can't
513 516 # hook up the GUI
514 517 error(str(e))
515 518
516 519 @skip_doctest
517 520 @line_magic
518 521 def precision(self, s=''):
519 522 """Set floating point precision for pretty printing.
520 523
521 524 Can set either integer precision or a format string.
522 525
523 526 If numpy has been imported and precision is an int,
524 527 numpy display precision will also be set, via ``numpy.set_printoptions``.
525 528
526 529 If no argument is given, defaults will be restored.
527 530
528 531 Examples
529 532 --------
530 533 ::
531 534
532 535 In [1]: from math import pi
533 536
534 537 In [2]: %precision 3
535 538 Out[2]: u'%.3f'
536 539
537 540 In [3]: pi
538 541 Out[3]: 3.142
539 542
540 543 In [4]: %precision %i
541 544 Out[4]: u'%i'
542 545
543 546 In [5]: pi
544 547 Out[5]: 3
545 548
546 549 In [6]: %precision %e
547 550 Out[6]: u'%e'
548 551
549 552 In [7]: pi**10
550 553 Out[7]: 9.364805e+04
551 554
552 555 In [8]: %precision
553 556 Out[8]: u'%r'
554 557
555 558 In [9]: pi**10
556 559 Out[9]: 93648.047476082982
557 560 """
558 561 ptformatter = self.shell.display_formatter.formatters['text/plain']
559 562 ptformatter.float_precision = s
560 563 return ptformatter.float_format
561 564
562 565 @magic_arguments.magic_arguments()
563 566 @magic_arguments.argument(
564 567 'filename', type=str,
565 568 help='Notebook name or filename'
566 569 )
567 570 @line_magic
568 571 def notebook(self, s):
569 572 """Export and convert IPython notebooks.
570 573
571 574 This function can export the current IPython history to a notebook file.
572 575 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
573 576 """
574 577 args = magic_arguments.parse_argstring(self.notebook, s)
575 578 outfname = os.path.expanduser(args.filename)
576 579
577 580 from nbformat import write, v4
578 581
579 582 cells = []
580 583 hist = list(self.shell.history_manager.get_range())
581 584 if(len(hist)<=1):
582 585 raise ValueError('History is empty, cannot export')
583 586 for session, execution_count, source in hist[:-1]:
584 587 cells.append(v4.new_code_cell(
585 588 execution_count=execution_count,
586 589 source=source
587 590 ))
588 591 nb = v4.new_notebook(cells=cells)
589 592 with io.open(outfname, "w", encoding="utf-8") as f:
590 593 write(nb, f, version=4)
591 594
592 595 @magics_class
593 596 class AsyncMagics(BasicMagics):
594 597
595 598 @line_magic
596 599 def autoawait(self, parameter_s):
597 600 """
598 601 Allow to change the status of the autoawait option.
599 602
600 603 This allow you to set a specific asynchronous code runner.
601 604
602 605 If no value is passed, print the currently used asynchronous integration
603 606 and whether it is activated.
604 607
605 608 It can take a number of value evaluated in the following order:
606 609
607 610 - False/false/off deactivate autoawait integration
608 611 - True/true/on activate autoawait integration using configured default
609 612 loop
610 613 - asyncio/curio/trio activate autoawait integration and use integration
611 614 with said library.
612 615
613 616 - `sync` turn on the pseudo-sync integration (mostly used for
614 617 `IPython.embed()` which does not run IPython with a real eventloop and
615 618 deactivate running asynchronous code. Turning on Asynchronous code with
616 619 the pseudo sync loop is undefined behavior and may lead IPython to crash.
617 620
618 621 If the passed parameter does not match any of the above and is a python
619 622 identifier, get said object from user namespace and set it as the
620 623 runner, and activate autoawait.
621 624
622 625 If the object is a fully qualified object name, attempt to import it and
623 626 set it as the runner, and activate autoawait.
624 627
625 628 The exact behavior of autoawait is experimental and subject to change
626 629 across version of IPython and Python.
627 630 """
628 631
629 632 param = parameter_s.strip()
630 633 d = {True: "on", False: "off"}
631 634
632 635 if not param:
633 636 print("IPython autoawait is `{}`, and set to use `{}`".format(
634 637 d[self.shell.autoawait],
635 638 self.shell.loop_runner
636 639 ))
637 640 return None
638 641
639 642 if param.lower() in ('false', 'off'):
640 643 self.shell.autoawait = False
641 644 return None
642 645 if param.lower() in ('true', 'on'):
643 646 self.shell.autoawait = True
644 647 return None
645 648
646 649 if param in self.shell.loop_runner_map:
647 650 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
648 651 return None
649 652
650 653 if param in self.shell.user_ns :
651 654 self.shell.loop_runner = self.shell.user_ns[param]
652 655 self.shell.autoawait = True
653 656 return None
654 657
655 658 runner = import_item(param)
656 659
657 660 self.shell.loop_runner = runner
658 661 self.shell.autoawait = True
General Comments 0
You need to be logged in to leave comments. Login now