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