Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
42
venv/Lib/site-packages/IPython/core/magics/__init__.py
Normal file
42
venv/Lib/site-packages/IPython/core/magics/__init__.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
"""Implementation of all the magic functions built into IPython.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
from ..magic import Magics, magics_class
|
||||
from .auto import AutoMagics
|
||||
from .basic import BasicMagics, AsyncMagics
|
||||
from .code import CodeMagics, MacroToEdit
|
||||
from .config import ConfigMagics
|
||||
from .display import DisplayMagics
|
||||
from .execution import ExecutionMagics
|
||||
from .extension import ExtensionMagics
|
||||
from .history import HistoryMagics
|
||||
from .logging import LoggingMagics
|
||||
from .namespace import NamespaceMagics
|
||||
from .osm import OSMagics
|
||||
from .packaging import PackagingMagics
|
||||
from .pylab import PylabMagics
|
||||
from .script import ScriptMagics
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@magics_class
|
||||
class UserMagics(Magics):
|
||||
"""Placeholder for user-defined magics to be added at runtime.
|
||||
|
||||
All magics are eventually merged into a single namespace at runtime, but we
|
||||
use this class to isolate the magics defined dynamically by the user into
|
||||
their own class.
|
||||
"""
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
128
venv/Lib/site-packages/IPython/core/magics/auto.py
Normal file
128
venv/Lib/site-packages/IPython/core/magics/auto.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
"""Implementation of magic functions that control various automatic behaviors.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.magic import Bunch, Magics, magics_class, line_magic
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from logging import error
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@magics_class
|
||||
class AutoMagics(Magics):
|
||||
"""Magics that control various autoX behaviors."""
|
||||
|
||||
def __init__(self, shell):
|
||||
super(AutoMagics, self).__init__(shell)
|
||||
# namespace for holding state we may need
|
||||
self._magic_state = Bunch()
|
||||
|
||||
@line_magic
|
||||
def automagic(self, parameter_s=''):
|
||||
"""Make magic functions callable without having to type the initial %.
|
||||
|
||||
Without arguments toggles on/off (when off, you must call it as
|
||||
%automagic, of course). With arguments it sets the value, and you can
|
||||
use any of (case insensitive):
|
||||
|
||||
- on, 1, True: to activate
|
||||
|
||||
- off, 0, False: to deactivate.
|
||||
|
||||
Note that magic functions have lowest priority, so if there's a
|
||||
variable whose name collides with that of a magic fn, automagic won't
|
||||
work for that function (you get the variable instead). However, if you
|
||||
delete the variable (del var), the previously shadowed magic function
|
||||
becomes visible to automagic again."""
|
||||
|
||||
arg = parameter_s.lower()
|
||||
mman = self.shell.magics_manager
|
||||
if arg in ('on', '1', 'true'):
|
||||
val = True
|
||||
elif arg in ('off', '0', 'false'):
|
||||
val = False
|
||||
else:
|
||||
val = not mman.auto_magic
|
||||
mman.auto_magic = val
|
||||
print('\n' + self.shell.magics_manager.auto_status())
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def autocall(self, parameter_s=''):
|
||||
"""Make functions callable without having to type parentheses.
|
||||
|
||||
Usage:
|
||||
|
||||
%autocall [mode]
|
||||
|
||||
The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
|
||||
value is toggled on and off (remembering the previous state).
|
||||
|
||||
In more detail, these values mean:
|
||||
|
||||
0 -> fully disabled
|
||||
|
||||
1 -> active, but do not apply if there are no arguments on the line.
|
||||
|
||||
In this mode, you get::
|
||||
|
||||
In [1]: callable
|
||||
Out[1]: <built-in function callable>
|
||||
|
||||
In [2]: callable 'hello'
|
||||
------> callable('hello')
|
||||
Out[2]: False
|
||||
|
||||
2 -> Active always. Even if no arguments are present, the callable
|
||||
object is called::
|
||||
|
||||
In [2]: float
|
||||
------> float()
|
||||
Out[2]: 0.0
|
||||
|
||||
Note that even with autocall off, you can still use '/' at the start of
|
||||
a line to treat the first argument on the command line as a function
|
||||
and add parentheses to it::
|
||||
|
||||
In [8]: /str 43
|
||||
------> str(43)
|
||||
Out[8]: '43'
|
||||
|
||||
# all-random (note for auto-testing)
|
||||
"""
|
||||
|
||||
if parameter_s:
|
||||
arg = int(parameter_s)
|
||||
else:
|
||||
arg = 'toggle'
|
||||
|
||||
if not arg in (0, 1, 2, 'toggle'):
|
||||
error('Valid modes: (0->Off, 1->Smart, 2->Full')
|
||||
return
|
||||
|
||||
if arg in (0, 1, 2):
|
||||
self.shell.autocall = arg
|
||||
else: # toggle
|
||||
if self.shell.autocall:
|
||||
self._magic_state.autocall_save = self.shell.autocall
|
||||
self.shell.autocall = 0
|
||||
else:
|
||||
try:
|
||||
self.shell.autocall = self._magic_state.autocall_save
|
||||
except AttributeError:
|
||||
self.shell.autocall = self._magic_state.autocall_save = 1
|
||||
|
||||
print("Automatic calling is:",['OFF','Smart','Full'][self.shell.autocall])
|
663
venv/Lib/site-packages/IPython/core/magics/basic.py
Normal file
663
venv/Lib/site-packages/IPython/core/magics/basic.py
Normal file
|
@ -0,0 +1,663 @@
|
|||
"""Implementation of basic magic functions."""
|
||||
|
||||
|
||||
import argparse
|
||||
from logging import error
|
||||
import io
|
||||
from pprint import pformat
|
||||
import sys
|
||||
from warnings import warn
|
||||
|
||||
from traitlets.utils.importstring import import_item
|
||||
from IPython.core import magic_arguments, page
|
||||
from IPython.core.error import UsageError
|
||||
from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
|
||||
from IPython.utils.text import format_screen, dedent, indent
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from IPython.utils.ipstruct import Struct
|
||||
|
||||
|
||||
class MagicsDisplay(object):
|
||||
def __init__(self, magics_manager, ignore=None):
|
||||
self.ignore = ignore if ignore else []
|
||||
self.magics_manager = magics_manager
|
||||
|
||||
def _lsmagic(self):
|
||||
"""The main implementation of the %lsmagic"""
|
||||
mesc = magic_escapes['line']
|
||||
cesc = magic_escapes['cell']
|
||||
mman = self.magics_manager
|
||||
magics = mman.lsmagic()
|
||||
out = ['Available line magics:',
|
||||
mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
|
||||
'',
|
||||
'Available cell magics:',
|
||||
cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
|
||||
'',
|
||||
mman.auto_status()]
|
||||
return '\n'.join(out)
|
||||
|
||||
def _repr_pretty_(self, p, cycle):
|
||||
p.text(self._lsmagic())
|
||||
|
||||
def __str__(self):
|
||||
return self._lsmagic()
|
||||
|
||||
def _jsonable(self):
|
||||
"""turn magics dict into jsonable dict of the same structure
|
||||
|
||||
replaces object instances with their class names as strings
|
||||
"""
|
||||
magic_dict = {}
|
||||
mman = self.magics_manager
|
||||
magics = mman.lsmagic()
|
||||
for key, subdict in magics.items():
|
||||
d = {}
|
||||
magic_dict[key] = d
|
||||
for name, obj in subdict.items():
|
||||
try:
|
||||
classname = obj.__self__.__class__.__name__
|
||||
except AttributeError:
|
||||
classname = 'Other'
|
||||
|
||||
d[name] = classname
|
||||
return magic_dict
|
||||
|
||||
def _repr_json_(self):
|
||||
return self._jsonable()
|
||||
|
||||
|
||||
@magics_class
|
||||
class BasicMagics(Magics):
|
||||
"""Magics that provide central IPython functionality.
|
||||
|
||||
These are various magics that don't fit into specific categories but that
|
||||
are all part of the base 'IPython experience'."""
|
||||
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument(
|
||||
'-l', '--line', action='store_true',
|
||||
help="""Create a line magic alias."""
|
||||
)
|
||||
@magic_arguments.argument(
|
||||
'-c', '--cell', action='store_true',
|
||||
help="""Create a cell magic alias."""
|
||||
)
|
||||
@magic_arguments.argument(
|
||||
'name',
|
||||
help="""Name of the magic to be created."""
|
||||
)
|
||||
@magic_arguments.argument(
|
||||
'target',
|
||||
help="""Name of the existing line or cell magic."""
|
||||
)
|
||||
@magic_arguments.argument(
|
||||
'-p', '--params', default=None,
|
||||
help="""Parameters passed to the magic function."""
|
||||
)
|
||||
@line_magic
|
||||
def alias_magic(self, line=''):
|
||||
"""Create an alias for an existing line or cell magic.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [1]: %alias_magic t timeit
|
||||
Created `%t` as an alias for `%timeit`.
|
||||
Created `%%t` as an alias for `%%timeit`.
|
||||
|
||||
In [2]: %t -n1 pass
|
||||
1 loops, best of 3: 954 ns per loop
|
||||
|
||||
In [3]: %%t -n1
|
||||
...: pass
|
||||
...:
|
||||
1 loops, best of 3: 954 ns per loop
|
||||
|
||||
In [4]: %alias_magic --cell whereami pwd
|
||||
UsageError: Cell magic function `%%pwd` not found.
|
||||
In [5]: %alias_magic --line whereami pwd
|
||||
Created `%whereami` as an alias for `%pwd`.
|
||||
|
||||
In [6]: %whereami
|
||||
Out[6]: u'/home/testuser'
|
||||
|
||||
In [7]: %alias_magic h history "-p -l 30" --line
|
||||
Created `%h` as an alias for `%history -l 30`.
|
||||
"""
|
||||
|
||||
args = magic_arguments.parse_argstring(self.alias_magic, line)
|
||||
shell = self.shell
|
||||
mman = self.shell.magics_manager
|
||||
escs = ''.join(magic_escapes.values())
|
||||
|
||||
target = args.target.lstrip(escs)
|
||||
name = args.name.lstrip(escs)
|
||||
|
||||
params = args.params
|
||||
if (params and
|
||||
((params.startswith('"') and params.endswith('"'))
|
||||
or (params.startswith("'") and params.endswith("'")))):
|
||||
params = params[1:-1]
|
||||
|
||||
# Find the requested magics.
|
||||
m_line = shell.find_magic(target, 'line')
|
||||
m_cell = shell.find_magic(target, 'cell')
|
||||
if args.line and m_line is None:
|
||||
raise UsageError('Line magic function `%s%s` not found.' %
|
||||
(magic_escapes['line'], target))
|
||||
if args.cell and m_cell is None:
|
||||
raise UsageError('Cell magic function `%s%s` not found.' %
|
||||
(magic_escapes['cell'], target))
|
||||
|
||||
# If --line and --cell are not specified, default to the ones
|
||||
# that are available.
|
||||
if not args.line and not args.cell:
|
||||
if not m_line and not m_cell:
|
||||
raise UsageError(
|
||||
'No line or cell magic with name `%s` found.' % target
|
||||
)
|
||||
args.line = bool(m_line)
|
||||
args.cell = bool(m_cell)
|
||||
|
||||
params_str = "" if params is None else " " + params
|
||||
|
||||
if args.line:
|
||||
mman.register_alias(name, target, 'line', params)
|
||||
print('Created `%s%s` as an alias for `%s%s%s`.' % (
|
||||
magic_escapes['line'], name,
|
||||
magic_escapes['line'], target, params_str))
|
||||
|
||||
if args.cell:
|
||||
mman.register_alias(name, target, 'cell', params)
|
||||
print('Created `%s%s` as an alias for `%s%s%s`.' % (
|
||||
magic_escapes['cell'], name,
|
||||
magic_escapes['cell'], target, params_str))
|
||||
|
||||
@line_magic
|
||||
def lsmagic(self, parameter_s=''):
|
||||
"""List currently available magic functions."""
|
||||
return MagicsDisplay(self.shell.magics_manager, ignore=[])
|
||||
|
||||
def _magic_docs(self, brief=False, rest=False):
|
||||
"""Return docstrings from magic functions."""
|
||||
mman = self.shell.magics_manager
|
||||
docs = mman.lsmagic_docs(brief, missing='No documentation')
|
||||
|
||||
if rest:
|
||||
format_string = '**%s%s**::\n\n%s\n\n'
|
||||
else:
|
||||
format_string = '%s%s:\n%s\n'
|
||||
|
||||
return ''.join(
|
||||
[format_string % (magic_escapes['line'], fname,
|
||||
indent(dedent(fndoc)))
|
||||
for fname, fndoc in sorted(docs['line'].items())]
|
||||
+
|
||||
[format_string % (magic_escapes['cell'], fname,
|
||||
indent(dedent(fndoc)))
|
||||
for fname, fndoc in sorted(docs['cell'].items())]
|
||||
)
|
||||
|
||||
@line_magic
|
||||
def magic(self, parameter_s=''):
|
||||
"""Print information about the magic function system.
|
||||
|
||||
Supported formats: -latex, -brief, -rest
|
||||
"""
|
||||
|
||||
mode = ''
|
||||
try:
|
||||
mode = parameter_s.split()[0][1:]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
brief = (mode == 'brief')
|
||||
rest = (mode == 'rest')
|
||||
magic_docs = self._magic_docs(brief, rest)
|
||||
|
||||
if mode == 'latex':
|
||||
print(self.format_latex(magic_docs))
|
||||
return
|
||||
else:
|
||||
magic_docs = format_screen(magic_docs)
|
||||
|
||||
out = ["""
|
||||
IPython's 'magic' functions
|
||||
===========================
|
||||
|
||||
The magic function system provides a series of functions which allow you to
|
||||
control the behavior of IPython itself, plus a lot of system-type
|
||||
features. There are two kinds of magics, line-oriented and cell-oriented.
|
||||
|
||||
Line magics are prefixed with the % character and work much like OS
|
||||
command-line calls: they get as an argument the rest of the line, where
|
||||
arguments are passed without parentheses or quotes. For example, this will
|
||||
time the given statement::
|
||||
|
||||
%timeit range(1000)
|
||||
|
||||
Cell magics are prefixed with a double %%, and they are functions that get as
|
||||
an argument not only the rest of the line, but also the lines below it in a
|
||||
separate argument. These magics are called with two arguments: the rest of the
|
||||
call line and the body of the cell, consisting of the lines below the first.
|
||||
For example::
|
||||
|
||||
%%timeit x = numpy.random.randn((100, 100))
|
||||
numpy.linalg.svd(x)
|
||||
|
||||
will time the execution of the numpy svd routine, running the assignment of x
|
||||
as part of the setup phase, which is not timed.
|
||||
|
||||
In a line-oriented client (the terminal or Qt console IPython), starting a new
|
||||
input with %% will automatically enter cell mode, and IPython will continue
|
||||
reading input until a blank line is given. In the notebook, simply type the
|
||||
whole cell as one entity, but keep in mind that the %% escape can only be at
|
||||
the very start of the cell.
|
||||
|
||||
NOTE: If you have 'automagic' enabled (via the command line option or with the
|
||||
%automagic function), you don't need to type in the % explicitly for line
|
||||
magics; cell magics always require an explicit '%%' escape. By default,
|
||||
IPython ships with automagic on, so you should only rarely need the % escape.
|
||||
|
||||
Example: typing '%cd mydir' (without the quotes) changes your working directory
|
||||
to 'mydir', if it exists.
|
||||
|
||||
For a list of the available magic functions, use %lsmagic. For a description
|
||||
of any of them, type %magic_name?, e.g. '%cd?'.
|
||||
|
||||
Currently the magic system has the following functions:""",
|
||||
magic_docs,
|
||||
"Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
|
||||
str(self.lsmagic()),
|
||||
]
|
||||
page.page('\n'.join(out))
|
||||
|
||||
|
||||
@line_magic
|
||||
def page(self, parameter_s=''):
|
||||
"""Pretty print the object and display it through a pager.
|
||||
|
||||
%page [options] OBJECT
|
||||
|
||||
If no object is given, use _ (last output).
|
||||
|
||||
Options:
|
||||
|
||||
-r: page str(object), don't pretty-print it."""
|
||||
|
||||
# After a function contributed by Olivier Aubert, slightly modified.
|
||||
|
||||
# Process options/args
|
||||
opts, args = self.parse_options(parameter_s, 'r')
|
||||
raw = 'r' in opts
|
||||
|
||||
oname = args and args or '_'
|
||||
info = self.shell._ofind(oname)
|
||||
if info['found']:
|
||||
txt = (raw and str or pformat)( info['obj'] )
|
||||
page.page(txt)
|
||||
else:
|
||||
print('Object `%s` not found' % oname)
|
||||
|
||||
@line_magic
|
||||
def pprint(self, parameter_s=''):
|
||||
"""Toggle pretty printing on/off."""
|
||||
ptformatter = self.shell.display_formatter.formatters['text/plain']
|
||||
ptformatter.pprint = bool(1 - ptformatter.pprint)
|
||||
print('Pretty printing has been turned',
|
||||
['OFF','ON'][ptformatter.pprint])
|
||||
|
||||
@line_magic
|
||||
def colors(self, parameter_s=''):
|
||||
"""Switch color scheme for prompts, info system and exception handlers.
|
||||
|
||||
Currently implemented schemes: NoColor, Linux, LightBG.
|
||||
|
||||
Color scheme names are not case-sensitive.
|
||||
|
||||
Examples
|
||||
--------
|
||||
To get a plain black and white terminal::
|
||||
|
||||
%colors nocolor
|
||||
"""
|
||||
def color_switch_err(name):
|
||||
warn('Error changing %s color schemes.\n%s' %
|
||||
(name, sys.exc_info()[1]), stacklevel=2)
|
||||
|
||||
|
||||
new_scheme = parameter_s.strip()
|
||||
if not new_scheme:
|
||||
raise UsageError(
|
||||
"%colors: you must specify a color scheme. See '%colors?'")
|
||||
# local shortcut
|
||||
shell = self.shell
|
||||
|
||||
# Set shell colour scheme
|
||||
try:
|
||||
shell.colors = new_scheme
|
||||
shell.refresh_style()
|
||||
except:
|
||||
color_switch_err('shell')
|
||||
|
||||
# Set exception colors
|
||||
try:
|
||||
shell.InteractiveTB.set_colors(scheme = new_scheme)
|
||||
shell.SyntaxTB.set_colors(scheme = new_scheme)
|
||||
except:
|
||||
color_switch_err('exception')
|
||||
|
||||
# Set info (for 'object?') colors
|
||||
if shell.color_info:
|
||||
try:
|
||||
shell.inspector.set_active_scheme(new_scheme)
|
||||
except:
|
||||
color_switch_err('object inspector')
|
||||
else:
|
||||
shell.inspector.set_active_scheme('NoColor')
|
||||
|
||||
@line_magic
|
||||
def xmode(self, parameter_s=''):
|
||||
"""Switch modes for the exception handlers.
|
||||
|
||||
Valid modes: Plain, Context, Verbose, and Minimal.
|
||||
|
||||
If called without arguments, acts as a toggle.
|
||||
|
||||
When in verbose mode the value --show (and --hide)
|
||||
will respectively show (or hide) frames with ``__tracebackhide__ =
|
||||
True`` value set.
|
||||
"""
|
||||
|
||||
def xmode_switch_err(name):
|
||||
warn('Error changing %s exception modes.\n%s' %
|
||||
(name,sys.exc_info()[1]))
|
||||
|
||||
shell = self.shell
|
||||
if parameter_s.strip() == "--show":
|
||||
shell.InteractiveTB.skip_hidden = False
|
||||
return
|
||||
if parameter_s.strip() == "--hide":
|
||||
shell.InteractiveTB.skip_hidden = True
|
||||
return
|
||||
|
||||
new_mode = parameter_s.strip().capitalize()
|
||||
try:
|
||||
shell.InteractiveTB.set_mode(mode=new_mode)
|
||||
print('Exception reporting mode:',shell.InteractiveTB.mode)
|
||||
except:
|
||||
xmode_switch_err('user')
|
||||
|
||||
@line_magic
|
||||
def quickref(self, arg):
|
||||
""" Show a quick reference sheet """
|
||||
from IPython.core.usage import quick_reference
|
||||
qr = quick_reference + self._magic_docs(brief=True)
|
||||
page.page(qr)
|
||||
|
||||
@line_magic
|
||||
def doctest_mode(self, parameter_s=''):
|
||||
"""Toggle doctest mode on and off.
|
||||
|
||||
This mode is intended to make IPython behave as much as possible like a
|
||||
plain Python shell, from the perspective of how its prompts, exceptions
|
||||
and output look. This makes it easy to copy and paste parts of a
|
||||
session into doctests. It does so by:
|
||||
|
||||
- Changing the prompts to the classic ``>>>`` ones.
|
||||
- Changing the exception reporting mode to 'Plain'.
|
||||
- Disabling pretty-printing of output.
|
||||
|
||||
Note that IPython also supports the pasting of code snippets that have
|
||||
leading '>>>' and '...' prompts in them. This means that you can paste
|
||||
doctests from files or docstrings (even if they have leading
|
||||
whitespace), and the code will execute correctly. You can then use
|
||||
'%history -t' to see the translated history; this will give you the
|
||||
input after removal of all the leading prompts and whitespace, which
|
||||
can be pasted back into an editor.
|
||||
|
||||
With these features, you can switch into this mode easily whenever you
|
||||
need to do testing and changes to doctests, without having to leave
|
||||
your existing IPython session.
|
||||
"""
|
||||
|
||||
# Shorthands
|
||||
shell = self.shell
|
||||
meta = shell.meta
|
||||
disp_formatter = self.shell.display_formatter
|
||||
ptformatter = disp_formatter.formatters['text/plain']
|
||||
# dstore is a data store kept in the instance metadata bag to track any
|
||||
# changes we make, so we can undo them later.
|
||||
dstore = meta.setdefault('doctest_mode',Struct())
|
||||
save_dstore = dstore.setdefault
|
||||
|
||||
# save a few values we'll need to recover later
|
||||
mode = save_dstore('mode',False)
|
||||
save_dstore('rc_pprint',ptformatter.pprint)
|
||||
save_dstore('xmode',shell.InteractiveTB.mode)
|
||||
save_dstore('rc_separate_out',shell.separate_out)
|
||||
save_dstore('rc_separate_out2',shell.separate_out2)
|
||||
save_dstore('rc_separate_in',shell.separate_in)
|
||||
save_dstore('rc_active_types',disp_formatter.active_types)
|
||||
|
||||
if not mode:
|
||||
# turn on
|
||||
|
||||
# Prompt separators like plain python
|
||||
shell.separate_in = ''
|
||||
shell.separate_out = ''
|
||||
shell.separate_out2 = ''
|
||||
|
||||
|
||||
ptformatter.pprint = False
|
||||
disp_formatter.active_types = ['text/plain']
|
||||
|
||||
shell.magic('xmode Plain')
|
||||
else:
|
||||
# turn off
|
||||
shell.separate_in = dstore.rc_separate_in
|
||||
|
||||
shell.separate_out = dstore.rc_separate_out
|
||||
shell.separate_out2 = dstore.rc_separate_out2
|
||||
|
||||
ptformatter.pprint = dstore.rc_pprint
|
||||
disp_formatter.active_types = dstore.rc_active_types
|
||||
|
||||
shell.magic('xmode ' + dstore.xmode)
|
||||
|
||||
# mode here is the state before we switch; switch_doctest_mode takes
|
||||
# the mode we're switching to.
|
||||
shell.switch_doctest_mode(not mode)
|
||||
|
||||
# Store new mode and inform
|
||||
dstore.mode = bool(not mode)
|
||||
mode_label = ['OFF','ON'][dstore.mode]
|
||||
print('Doctest mode is:', mode_label)
|
||||
|
||||
@line_magic
|
||||
def gui(self, parameter_s=''):
|
||||
"""Enable or disable IPython GUI event loop integration.
|
||||
|
||||
%gui [GUINAME]
|
||||
|
||||
This magic replaces IPython's threaded shells that were activated
|
||||
using the (pylab/wthread/etc.) command line flags. GUI toolkits
|
||||
can now be enabled at runtime and keyboard
|
||||
interrupts should work without any problems. The following toolkits
|
||||
are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
|
||||
|
||||
%gui wx # enable wxPython event loop integration
|
||||
%gui qt4|qt # enable PyQt4 event loop integration
|
||||
%gui qt5 # enable PyQt5 event loop integration
|
||||
%gui gtk # enable PyGTK event loop integration
|
||||
%gui gtk3 # enable Gtk3 event loop integration
|
||||
%gui tk # enable Tk event loop integration
|
||||
%gui osx # enable Cocoa event loop integration
|
||||
# (requires %matplotlib 1.1)
|
||||
%gui # disable all event loop integration
|
||||
|
||||
WARNING: after any of these has been called you can simply create
|
||||
an application object, but DO NOT start the event loop yourself, as
|
||||
we have already handled that.
|
||||
"""
|
||||
opts, arg = self.parse_options(parameter_s, '')
|
||||
if arg=='': arg = None
|
||||
try:
|
||||
return self.shell.enable_gui(arg)
|
||||
except Exception as e:
|
||||
# print simple error message, rather than traceback if we can't
|
||||
# hook up the GUI
|
||||
error(str(e))
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def precision(self, s=''):
|
||||
"""Set floating point precision for pretty printing.
|
||||
|
||||
Can set either integer precision or a format string.
|
||||
|
||||
If numpy has been imported and precision is an int,
|
||||
numpy display precision will also be set, via ``numpy.set_printoptions``.
|
||||
|
||||
If no argument is given, defaults will be restored.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [1]: from math import pi
|
||||
|
||||
In [2]: %precision 3
|
||||
Out[2]: u'%.3f'
|
||||
|
||||
In [3]: pi
|
||||
Out[3]: 3.142
|
||||
|
||||
In [4]: %precision %i
|
||||
Out[4]: u'%i'
|
||||
|
||||
In [5]: pi
|
||||
Out[5]: 3
|
||||
|
||||
In [6]: %precision %e
|
||||
Out[6]: u'%e'
|
||||
|
||||
In [7]: pi**10
|
||||
Out[7]: 9.364805e+04
|
||||
|
||||
In [8]: %precision
|
||||
Out[8]: u'%r'
|
||||
|
||||
In [9]: pi**10
|
||||
Out[9]: 93648.047476082982
|
||||
"""
|
||||
ptformatter = self.shell.display_formatter.formatters['text/plain']
|
||||
ptformatter.float_precision = s
|
||||
return ptformatter.float_format
|
||||
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument(
|
||||
'-e', '--export', action='store_true', default=False,
|
||||
help=argparse.SUPPRESS
|
||||
)
|
||||
@magic_arguments.argument(
|
||||
'filename', type=str,
|
||||
help='Notebook name or filename'
|
||||
)
|
||||
@line_magic
|
||||
def notebook(self, s):
|
||||
"""Export and convert IPython notebooks.
|
||||
|
||||
This function can export the current IPython history to a notebook file.
|
||||
For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
|
||||
|
||||
The -e or --export flag is deprecated in IPython 5.2, and will be
|
||||
removed in the future.
|
||||
"""
|
||||
args = magic_arguments.parse_argstring(self.notebook, s)
|
||||
|
||||
from nbformat import write, v4
|
||||
|
||||
cells = []
|
||||
hist = list(self.shell.history_manager.get_range())
|
||||
if(len(hist)<=1):
|
||||
raise ValueError('History is empty, cannot export')
|
||||
for session, execution_count, source in hist[:-1]:
|
||||
cells.append(v4.new_code_cell(
|
||||
execution_count=execution_count,
|
||||
source=source
|
||||
))
|
||||
nb = v4.new_notebook(cells=cells)
|
||||
with io.open(args.filename, 'w', encoding='utf-8') as f:
|
||||
write(nb, f, version=4)
|
||||
|
||||
@magics_class
|
||||
class AsyncMagics(BasicMagics):
|
||||
|
||||
@line_magic
|
||||
def autoawait(self, parameter_s):
|
||||
"""
|
||||
Allow to change the status of the autoawait option.
|
||||
|
||||
This allow you to set a specific asynchronous code runner.
|
||||
|
||||
If no value is passed, print the currently used asynchronous integration
|
||||
and whether it is activated.
|
||||
|
||||
It can take a number of value evaluated in the following order:
|
||||
|
||||
- False/false/off deactivate autoawait integration
|
||||
- True/true/on activate autoawait integration using configured default
|
||||
loop
|
||||
- asyncio/curio/trio activate autoawait integration and use integration
|
||||
with said library.
|
||||
|
||||
- `sync` turn on the pseudo-sync integration (mostly used for
|
||||
`IPython.embed()` which does not run IPython with a real eventloop and
|
||||
deactivate running asynchronous code. Turning on Asynchronous code with
|
||||
the pseudo sync loop is undefined behavior and may lead IPython to crash.
|
||||
|
||||
If the passed parameter does not match any of the above and is a python
|
||||
identifier, get said object from user namespace and set it as the
|
||||
runner, and activate autoawait.
|
||||
|
||||
If the object is a fully qualified object name, attempt to import it and
|
||||
set it as the runner, and activate autoawait.
|
||||
|
||||
|
||||
The exact behavior of autoawait is experimental and subject to change
|
||||
across version of IPython and Python.
|
||||
"""
|
||||
|
||||
param = parameter_s.strip()
|
||||
d = {True: "on", False: "off"}
|
||||
|
||||
if not param:
|
||||
print("IPython autoawait is `{}`, and set to use `{}`".format(
|
||||
d[self.shell.autoawait],
|
||||
self.shell.loop_runner
|
||||
))
|
||||
return None
|
||||
|
||||
if param.lower() in ('false', 'off'):
|
||||
self.shell.autoawait = False
|
||||
return None
|
||||
if param.lower() in ('true', 'on'):
|
||||
self.shell.autoawait = True
|
||||
return None
|
||||
|
||||
if param in self.shell.loop_runner_map:
|
||||
self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
|
||||
return None
|
||||
|
||||
if param in self.shell.user_ns :
|
||||
self.shell.loop_runner = self.shell.user_ns[param]
|
||||
self.shell.autoawait = True
|
||||
return None
|
||||
|
||||
runner = import_item(param)
|
||||
|
||||
self.shell.loop_runner = runner
|
||||
self.shell.autoawait = True
|
730
venv/Lib/site-packages/IPython/core/magics/code.py
Normal file
730
venv/Lib/site-packages/IPython/core/magics/code.py
Normal file
|
@ -0,0 +1,730 @@
|
|||
"""Implementation of code management magic functions.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Stdlib
|
||||
import inspect
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import ast
|
||||
from itertools import chain
|
||||
from urllib.request import urlopen
|
||||
from urllib.parse import urlencode
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
|
||||
from IPython.core.macro import Macro
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
from IPython.core.oinspect import find_file, find_source_lines
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from IPython.utils.contexts import preserve_keys
|
||||
from IPython.utils.path import get_py_filename
|
||||
from warnings import warn
|
||||
from logging import error
|
||||
from IPython.utils.text import get_text_list
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Used for exception handling in magic_edit
|
||||
class MacroToEdit(ValueError): pass
|
||||
|
||||
ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
|
||||
|
||||
# To match, e.g. 8-10 1:5 :10 3-
|
||||
range_re = re.compile(r"""
|
||||
(?P<start>\d+)?
|
||||
((?P<sep>[\-:])
|
||||
(?P<end>\d+)?)?
|
||||
$""", re.VERBOSE)
|
||||
|
||||
|
||||
def extract_code_ranges(ranges_str):
|
||||
"""Turn a string of range for %%load into 2-tuples of (start, stop)
|
||||
ready to use as a slice of the content split by lines.
|
||||
|
||||
Examples
|
||||
--------
|
||||
list(extract_input_ranges("5-10 2"))
|
||||
[(4, 10), (1, 2)]
|
||||
"""
|
||||
for range_str in ranges_str.split():
|
||||
rmatch = range_re.match(range_str)
|
||||
if not rmatch:
|
||||
continue
|
||||
sep = rmatch.group("sep")
|
||||
start = rmatch.group("start")
|
||||
end = rmatch.group("end")
|
||||
|
||||
if sep == '-':
|
||||
start = int(start) - 1 if start else None
|
||||
end = int(end) if end else None
|
||||
elif sep == ':':
|
||||
start = int(start) - 1 if start else None
|
||||
end = int(end) - 1 if end else None
|
||||
else:
|
||||
end = int(start)
|
||||
start = int(start) - 1
|
||||
yield (start, end)
|
||||
|
||||
|
||||
def extract_symbols(code, symbols):
|
||||
"""
|
||||
Return a tuple (blocks, not_found)
|
||||
where ``blocks`` is a list of code fragments
|
||||
for each symbol parsed from code, and ``not_found`` are
|
||||
symbols not found in the code.
|
||||
|
||||
For example::
|
||||
|
||||
In [1]: code = '''a = 10
|
||||
...: def b(): return 42
|
||||
...: class A: pass'''
|
||||
|
||||
In [2]: extract_symbols(code, 'A,b,z')
|
||||
Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z'])
|
||||
"""
|
||||
symbols = symbols.split(',')
|
||||
|
||||
# this will raise SyntaxError if code isn't valid Python
|
||||
py_code = ast.parse(code)
|
||||
|
||||
marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
|
||||
code = code.split('\n')
|
||||
|
||||
symbols_lines = {}
|
||||
|
||||
# we already know the start_lineno of each symbol (marks).
|
||||
# To find each end_lineno, we traverse in reverse order until each
|
||||
# non-blank line
|
||||
end = len(code)
|
||||
for name, start in reversed(marks):
|
||||
while not code[end - 1].strip():
|
||||
end -= 1
|
||||
if name:
|
||||
symbols_lines[name] = (start - 1, end)
|
||||
end = start - 1
|
||||
|
||||
# Now symbols_lines is a map
|
||||
# {'symbol_name': (start_lineno, end_lineno), ...}
|
||||
|
||||
# fill a list with chunks of codes for each requested symbol
|
||||
blocks = []
|
||||
not_found = []
|
||||
for symbol in symbols:
|
||||
if symbol in symbols_lines:
|
||||
start, end = symbols_lines[symbol]
|
||||
blocks.append('\n'.join(code[start:end]) + '\n')
|
||||
else:
|
||||
not_found.append(symbol)
|
||||
|
||||
return blocks, not_found
|
||||
|
||||
def strip_initial_indent(lines):
|
||||
"""For %load, strip indent from lines until finding an unindented line.
|
||||
|
||||
https://github.com/ipython/ipython/issues/9775
|
||||
"""
|
||||
indent_re = re.compile(r'\s+')
|
||||
|
||||
it = iter(lines)
|
||||
first_line = next(it)
|
||||
indent_match = indent_re.match(first_line)
|
||||
|
||||
if indent_match:
|
||||
# First line was indented
|
||||
indent = indent_match.group()
|
||||
yield first_line[len(indent):]
|
||||
|
||||
for line in it:
|
||||
if line.startswith(indent):
|
||||
yield line[len(indent):]
|
||||
else:
|
||||
# Less indented than the first line - stop dedenting
|
||||
yield line
|
||||
break
|
||||
else:
|
||||
yield first_line
|
||||
|
||||
# Pass the remaining lines through without dedenting
|
||||
for line in it:
|
||||
yield line
|
||||
|
||||
|
||||
class InteractivelyDefined(Exception):
|
||||
"""Exception for interactively defined variable in magic_edit"""
|
||||
def __init__(self, index):
|
||||
self.index = index
|
||||
|
||||
|
||||
@magics_class
|
||||
class CodeMagics(Magics):
|
||||
"""Magics related to code management (loading, saving, editing, ...)."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._knowntemps = set()
|
||||
super(CodeMagics, self).__init__(*args, **kwargs)
|
||||
|
||||
@line_magic
|
||||
def save(self, parameter_s=''):
|
||||
"""Save a set of lines or a macro to a given filename.
|
||||
|
||||
Usage:\\
|
||||
%save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
|
||||
|
||||
Options:
|
||||
|
||||
-r: use 'raw' input. By default, the 'processed' history is used,
|
||||
so that magics are loaded in their transformed version to valid
|
||||
Python. If this option is given, the raw input as typed as the
|
||||
command line is used instead.
|
||||
|
||||
-f: force overwrite. If file exists, %save will prompt for overwrite
|
||||
unless -f is given.
|
||||
|
||||
-a: append to the file instead of overwriting it.
|
||||
|
||||
This function uses the same syntax as %history for input ranges,
|
||||
then saves the lines to the filename you specify.
|
||||
|
||||
It adds a '.py' extension to the file if you don't do so yourself, and
|
||||
it asks for confirmation before overwriting existing files.
|
||||
|
||||
If `-r` option is used, the default extension is `.ipy`.
|
||||
"""
|
||||
|
||||
opts,args = self.parse_options(parameter_s,'fra',mode='list')
|
||||
if not args:
|
||||
raise UsageError('Missing filename.')
|
||||
raw = 'r' in opts
|
||||
force = 'f' in opts
|
||||
append = 'a' in opts
|
||||
mode = 'a' if append else 'w'
|
||||
ext = '.ipy' if raw else '.py'
|
||||
fname, codefrom = args[0], " ".join(args[1:])
|
||||
if not fname.endswith(('.py','.ipy')):
|
||||
fname += ext
|
||||
file_exists = os.path.isfile(fname)
|
||||
if file_exists and not force and not append:
|
||||
try:
|
||||
overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
|
||||
except StdinNotImplementedError:
|
||||
print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
|
||||
return
|
||||
if not overwrite :
|
||||
print('Operation cancelled.')
|
||||
return
|
||||
try:
|
||||
cmds = self.shell.find_user_code(codefrom,raw)
|
||||
except (TypeError, ValueError) as e:
|
||||
print(e.args[0])
|
||||
return
|
||||
with io.open(fname, mode, encoding="utf-8") as f:
|
||||
if not file_exists or not append:
|
||||
f.write("# coding: utf-8\n")
|
||||
f.write(cmds)
|
||||
# make sure we end on a newline
|
||||
if not cmds.endswith('\n'):
|
||||
f.write('\n')
|
||||
print('The following commands were written to file `%s`:' % fname)
|
||||
print(cmds)
|
||||
|
||||
@line_magic
|
||||
def pastebin(self, parameter_s=''):
|
||||
"""Upload code to dpaste's paste bin, returning the URL.
|
||||
|
||||
Usage:\\
|
||||
%pastebin [-d "Custom description"] 1-7
|
||||
|
||||
The argument can be an input history range, a filename, or the name of a
|
||||
string or macro.
|
||||
|
||||
Options:
|
||||
|
||||
-d: Pass a custom description for the gist. The default will say
|
||||
"Pasted from IPython".
|
||||
"""
|
||||
opts, args = self.parse_options(parameter_s, 'd:')
|
||||
|
||||
try:
|
||||
code = self.shell.find_user_code(args)
|
||||
except (ValueError, TypeError) as e:
|
||||
print(e.args[0])
|
||||
return
|
||||
|
||||
post_data = urlencode({
|
||||
"title": opts.get('d', "Pasted from IPython"),
|
||||
"syntax": "python3",
|
||||
"content": code
|
||||
}).encode('utf-8')
|
||||
|
||||
response = urlopen("http://dpaste.com/api/v2/", post_data)
|
||||
return response.headers.get('Location')
|
||||
|
||||
@line_magic
|
||||
def loadpy(self, arg_s):
|
||||
"""Alias of `%load`
|
||||
|
||||
`%loadpy` has gained some flexibility and dropped the requirement of a `.py`
|
||||
extension. So it has been renamed simply into %load. You can look at
|
||||
`%load`'s docstring for more info.
|
||||
"""
|
||||
self.load(arg_s)
|
||||
|
||||
@line_magic
|
||||
def load(self, arg_s):
|
||||
"""Load code into the current frontend.
|
||||
|
||||
Usage:\\
|
||||
%load [options] source
|
||||
|
||||
where source can be a filename, URL, input history range, macro, or
|
||||
element in the user namespace
|
||||
|
||||
Options:
|
||||
|
||||
-r <lines>: Specify lines or ranges of lines to load from the source.
|
||||
Ranges could be specified as x-y (x..y) or in python-style x:y
|
||||
(x..(y-1)). Both limits x and y can be left blank (meaning the
|
||||
beginning and end of the file, respectively).
|
||||
|
||||
-s <symbols>: Specify function or classes to load from python source.
|
||||
|
||||
-y : Don't ask confirmation for loading source above 200 000 characters.
|
||||
|
||||
-n : Include the user's namespace when searching for source code.
|
||||
|
||||
This magic command can either take a local filename, a URL, an history
|
||||
range (see %history) or a macro as argument, it will prompt for
|
||||
confirmation before loading source with more than 200 000 characters, unless
|
||||
-y flag is passed or if the frontend does not support raw_input::
|
||||
|
||||
%load myscript.py
|
||||
%load 7-27
|
||||
%load myMacro
|
||||
%load http://www.example.com/myscript.py
|
||||
%load -r 5-10 myscript.py
|
||||
%load -r 10-20,30,40: foo.py
|
||||
%load -s MyClass,wonder_function myscript.py
|
||||
%load -n MyClass
|
||||
%load -n my_module.wonder_function
|
||||
"""
|
||||
opts,args = self.parse_options(arg_s,'yns:r:')
|
||||
|
||||
if not args:
|
||||
raise UsageError('Missing filename, URL, input history range, '
|
||||
'macro, or element in the user namespace.')
|
||||
|
||||
search_ns = 'n' in opts
|
||||
|
||||
contents = self.shell.find_user_code(args, search_ns=search_ns)
|
||||
|
||||
if 's' in opts:
|
||||
try:
|
||||
blocks, not_found = extract_symbols(contents, opts['s'])
|
||||
except SyntaxError:
|
||||
# non python code
|
||||
error("Unable to parse the input as valid Python code")
|
||||
return
|
||||
|
||||
if len(not_found) == 1:
|
||||
warn('The symbol `%s` was not found' % not_found[0])
|
||||
elif len(not_found) > 1:
|
||||
warn('The symbols %s were not found' % get_text_list(not_found,
|
||||
wrap_item_with='`')
|
||||
)
|
||||
|
||||
contents = '\n'.join(blocks)
|
||||
|
||||
if 'r' in opts:
|
||||
ranges = opts['r'].replace(',', ' ')
|
||||
lines = contents.split('\n')
|
||||
slices = extract_code_ranges(ranges)
|
||||
contents = [lines[slice(*slc)] for slc in slices]
|
||||
contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
|
||||
|
||||
l = len(contents)
|
||||
|
||||
# 200 000 is ~ 2500 full 80 character lines
|
||||
# so in average, more than 5000 lines
|
||||
if l > 200000 and 'y' not in opts:
|
||||
try:
|
||||
ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
|
||||
" (%d characters). Continue (y/[N]) ?" % l), default='n' )
|
||||
except StdinNotImplementedError:
|
||||
#assume yes if raw input not implemented
|
||||
ans = True
|
||||
|
||||
if ans is False :
|
||||
print('Operation cancelled.')
|
||||
return
|
||||
|
||||
contents = "# %load {}\n".format(arg_s) + contents
|
||||
|
||||
self.shell.set_next_input(contents, replace=True)
|
||||
|
||||
@staticmethod
|
||||
def _find_edit_target(shell, args, opts, last_call):
|
||||
"""Utility method used by magic_edit to find what to edit."""
|
||||
|
||||
def make_filename(arg):
|
||||
"Make a filename from the given args"
|
||||
try:
|
||||
filename = get_py_filename(arg)
|
||||
except IOError:
|
||||
# If it ends with .py but doesn't already exist, assume we want
|
||||
# a new file.
|
||||
if arg.endswith('.py'):
|
||||
filename = arg
|
||||
else:
|
||||
filename = None
|
||||
return filename
|
||||
|
||||
# Set a few locals from the options for convenience:
|
||||
opts_prev = 'p' in opts
|
||||
opts_raw = 'r' in opts
|
||||
|
||||
# custom exceptions
|
||||
class DataIsObject(Exception): pass
|
||||
|
||||
# Default line number value
|
||||
lineno = opts.get('n',None)
|
||||
|
||||
if opts_prev:
|
||||
args = '_%s' % last_call[0]
|
||||
if args not in shell.user_ns:
|
||||
args = last_call[1]
|
||||
|
||||
# by default this is done with temp files, except when the given
|
||||
# arg is a filename
|
||||
use_temp = True
|
||||
|
||||
data = ''
|
||||
|
||||
# First, see if the arguments should be a filename.
|
||||
filename = make_filename(args)
|
||||
if filename:
|
||||
use_temp = False
|
||||
elif args:
|
||||
# Mode where user specifies ranges of lines, like in %macro.
|
||||
data = shell.extract_input_lines(args, opts_raw)
|
||||
if not data:
|
||||
try:
|
||||
# Load the parameter given as a variable. If not a string,
|
||||
# process it as an object instead (below)
|
||||
|
||||
#print '*** args',args,'type',type(args) # dbg
|
||||
data = eval(args, shell.user_ns)
|
||||
if not isinstance(data, str):
|
||||
raise DataIsObject
|
||||
|
||||
except (NameError,SyntaxError):
|
||||
# given argument is not a variable, try as a filename
|
||||
filename = make_filename(args)
|
||||
if filename is None:
|
||||
warn("Argument given (%s) can't be found as a variable "
|
||||
"or as a filename." % args)
|
||||
return (None, None, None)
|
||||
use_temp = False
|
||||
|
||||
except DataIsObject:
|
||||
# macros have a special edit function
|
||||
if isinstance(data, Macro):
|
||||
raise MacroToEdit(data)
|
||||
|
||||
# For objects, try to edit the file where they are defined
|
||||
filename = find_file(data)
|
||||
if filename:
|
||||
if 'fakemodule' in filename.lower() and \
|
||||
inspect.isclass(data):
|
||||
# class created by %edit? Try to find source
|
||||
# by looking for method definitions instead, the
|
||||
# __module__ in those classes is FakeModule.
|
||||
attrs = [getattr(data, aname) for aname in dir(data)]
|
||||
for attr in attrs:
|
||||
if not inspect.ismethod(attr):
|
||||
continue
|
||||
filename = find_file(attr)
|
||||
if filename and \
|
||||
'fakemodule' not in filename.lower():
|
||||
# change the attribute to be the edit
|
||||
# target instead
|
||||
data = attr
|
||||
break
|
||||
|
||||
m = ipython_input_pat.match(os.path.basename(filename))
|
||||
if m:
|
||||
raise InteractivelyDefined(int(m.groups()[0]))
|
||||
|
||||
datafile = 1
|
||||
if filename is None:
|
||||
filename = make_filename(args)
|
||||
datafile = 1
|
||||
if filename is not None:
|
||||
# only warn about this if we get a real name
|
||||
warn('Could not find file where `%s` is defined.\n'
|
||||
'Opening a file named `%s`' % (args, filename))
|
||||
# Now, make sure we can actually read the source (if it was
|
||||
# in a temp file it's gone by now).
|
||||
if datafile:
|
||||
if lineno is None:
|
||||
lineno = find_source_lines(data)
|
||||
if lineno is None:
|
||||
filename = make_filename(args)
|
||||
if filename is None:
|
||||
warn('The file where `%s` was defined '
|
||||
'cannot be read or found.' % data)
|
||||
return (None, None, None)
|
||||
use_temp = False
|
||||
|
||||
if use_temp:
|
||||
filename = shell.mktempfile(data)
|
||||
print('IPython will make a temporary file named:',filename)
|
||||
|
||||
# use last_call to remember the state of the previous call, but don't
|
||||
# let it be clobbered by successive '-p' calls.
|
||||
try:
|
||||
last_call[0] = shell.displayhook.prompt_count
|
||||
if not opts_prev:
|
||||
last_call[1] = args
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
return filename, lineno, use_temp
|
||||
|
||||
def _edit_macro(self,mname,macro):
|
||||
"""open an editor with the macro data in a file"""
|
||||
filename = self.shell.mktempfile(macro.value)
|
||||
self.shell.hooks.editor(filename)
|
||||
|
||||
# and make a new macro object, to replace the old one
|
||||
with open(filename) as mfile:
|
||||
mvalue = mfile.read()
|
||||
self.shell.user_ns[mname] = Macro(mvalue)
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def edit(self, parameter_s='',last_call=['','']):
|
||||
"""Bring up an editor and execute the resulting code.
|
||||
|
||||
Usage:
|
||||
%edit [options] [args]
|
||||
|
||||
%edit runs IPython's editor hook. The default version of this hook is
|
||||
set to call the editor specified by your $EDITOR environment variable.
|
||||
If this isn't found, it will default to vi under Linux/Unix and to
|
||||
notepad under Windows. See the end of this docstring for how to change
|
||||
the editor hook.
|
||||
|
||||
You can also set the value of this editor via the
|
||||
``TerminalInteractiveShell.editor`` option in your configuration file.
|
||||
This is useful if you wish to use a different editor from your typical
|
||||
default with IPython (and for Windows users who typically don't set
|
||||
environment variables).
|
||||
|
||||
This command allows you to conveniently edit multi-line code right in
|
||||
your IPython session.
|
||||
|
||||
If called without arguments, %edit opens up an empty editor with a
|
||||
temporary file and will execute the contents of this file when you
|
||||
close it (don't forget to save it!).
|
||||
|
||||
|
||||
Options:
|
||||
|
||||
-n <number>: open the editor at a specified line number. By default,
|
||||
the IPython editor hook uses the unix syntax 'editor +N filename', but
|
||||
you can configure this by providing your own modified hook if your
|
||||
favorite editor supports line-number specifications with a different
|
||||
syntax.
|
||||
|
||||
-p: this will call the editor with the same data as the previous time
|
||||
it was used, regardless of how long ago (in your current session) it
|
||||
was.
|
||||
|
||||
-r: use 'raw' input. This option only applies to input taken from the
|
||||
user's history. By default, the 'processed' history is used, so that
|
||||
magics are loaded in their transformed version to valid Python. If
|
||||
this option is given, the raw input as typed as the command line is
|
||||
used instead. When you exit the editor, it will be executed by
|
||||
IPython's own processor.
|
||||
|
||||
-x: do not execute the edited code immediately upon exit. This is
|
||||
mainly useful if you are editing programs which need to be called with
|
||||
command line arguments, which you can then do using %run.
|
||||
|
||||
|
||||
Arguments:
|
||||
|
||||
If arguments are given, the following possibilities exist:
|
||||
|
||||
- If the argument is a filename, IPython will load that into the
|
||||
editor. It will execute its contents with execfile() when you exit,
|
||||
loading any code in the file into your interactive namespace.
|
||||
|
||||
- The arguments are ranges of input history, e.g. "7 ~1/4-6".
|
||||
The syntax is the same as in the %history magic.
|
||||
|
||||
- If the argument is a string variable, its contents are loaded
|
||||
into the editor. You can thus edit any string which contains
|
||||
python code (including the result of previous edits).
|
||||
|
||||
- If the argument is the name of an object (other than a string),
|
||||
IPython will try to locate the file where it was defined and open the
|
||||
editor at the point where it is defined. You can use `%edit function`
|
||||
to load an editor exactly at the point where 'function' is defined,
|
||||
edit it and have the file be executed automatically.
|
||||
|
||||
- If the object is a macro (see %macro for details), this opens up your
|
||||
specified editor with a temporary file containing the macro's data.
|
||||
Upon exit, the macro is reloaded with the contents of the file.
|
||||
|
||||
Note: opening at an exact line is only supported under Unix, and some
|
||||
editors (like kedit and gedit up to Gnome 2.8) do not understand the
|
||||
'+NUMBER' parameter necessary for this feature. Good editors like
|
||||
(X)Emacs, vi, jed, pico and joe all do.
|
||||
|
||||
After executing your code, %edit will return as output the code you
|
||||
typed in the editor (except when it was an existing file). This way
|
||||
you can reload the code in further invocations of %edit as a variable,
|
||||
via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
|
||||
the output.
|
||||
|
||||
Note that %edit is also available through the alias %ed.
|
||||
|
||||
This is an example of creating a simple function inside the editor and
|
||||
then modifying it. First, start up the editor::
|
||||
|
||||
In [1]: edit
|
||||
Editing... done. Executing edited code...
|
||||
Out[1]: 'def foo():\\n print "foo() was defined in an editing
|
||||
session"\\n'
|
||||
|
||||
We can then call the function foo()::
|
||||
|
||||
In [2]: foo()
|
||||
foo() was defined in an editing session
|
||||
|
||||
Now we edit foo. IPython automatically loads the editor with the
|
||||
(temporary) file where foo() was previously defined::
|
||||
|
||||
In [3]: edit foo
|
||||
Editing... done. Executing edited code...
|
||||
|
||||
And if we call foo() again we get the modified version::
|
||||
|
||||
In [4]: foo()
|
||||
foo() has now been changed!
|
||||
|
||||
Here is an example of how to edit a code snippet successive
|
||||
times. First we call the editor::
|
||||
|
||||
In [5]: edit
|
||||
Editing... done. Executing edited code...
|
||||
hello
|
||||
Out[5]: "print 'hello'\\n"
|
||||
|
||||
Now we call it again with the previous output (stored in _)::
|
||||
|
||||
In [6]: edit _
|
||||
Editing... done. Executing edited code...
|
||||
hello world
|
||||
Out[6]: "print 'hello world'\\n"
|
||||
|
||||
Now we call it with the output #8 (stored in _8, also as Out[8])::
|
||||
|
||||
In [7]: edit _8
|
||||
Editing... done. Executing edited code...
|
||||
hello again
|
||||
Out[7]: "print 'hello again'\\n"
|
||||
|
||||
|
||||
Changing the default editor hook:
|
||||
|
||||
If you wish to write your own editor hook, you can put it in a
|
||||
configuration file which you load at startup time. The default hook
|
||||
is defined in the IPython.core.hooks module, and you can use that as a
|
||||
starting example for further modifications. That file also has
|
||||
general instructions on how to set a new hook for use once you've
|
||||
defined it."""
|
||||
opts,args = self.parse_options(parameter_s,'prxn:')
|
||||
|
||||
try:
|
||||
filename, lineno, is_temp = self._find_edit_target(self.shell,
|
||||
args, opts, last_call)
|
||||
except MacroToEdit as e:
|
||||
self._edit_macro(args, e.args[0])
|
||||
return
|
||||
except InteractivelyDefined as e:
|
||||
print("Editing In[%i]" % e.index)
|
||||
args = str(e.index)
|
||||
filename, lineno, is_temp = self._find_edit_target(self.shell,
|
||||
args, opts, last_call)
|
||||
if filename is None:
|
||||
# nothing was found, warnings have already been issued,
|
||||
# just give up.
|
||||
return
|
||||
|
||||
if is_temp:
|
||||
self._knowntemps.add(filename)
|
||||
elif (filename in self._knowntemps):
|
||||
is_temp = True
|
||||
|
||||
|
||||
# do actual editing here
|
||||
print('Editing...', end=' ')
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
# Quote filenames that may have spaces in them
|
||||
if ' ' in filename:
|
||||
filename = "'%s'" % filename
|
||||
self.shell.hooks.editor(filename,lineno)
|
||||
except TryNext:
|
||||
warn('Could not open editor')
|
||||
return
|
||||
|
||||
# XXX TODO: should this be generalized for all string vars?
|
||||
# For now, this is special-cased to blocks created by cpaste
|
||||
if args.strip() == 'pasted_block':
|
||||
with open(filename, 'r') as f:
|
||||
self.shell.user_ns['pasted_block'] = f.read()
|
||||
|
||||
if 'x' in opts: # -x prevents actual execution
|
||||
print()
|
||||
else:
|
||||
print('done. Executing edited code...')
|
||||
with preserve_keys(self.shell.user_ns, '__file__'):
|
||||
if not is_temp:
|
||||
self.shell.user_ns['__file__'] = filename
|
||||
if 'r' in opts: # Untranslated IPython code
|
||||
with open(filename, 'r') as f:
|
||||
source = f.read()
|
||||
self.shell.run_cell(source, store_history=False)
|
||||
else:
|
||||
self.shell.safe_execfile(filename, self.shell.user_ns,
|
||||
self.shell.user_ns)
|
||||
|
||||
if is_temp:
|
||||
try:
|
||||
with open(filename) as f:
|
||||
return f.read()
|
||||
except IOError as msg:
|
||||
if msg.filename == filename:
|
||||
warn('File not found. Did you forget to save?')
|
||||
return
|
||||
else:
|
||||
self.shell.showtraceback()
|
158
venv/Lib/site-packages/IPython/core/magics/config.py
Normal file
158
venv/Lib/site-packages/IPython/core/magics/config.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
"""Implementation of configuration-related magic functions.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Stdlib
|
||||
import re
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.error import UsageError
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
from logging import error
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
reg = re.compile(r'^\w+\.\w+$')
|
||||
@magics_class
|
||||
class ConfigMagics(Magics):
|
||||
|
||||
def __init__(self, shell):
|
||||
super(ConfigMagics, self).__init__(shell)
|
||||
self.configurables = []
|
||||
|
||||
@line_magic
|
||||
def config(self, s):
|
||||
"""configure IPython
|
||||
|
||||
%config Class[.trait=value]
|
||||
|
||||
This magic exposes most of the IPython config system. Any
|
||||
Configurable class should be able to be configured with the simple
|
||||
line::
|
||||
|
||||
%config Class.trait=value
|
||||
|
||||
Where `value` will be resolved in the user's namespace, if it is an
|
||||
expression or variable name.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
To see what classes are available for config, pass no arguments::
|
||||
|
||||
In [1]: %config
|
||||
Available objects for config:
|
||||
TerminalInteractiveShell
|
||||
HistoryManager
|
||||
PrefilterManager
|
||||
AliasManager
|
||||
IPCompleter
|
||||
DisplayFormatter
|
||||
|
||||
To view what is configurable on a given class, just pass the class
|
||||
name::
|
||||
|
||||
In [2]: %config IPCompleter
|
||||
IPCompleter options
|
||||
-----------------
|
||||
IPCompleter.omit__names=<Enum>
|
||||
Current: 2
|
||||
Choices: (0, 1, 2)
|
||||
Instruct the completer to omit private method names
|
||||
Specifically, when completing on ``object.<tab>``.
|
||||
When 2 [default]: all names that start with '_' will be excluded.
|
||||
When 1: all 'magic' names (``__foo__``) will be excluded.
|
||||
When 0: nothing will be excluded.
|
||||
IPCompleter.merge_completions=<CBool>
|
||||
Current: True
|
||||
Whether to merge completion results into a single list
|
||||
If False, only the completion results from the first non-empty
|
||||
completer will be returned.
|
||||
IPCompleter.limit_to__all__=<CBool>
|
||||
Current: False
|
||||
Instruct the completer to use __all__ for the completion
|
||||
Specifically, when completing on ``object.<tab>``.
|
||||
When True: only those names in obj.__all__ will be included.
|
||||
When False [default]: the __all__ attribute is ignored
|
||||
IPCompleter.greedy=<CBool>
|
||||
Current: False
|
||||
Activate greedy completion
|
||||
This will enable completion on elements of lists, results of
|
||||
function calls, etc., but can be unsafe because the code is
|
||||
actually evaluated on TAB.
|
||||
|
||||
but the real use is in setting values::
|
||||
|
||||
In [3]: %config IPCompleter.greedy = True
|
||||
|
||||
and these values are read from the user_ns if they are variables::
|
||||
|
||||
In [4]: feeling_greedy=False
|
||||
|
||||
In [5]: %config IPCompleter.greedy = feeling_greedy
|
||||
|
||||
"""
|
||||
from traitlets.config.loader import Config
|
||||
# some IPython objects are Configurable, but do not yet have
|
||||
# any configurable traits. Exclude them from the effects of
|
||||
# this magic, as their presence is just noise:
|
||||
configurables = sorted(set([ c for c in self.shell.configurables
|
||||
if c.__class__.class_traits(config=True)
|
||||
]), key=lambda x: x.__class__.__name__)
|
||||
classnames = [ c.__class__.__name__ for c in configurables ]
|
||||
|
||||
line = s.strip()
|
||||
if not line:
|
||||
# print available configurable names
|
||||
print("Available objects for config:")
|
||||
for name in classnames:
|
||||
print(" ", name)
|
||||
return
|
||||
elif line in classnames:
|
||||
# `%config TerminalInteractiveShell` will print trait info for
|
||||
# TerminalInteractiveShell
|
||||
c = configurables[classnames.index(line)]
|
||||
cls = c.__class__
|
||||
help = cls.class_get_help(c)
|
||||
# strip leading '--' from cl-args:
|
||||
help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
|
||||
print(help)
|
||||
return
|
||||
elif reg.match(line):
|
||||
cls, attr = line.split('.')
|
||||
return getattr(configurables[classnames.index(cls)],attr)
|
||||
elif '=' not in line:
|
||||
msg = "Invalid config statement: %r, "\
|
||||
"should be `Class.trait = value`."
|
||||
|
||||
ll = line.lower()
|
||||
for classname in classnames:
|
||||
if ll == classname.lower():
|
||||
msg = msg + '\nDid you mean %s (note the case)?' % classname
|
||||
break
|
||||
|
||||
raise UsageError( msg % line)
|
||||
|
||||
# otherwise, assume we are setting configurables.
|
||||
# leave quotes on args when splitting, because we want
|
||||
# unquoted args to eval in user_ns
|
||||
cfg = Config()
|
||||
exec("cfg."+line, locals(), self.shell.user_ns)
|
||||
|
||||
for configurable in configurables:
|
||||
try:
|
||||
configurable.update_config(cfg)
|
||||
except Exception as e:
|
||||
error(e)
|
82
venv/Lib/site-packages/IPython/core/magics/display.py
Normal file
82
venv/Lib/site-packages/IPython/core/magics/display.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
"""Simple magics for display formats"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.display import display, Javascript, Latex, SVG, HTML, Markdown
|
||||
from IPython.core.magic import (
|
||||
Magics, magics_class, cell_magic
|
||||
)
|
||||
from IPython.core import magic_arguments
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@magics_class
|
||||
class DisplayMagics(Magics):
|
||||
"""Magics for displaying various output types with literals
|
||||
|
||||
Defines javascript/latex/svg/html cell magics for writing
|
||||
blocks in those languages, to be rendered in the frontend.
|
||||
"""
|
||||
|
||||
@cell_magic
|
||||
def js(self, line, cell):
|
||||
"""Run the cell block of Javascript code
|
||||
|
||||
Alias of `%%javascript`
|
||||
"""
|
||||
self.javascript(line, cell)
|
||||
|
||||
@cell_magic
|
||||
def javascript(self, line, cell):
|
||||
"""Run the cell block of Javascript code"""
|
||||
display(Javascript(cell))
|
||||
|
||||
|
||||
@cell_magic
|
||||
def latex(self, line, cell):
|
||||
"""Render the cell as a block of latex
|
||||
|
||||
The subset of latex which is support depends on the implementation in
|
||||
the client. In the Jupyter Notebook, this magic only renders the subset
|
||||
of latex defined by MathJax
|
||||
[here](https://docs.mathjax.org/en/v2.5-latest/tex.html)."""
|
||||
display(Latex(cell))
|
||||
|
||||
@cell_magic
|
||||
def svg(self, line, cell):
|
||||
"""Render the cell as an SVG literal"""
|
||||
display(SVG(cell))
|
||||
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument(
|
||||
'--isolated', action='store_true', default=False,
|
||||
help="""Annotate the cell as 'isolated'.
|
||||
Isolated cells are rendered inside their own <iframe> tag"""
|
||||
)
|
||||
@cell_magic
|
||||
def html(self, line, cell):
|
||||
"""Render the cell as a block of HTML"""
|
||||
args = magic_arguments.parse_argstring(self.html, line)
|
||||
html = HTML(cell)
|
||||
if args.isolated:
|
||||
display(html, metadata={'text/html':{'isolated':True}})
|
||||
else:
|
||||
display(html)
|
||||
|
||||
@cell_magic
|
||||
def markdown(self, line, cell):
|
||||
"""Render the cell as Markdown text block"""
|
||||
display(Markdown(cell))
|
1506
venv/Lib/site-packages/IPython/core/magics/execution.py
Normal file
1506
venv/Lib/site-packages/IPython/core/magics/execution.py
Normal file
File diff suppressed because it is too large
Load diff
63
venv/Lib/site-packages/IPython/core/magics/extension.py
Normal file
63
venv/Lib/site-packages/IPython/core/magics/extension.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
"""Implementation of magic functions for the extension machinery.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.error import UsageError
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@magics_class
|
||||
class ExtensionMagics(Magics):
|
||||
"""Magics to manage the IPython extensions system."""
|
||||
|
||||
@line_magic
|
||||
def load_ext(self, module_str):
|
||||
"""Load an IPython extension by its module name."""
|
||||
if not module_str:
|
||||
raise UsageError('Missing module name.')
|
||||
res = self.shell.extension_manager.load_extension(module_str)
|
||||
|
||||
if res == 'already loaded':
|
||||
print("The %s extension is already loaded. To reload it, use:" % module_str)
|
||||
print(" %reload_ext", module_str)
|
||||
elif res == 'no load function':
|
||||
print("The %s module is not an IPython extension." % module_str)
|
||||
|
||||
@line_magic
|
||||
def unload_ext(self, module_str):
|
||||
"""Unload an IPython extension by its module name.
|
||||
|
||||
Not all extensions can be unloaded, only those which define an
|
||||
``unload_ipython_extension`` function.
|
||||
"""
|
||||
if not module_str:
|
||||
raise UsageError('Missing module name.')
|
||||
|
||||
res = self.shell.extension_manager.unload_extension(module_str)
|
||||
|
||||
if res == 'no unload function':
|
||||
print("The %s extension doesn't define how to unload it." % module_str)
|
||||
elif res == "not loaded":
|
||||
print("The %s extension is not loaded." % module_str)
|
||||
|
||||
@line_magic
|
||||
def reload_ext(self, module_str):
|
||||
"""Reload an IPython extension by its module name."""
|
||||
if not module_str:
|
||||
raise UsageError('Missing module name.')
|
||||
self.shell.extension_manager.reload_extension(module_str)
|
318
venv/Lib/site-packages/IPython/core/magics/history.py
Normal file
318
venv/Lib/site-packages/IPython/core/magics/history.py
Normal file
|
@ -0,0 +1,318 @@
|
|||
"""Implementation of magic functions related to History.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012, IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Stdlib
|
||||
import os
|
||||
import sys
|
||||
from io import open as io_open
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.error import StdinNotImplementedError
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
from IPython.core.magic_arguments import (argument, magic_arguments,
|
||||
parse_argstring)
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from IPython.utils import io
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magics class implementation
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
_unspecified = object()
|
||||
|
||||
|
||||
@magics_class
|
||||
class HistoryMagics(Magics):
|
||||
|
||||
@magic_arguments()
|
||||
@argument(
|
||||
'-n', dest='print_nums', action='store_true', default=False,
|
||||
help="""
|
||||
print line numbers for each input.
|
||||
This feature is only available if numbered prompts are in use.
|
||||
""")
|
||||
@argument(
|
||||
'-o', dest='get_output', action='store_true', default=False,
|
||||
help="also print outputs for each input.")
|
||||
@argument(
|
||||
'-p', dest='pyprompts', action='store_true', default=False,
|
||||
help="""
|
||||
print classic '>>>' python prompts before each input.
|
||||
This is useful for making documentation, and in conjunction
|
||||
with -o, for producing doctest-ready output.
|
||||
""")
|
||||
@argument(
|
||||
'-t', dest='raw', action='store_false', default=True,
|
||||
help="""
|
||||
print the 'translated' history, as IPython understands it.
|
||||
IPython filters your input and converts it all into valid Python
|
||||
source before executing it (things like magics or aliases are turned
|
||||
into function calls, for example). With this option, you'll see the
|
||||
native history instead of the user-entered version: '%%cd /' will be
|
||||
seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
|
||||
""")
|
||||
@argument(
|
||||
'-f', dest='filename',
|
||||
help="""
|
||||
FILENAME: instead of printing the output to the screen, redirect
|
||||
it to the given file. The file is always overwritten, though *when
|
||||
it can*, IPython asks for confirmation first. In particular, running
|
||||
the command 'history -f FILENAME' from the IPython Notebook
|
||||
interface will replace FILENAME even if it already exists *without*
|
||||
confirmation.
|
||||
""")
|
||||
@argument(
|
||||
'-g', dest='pattern', nargs='*', default=None,
|
||||
help="""
|
||||
treat the arg as a glob pattern to search for in (full) history.
|
||||
This includes the saved history (almost all commands ever written).
|
||||
The pattern may contain '?' to match one unknown character and '*'
|
||||
to match any number of unknown characters. Use '%%hist -g' to show
|
||||
full saved history (may be very long).
|
||||
""")
|
||||
@argument(
|
||||
'-l', dest='limit', type=int, nargs='?', default=_unspecified,
|
||||
help="""
|
||||
get the last n lines from all sessions. Specify n as a single
|
||||
arg, or the default is the last 10 lines.
|
||||
""")
|
||||
@argument(
|
||||
'-u', dest='unique', action='store_true',
|
||||
help="""
|
||||
when searching history using `-g`, show only unique history.
|
||||
""")
|
||||
@argument('range', nargs='*')
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def history(self, parameter_s = ''):
|
||||
"""Print input history (_i<n> variables), with most recent last.
|
||||
|
||||
By default, input history is printed without line numbers so it can be
|
||||
directly pasted into an editor. Use -n to show them.
|
||||
|
||||
By default, all input history from the current session is displayed.
|
||||
Ranges of history can be indicated using the syntax:
|
||||
|
||||
``4``
|
||||
Line 4, current session
|
||||
``4-6``
|
||||
Lines 4-6, current session
|
||||
``243/1-5``
|
||||
Lines 1-5, session 243
|
||||
``~2/7``
|
||||
Line 7, session 2 before current
|
||||
``~8/1-~6/5``
|
||||
From the first line of 8 sessions ago, to the fifth line of 6
|
||||
sessions ago.
|
||||
|
||||
Multiple ranges can be entered, separated by spaces
|
||||
|
||||
The same syntax is used by %macro, %save, %edit, %rerun
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [6]: %history -n 4-6
|
||||
4:a = 12
|
||||
5:print a**2
|
||||
6:%history -n 4-6
|
||||
|
||||
"""
|
||||
|
||||
args = parse_argstring(self.history, parameter_s)
|
||||
|
||||
# For brevity
|
||||
history_manager = self.shell.history_manager
|
||||
|
||||
def _format_lineno(session, line):
|
||||
"""Helper function to format line numbers properly."""
|
||||
if session in (0, history_manager.session_number):
|
||||
return str(line)
|
||||
return "%s/%s" % (session, line)
|
||||
|
||||
# Check if output to specific file was requested.
|
||||
outfname = args.filename
|
||||
if not outfname:
|
||||
outfile = sys.stdout # default
|
||||
# We don't want to close stdout at the end!
|
||||
close_at_end = False
|
||||
else:
|
||||
if os.path.exists(outfname):
|
||||
try:
|
||||
ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
|
||||
except StdinNotImplementedError:
|
||||
ans = True
|
||||
if not ans:
|
||||
print('Aborting.')
|
||||
return
|
||||
print("Overwriting file.")
|
||||
outfile = io_open(outfname, 'w', encoding='utf-8')
|
||||
close_at_end = True
|
||||
|
||||
print_nums = args.print_nums
|
||||
get_output = args.get_output
|
||||
pyprompts = args.pyprompts
|
||||
raw = args.raw
|
||||
|
||||
pattern = None
|
||||
limit = None if args.limit is _unspecified else args.limit
|
||||
|
||||
if args.pattern is not None:
|
||||
if args.pattern:
|
||||
pattern = "*" + " ".join(args.pattern) + "*"
|
||||
else:
|
||||
pattern = "*"
|
||||
hist = history_manager.search(pattern, raw=raw, output=get_output,
|
||||
n=limit, unique=args.unique)
|
||||
print_nums = True
|
||||
elif args.limit is not _unspecified:
|
||||
n = 10 if limit is None else limit
|
||||
hist = history_manager.get_tail(n, raw=raw, output=get_output)
|
||||
else:
|
||||
if args.range: # Get history by ranges
|
||||
hist = history_manager.get_range_by_str(" ".join(args.range),
|
||||
raw, get_output)
|
||||
else: # Just get history for the current session
|
||||
hist = history_manager.get_range(raw=raw, output=get_output)
|
||||
|
||||
# We could be displaying the entire history, so let's not try to pull
|
||||
# it into a list in memory. Anything that needs more space will just
|
||||
# misalign.
|
||||
width = 4
|
||||
|
||||
for session, lineno, inline in hist:
|
||||
# Print user history with tabs expanded to 4 spaces. The GUI
|
||||
# clients use hard tabs for easier usability in auto-indented code,
|
||||
# but we want to produce PEP-8 compliant history for safe pasting
|
||||
# into an editor.
|
||||
if get_output:
|
||||
inline, output = inline
|
||||
inline = inline.expandtabs(4).rstrip()
|
||||
|
||||
multiline = "\n" in inline
|
||||
line_sep = '\n' if multiline else ' '
|
||||
if print_nums:
|
||||
print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
|
||||
line_sep), file=outfile, end=u'')
|
||||
if pyprompts:
|
||||
print(u">>> ", end=u"", file=outfile)
|
||||
if multiline:
|
||||
inline = "\n... ".join(inline.splitlines()) + "\n..."
|
||||
print(inline, file=outfile)
|
||||
if get_output and output:
|
||||
print(output, file=outfile)
|
||||
|
||||
if close_at_end:
|
||||
outfile.close()
|
||||
|
||||
@line_magic
|
||||
def recall(self, arg):
|
||||
r"""Repeat a command, or get command to input line for editing.
|
||||
|
||||
%recall and %rep are equivalent.
|
||||
|
||||
- %recall (no arguments):
|
||||
|
||||
Place a string version of last computation result (stored in the
|
||||
special '_' variable) to the next input prompt. Allows you to create
|
||||
elaborate command lines without using copy-paste::
|
||||
|
||||
In[1]: l = ["hei", "vaan"]
|
||||
In[2]: "".join(l)
|
||||
Out[2]: heivaan
|
||||
In[3]: %recall
|
||||
In[4]: heivaan_ <== cursor blinking
|
||||
|
||||
%recall 45
|
||||
|
||||
Place history line 45 on the next input prompt. Use %hist to find
|
||||
out the number.
|
||||
|
||||
%recall 1-4
|
||||
|
||||
Combine the specified lines into one cell, and place it on the next
|
||||
input prompt. See %history for the slice syntax.
|
||||
|
||||
%recall foo+bar
|
||||
|
||||
If foo+bar can be evaluated in the user namespace, the result is
|
||||
placed at the next input prompt. Otherwise, the history is searched
|
||||
for lines which contain that substring, and the most recent one is
|
||||
placed at the next input prompt.
|
||||
"""
|
||||
if not arg: # Last output
|
||||
self.shell.set_next_input(str(self.shell.user_ns["_"]))
|
||||
return
|
||||
# Get history range
|
||||
histlines = self.shell.history_manager.get_range_by_str(arg)
|
||||
cmd = "\n".join(x[2] for x in histlines)
|
||||
if cmd:
|
||||
self.shell.set_next_input(cmd.rstrip())
|
||||
return
|
||||
|
||||
try: # Variable in user namespace
|
||||
cmd = str(eval(arg, self.shell.user_ns))
|
||||
except Exception: # Search for term in history
|
||||
histlines = self.shell.history_manager.search("*"+arg+"*")
|
||||
for h in reversed([x[2] for x in histlines]):
|
||||
if 'recall' in h or 'rep' in h:
|
||||
continue
|
||||
self.shell.set_next_input(h.rstrip())
|
||||
return
|
||||
else:
|
||||
self.shell.set_next_input(cmd.rstrip())
|
||||
print("Couldn't evaluate or find in history:", arg)
|
||||
|
||||
@line_magic
|
||||
def rerun(self, parameter_s=''):
|
||||
"""Re-run previous input
|
||||
|
||||
By default, you can specify ranges of input history to be repeated
|
||||
(as with %history). With no arguments, it will repeat the last line.
|
||||
|
||||
Options:
|
||||
|
||||
-l <n> : Repeat the last n lines of input, not including the
|
||||
current command.
|
||||
|
||||
-g foo : Repeat the most recent line which contains foo
|
||||
"""
|
||||
opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
|
||||
if "l" in opts: # Last n lines
|
||||
n = int(opts['l'])
|
||||
hist = self.shell.history_manager.get_tail(n)
|
||||
elif "g" in opts: # Search
|
||||
p = "*"+opts['g']+"*"
|
||||
hist = list(self.shell.history_manager.search(p))
|
||||
for l in reversed(hist):
|
||||
if "rerun" not in l[2]:
|
||||
hist = [l] # The last match which isn't a %rerun
|
||||
break
|
||||
else:
|
||||
hist = [] # No matches except %rerun
|
||||
elif args: # Specify history ranges
|
||||
hist = self.shell.history_manager.get_range_by_str(args)
|
||||
else: # Last line
|
||||
hist = self.shell.history_manager.get_tail(1)
|
||||
hist = [x[2] for x in hist]
|
||||
if not hist:
|
||||
print("No lines in history match specification")
|
||||
return
|
||||
histlines = "\n".join(hist)
|
||||
print("=== Executing: ===")
|
||||
print(histlines)
|
||||
print("=== Output: ===")
|
||||
self.shell.run_cell("\n".join(hist), store_history=False)
|
195
venv/Lib/site-packages/IPython/core/magics/logging.py
Normal file
195
venv/Lib/site-packages/IPython/core/magics/logging.py
Normal file
|
@ -0,0 +1,195 @@
|
|||
"""Implementation of magic functions for IPython's own logging.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Stdlib
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Our own packages
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
from warnings import warn
|
||||
from traitlets import Bool
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@magics_class
|
||||
class LoggingMagics(Magics):
|
||||
"""Magics related to all logging machinery."""
|
||||
|
||||
quiet = Bool(False, help=
|
||||
"""
|
||||
Suppress output of log state when logging is enabled
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
@line_magic
|
||||
def logstart(self, parameter_s=''):
|
||||
"""Start logging anywhere in a session.
|
||||
|
||||
%logstart [-o|-r|-t|-q] [log_name [log_mode]]
|
||||
|
||||
If no name is given, it defaults to a file named 'ipython_log.py' in your
|
||||
current directory, in 'rotate' mode (see below).
|
||||
|
||||
'%logstart name' saves to file 'name' in 'backup' mode. It saves your
|
||||
history up to that point and then continues logging.
|
||||
|
||||
%logstart takes a second optional parameter: logging mode. This can be one
|
||||
of (note that the modes are given unquoted):
|
||||
|
||||
append
|
||||
Keep logging at the end of any existing file.
|
||||
|
||||
backup
|
||||
Rename any existing file to name~ and start name.
|
||||
|
||||
global
|
||||
Append to a single logfile in your home directory.
|
||||
|
||||
over
|
||||
Overwrite any existing log.
|
||||
|
||||
rotate
|
||||
Create rotating logs: name.1~, name.2~, etc.
|
||||
|
||||
Options:
|
||||
|
||||
-o
|
||||
log also IPython's output. In this mode, all commands which
|
||||
generate an Out[NN] prompt are recorded to the logfile, right after
|
||||
their corresponding input line. The output lines are always
|
||||
prepended with a '#[Out]# ' marker, so that the log remains valid
|
||||
Python code.
|
||||
|
||||
Since this marker is always the same, filtering only the output from
|
||||
a log is very easy, using for example a simple awk call::
|
||||
|
||||
awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
|
||||
|
||||
-r
|
||||
log 'raw' input. Normally, IPython's logs contain the processed
|
||||
input, so that user lines are logged in their final form, converted
|
||||
into valid Python. For example, %Exit is logged as
|
||||
_ip.magic("Exit"). If the -r flag is given, all input is logged
|
||||
exactly as typed, with no transformations applied.
|
||||
|
||||
-t
|
||||
put timestamps before each input line logged (these are put in
|
||||
comments).
|
||||
|
||||
-q
|
||||
suppress output of logstate message when logging is invoked
|
||||
"""
|
||||
|
||||
opts,par = self.parse_options(parameter_s,'ortq')
|
||||
log_output = 'o' in opts
|
||||
log_raw_input = 'r' in opts
|
||||
timestamp = 't' in opts
|
||||
quiet = 'q' in opts
|
||||
|
||||
logger = self.shell.logger
|
||||
|
||||
# if no args are given, the defaults set in the logger constructor by
|
||||
# ipython remain valid
|
||||
if par:
|
||||
try:
|
||||
logfname,logmode = par.split()
|
||||
except:
|
||||
logfname = par
|
||||
logmode = 'backup'
|
||||
else:
|
||||
logfname = logger.logfname
|
||||
logmode = logger.logmode
|
||||
# put logfname into rc struct as if it had been called on the command
|
||||
# line, so it ends up saved in the log header Save it in case we need
|
||||
# to restore it...
|
||||
old_logfile = self.shell.logfile
|
||||
if logfname:
|
||||
logfname = os.path.expanduser(logfname)
|
||||
self.shell.logfile = logfname
|
||||
|
||||
loghead = u'# IPython log file\n\n'
|
||||
try:
|
||||
logger.logstart(logfname, loghead, logmode, log_output, timestamp,
|
||||
log_raw_input)
|
||||
except:
|
||||
self.shell.logfile = old_logfile
|
||||
warn("Couldn't start log: %s" % sys.exc_info()[1])
|
||||
else:
|
||||
# log input history up to this point, optionally interleaving
|
||||
# output if requested
|
||||
|
||||
if timestamp:
|
||||
# disable timestamping for the previous history, since we've
|
||||
# lost those already (no time machine here).
|
||||
logger.timestamp = False
|
||||
|
||||
if log_raw_input:
|
||||
input_hist = self.shell.history_manager.input_hist_raw
|
||||
else:
|
||||
input_hist = self.shell.history_manager.input_hist_parsed
|
||||
|
||||
if log_output:
|
||||
log_write = logger.log_write
|
||||
output_hist = self.shell.history_manager.output_hist
|
||||
for n in range(1,len(input_hist)-1):
|
||||
log_write(input_hist[n].rstrip() + u'\n')
|
||||
if n in output_hist:
|
||||
log_write(repr(output_hist[n]),'output')
|
||||
else:
|
||||
logger.log_write(u'\n'.join(input_hist[1:]))
|
||||
logger.log_write(u'\n')
|
||||
if timestamp:
|
||||
# re-enable timestamping
|
||||
logger.timestamp = True
|
||||
|
||||
if not (self.quiet or quiet):
|
||||
print ('Activating auto-logging. '
|
||||
'Current session state plus future input saved.')
|
||||
logger.logstate()
|
||||
|
||||
@line_magic
|
||||
def logstop(self, parameter_s=''):
|
||||
"""Fully stop logging and close log file.
|
||||
|
||||
In order to start logging again, a new %logstart call needs to be made,
|
||||
possibly (though not necessarily) with a new filename, mode and other
|
||||
options."""
|
||||
self.shell.logger.logstop()
|
||||
|
||||
@line_magic
|
||||
def logoff(self, parameter_s=''):
|
||||
"""Temporarily stop logging.
|
||||
|
||||
You must have previously started logging."""
|
||||
self.shell.logger.switch_log(0)
|
||||
|
||||
@line_magic
|
||||
def logon(self, parameter_s=''):
|
||||
"""Restart logging.
|
||||
|
||||
This function is for restarting logging which you've temporarily
|
||||
stopped with %logoff. For starting logging for the first time, you
|
||||
must use the %logstart function, which allows you to specify an
|
||||
optional log filename."""
|
||||
|
||||
self.shell.logger.switch_log(1)
|
||||
|
||||
@line_magic
|
||||
def logstate(self, parameter_s=''):
|
||||
"""Print the status of the logging system."""
|
||||
|
||||
self.shell.logger.logstate()
|
708
venv/Lib/site-packages/IPython/core/magics/namespace.py
Normal file
708
venv/Lib/site-packages/IPython/core/magics/namespace.py
Normal file
|
@ -0,0 +1,708 @@
|
|||
"""Implementation of namespace-related magic functions.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Stdlib
|
||||
import gc
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Our own packages
|
||||
from IPython.core import page
|
||||
from IPython.core.error import StdinNotImplementedError, UsageError
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from IPython.utils.encoding import DEFAULT_ENCODING
|
||||
from IPython.utils.openpy import read_py_file
|
||||
from IPython.utils.path import get_py_filename
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@magics_class
|
||||
class NamespaceMagics(Magics):
|
||||
"""Magics to manage various aspects of the user's namespace.
|
||||
|
||||
These include listing variables, introspecting into them, etc.
|
||||
"""
|
||||
|
||||
@line_magic
|
||||
def pinfo(self, parameter_s='', namespaces=None):
|
||||
"""Provide detailed information about an object.
|
||||
|
||||
'%pinfo object' is just a synonym for object? or ?object."""
|
||||
|
||||
#print 'pinfo par: <%s>' % parameter_s # dbg
|
||||
# detail_level: 0 -> obj? , 1 -> obj??
|
||||
detail_level = 0
|
||||
# We need to detect if we got called as 'pinfo pinfo foo', which can
|
||||
# happen if the user types 'pinfo foo?' at the cmd line.
|
||||
pinfo,qmark1,oname,qmark2 = \
|
||||
re.match(r'(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
|
||||
if pinfo or qmark1 or qmark2:
|
||||
detail_level = 1
|
||||
if "*" in oname:
|
||||
self.psearch(oname)
|
||||
else:
|
||||
self.shell._inspect('pinfo', oname, detail_level=detail_level,
|
||||
namespaces=namespaces)
|
||||
|
||||
@line_magic
|
||||
def pinfo2(self, parameter_s='', namespaces=None):
|
||||
"""Provide extra detailed information about an object.
|
||||
|
||||
'%pinfo2 object' is just a synonym for object?? or ??object."""
|
||||
self.shell._inspect('pinfo', parameter_s, detail_level=1,
|
||||
namespaces=namespaces)
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def pdef(self, parameter_s='', namespaces=None):
|
||||
"""Print the call signature for any callable object.
|
||||
|
||||
If the object is a class, print the constructor information.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [3]: %pdef urllib.urlopen
|
||||
urllib.urlopen(url, data=None, proxies=None)
|
||||
"""
|
||||
self.shell._inspect('pdef',parameter_s, namespaces)
|
||||
|
||||
@line_magic
|
||||
def pdoc(self, parameter_s='', namespaces=None):
|
||||
"""Print the docstring for an object.
|
||||
|
||||
If the given object is a class, it will print both the class and the
|
||||
constructor docstrings."""
|
||||
self.shell._inspect('pdoc',parameter_s, namespaces)
|
||||
|
||||
@line_magic
|
||||
def psource(self, parameter_s='', namespaces=None):
|
||||
"""Print (or run through pager) the source code for an object."""
|
||||
if not parameter_s:
|
||||
raise UsageError('Missing object name.')
|
||||
self.shell._inspect('psource',parameter_s, namespaces)
|
||||
|
||||
@line_magic
|
||||
def pfile(self, parameter_s='', namespaces=None):
|
||||
"""Print (or run through pager) the file where an object is defined.
|
||||
|
||||
The file opens at the line where the object definition begins. IPython
|
||||
will honor the environment variable PAGER if set, and otherwise will
|
||||
do its best to print the file in a convenient form.
|
||||
|
||||
If the given argument is not an object currently defined, IPython will
|
||||
try to interpret it as a filename (automatically adding a .py extension
|
||||
if needed). You can thus use %pfile as a syntax highlighting code
|
||||
viewer."""
|
||||
|
||||
# first interpret argument as an object name
|
||||
out = self.shell._inspect('pfile',parameter_s, namespaces)
|
||||
# if not, try the input as a filename
|
||||
if out == 'not found':
|
||||
try:
|
||||
filename = get_py_filename(parameter_s)
|
||||
except IOError as msg:
|
||||
print(msg)
|
||||
return
|
||||
page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
|
||||
|
||||
@line_magic
|
||||
def psearch(self, parameter_s=''):
|
||||
"""Search for object in namespaces by wildcard.
|
||||
|
||||
%psearch [options] PATTERN [OBJECT TYPE]
|
||||
|
||||
Note: ? can be used as a synonym for %psearch, at the beginning or at
|
||||
the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
|
||||
rest of the command line must be unchanged (options come first), so
|
||||
for example the following forms are equivalent
|
||||
|
||||
%psearch -i a* function
|
||||
-i a* function?
|
||||
?-i a* function
|
||||
|
||||
Arguments:
|
||||
|
||||
PATTERN
|
||||
|
||||
where PATTERN is a string containing * as a wildcard similar to its
|
||||
use in a shell. The pattern is matched in all namespaces on the
|
||||
search path. By default objects starting with a single _ are not
|
||||
matched, many IPython generated objects have a single
|
||||
underscore. The default is case insensitive matching. Matching is
|
||||
also done on the attributes of objects and not only on the objects
|
||||
in a module.
|
||||
|
||||
[OBJECT TYPE]
|
||||
|
||||
Is the name of a python type from the types module. The name is
|
||||
given in lowercase without the ending type, ex. StringType is
|
||||
written string. By adding a type here only objects matching the
|
||||
given type are matched. Using all here makes the pattern match all
|
||||
types (this is the default).
|
||||
|
||||
Options:
|
||||
|
||||
-a: makes the pattern match even objects whose names start with a
|
||||
single underscore. These names are normally omitted from the
|
||||
search.
|
||||
|
||||
-i/-c: make the pattern case insensitive/sensitive. If neither of
|
||||
these options are given, the default is read from your configuration
|
||||
file, with the option ``InteractiveShell.wildcards_case_sensitive``.
|
||||
If this option is not specified in your configuration file, IPython's
|
||||
internal default is to do a case sensitive search.
|
||||
|
||||
-e/-s NAMESPACE: exclude/search a given namespace. The pattern you
|
||||
specify can be searched in any of the following namespaces:
|
||||
'builtin', 'user', 'user_global','internal', 'alias', where
|
||||
'builtin' and 'user' are the search defaults. Note that you should
|
||||
not use quotes when specifying namespaces.
|
||||
|
||||
-l: List all available object types for object matching. This function
|
||||
can be used without arguments.
|
||||
|
||||
'Builtin' contains the python module builtin, 'user' contains all
|
||||
user data, 'alias' only contain the shell aliases and no python
|
||||
objects, 'internal' contains objects used by IPython. The
|
||||
'user_global' namespace is only used by embedded IPython instances,
|
||||
and it contains module-level globals. You can add namespaces to the
|
||||
search with -s or exclude them with -e (these options can be given
|
||||
more than once).
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
%psearch a* -> objects beginning with an a
|
||||
%psearch -e builtin a* -> objects NOT in the builtin space starting in a
|
||||
%psearch a* function -> all functions beginning with an a
|
||||
%psearch re.e* -> objects beginning with an e in module re
|
||||
%psearch r*.e* -> objects that start with e in modules starting in r
|
||||
%psearch r*.* string -> all strings in modules beginning with r
|
||||
|
||||
Case sensitive search::
|
||||
|
||||
%psearch -c a* list all object beginning with lower case a
|
||||
|
||||
Show objects beginning with a single _::
|
||||
|
||||
%psearch -a _* list objects beginning with a single underscore
|
||||
|
||||
List available objects::
|
||||
|
||||
%psearch -l list all available object types
|
||||
"""
|
||||
# default namespaces to be searched
|
||||
def_search = ['user_local', 'user_global', 'builtin']
|
||||
|
||||
# Process options/args
|
||||
opts,args = self.parse_options(parameter_s,'cias:e:l',list_all=True)
|
||||
opt = opts.get
|
||||
shell = self.shell
|
||||
psearch = shell.inspector.psearch
|
||||
|
||||
# select list object types
|
||||
list_types = False
|
||||
if 'l' in opts:
|
||||
list_types = True
|
||||
|
||||
# select case options
|
||||
if 'i' in opts:
|
||||
ignore_case = True
|
||||
elif 'c' in opts:
|
||||
ignore_case = False
|
||||
else:
|
||||
ignore_case = not shell.wildcards_case_sensitive
|
||||
|
||||
# Build list of namespaces to search from user options
|
||||
def_search.extend(opt('s',[]))
|
||||
ns_exclude = ns_exclude=opt('e',[])
|
||||
ns_search = [nm for nm in def_search if nm not in ns_exclude]
|
||||
|
||||
# Call the actual search
|
||||
try:
|
||||
psearch(args,shell.ns_table,ns_search,
|
||||
show_all=opt('a'),ignore_case=ignore_case, list_types=list_types)
|
||||
except:
|
||||
shell.showtraceback()
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def who_ls(self, parameter_s=''):
|
||||
"""Return a sorted list of all interactive variables.
|
||||
|
||||
If arguments are given, only variables of types matching these
|
||||
arguments are returned.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Define two variables and list them with who_ls::
|
||||
|
||||
In [1]: alpha = 123
|
||||
|
||||
In [2]: beta = 'test'
|
||||
|
||||
In [3]: %who_ls
|
||||
Out[3]: ['alpha', 'beta']
|
||||
|
||||
In [4]: %who_ls int
|
||||
Out[4]: ['alpha']
|
||||
|
||||
In [5]: %who_ls str
|
||||
Out[5]: ['beta']
|
||||
"""
|
||||
|
||||
user_ns = self.shell.user_ns
|
||||
user_ns_hidden = self.shell.user_ns_hidden
|
||||
nonmatching = object() # This can never be in user_ns
|
||||
out = [ i for i in user_ns
|
||||
if not i.startswith('_') \
|
||||
and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
|
||||
|
||||
typelist = parameter_s.split()
|
||||
if typelist:
|
||||
typeset = set(typelist)
|
||||
out = [i for i in out if type(user_ns[i]).__name__ in typeset]
|
||||
|
||||
out.sort()
|
||||
return out
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def who(self, parameter_s=''):
|
||||
"""Print all interactive variables, with some minimal formatting.
|
||||
|
||||
If any arguments are given, only variables whose type matches one of
|
||||
these are printed. For example::
|
||||
|
||||
%who function str
|
||||
|
||||
will only list functions and strings, excluding all other types of
|
||||
variables. To find the proper type names, simply use type(var) at a
|
||||
command line to see how python prints type names. For example:
|
||||
|
||||
::
|
||||
|
||||
In [1]: type('hello')\\
|
||||
Out[1]: <type 'str'>
|
||||
|
||||
indicates that the type name for strings is 'str'.
|
||||
|
||||
``%who`` always excludes executed names loaded through your configuration
|
||||
file and things which are internal to IPython.
|
||||
|
||||
This is deliberate, as typically you may load many modules and the
|
||||
purpose of %who is to show you only what you've manually defined.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Define two variables and list them with who::
|
||||
|
||||
In [1]: alpha = 123
|
||||
|
||||
In [2]: beta = 'test'
|
||||
|
||||
In [3]: %who
|
||||
alpha beta
|
||||
|
||||
In [4]: %who int
|
||||
alpha
|
||||
|
||||
In [5]: %who str
|
||||
beta
|
||||
"""
|
||||
|
||||
varlist = self.who_ls(parameter_s)
|
||||
if not varlist:
|
||||
if parameter_s:
|
||||
print('No variables match your requested type.')
|
||||
else:
|
||||
print('Interactive namespace is empty.')
|
||||
return
|
||||
|
||||
# if we have variables, move on...
|
||||
count = 0
|
||||
for i in varlist:
|
||||
print(i+'\t', end=' ')
|
||||
count += 1
|
||||
if count > 8:
|
||||
count = 0
|
||||
print()
|
||||
print()
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def whos(self, parameter_s=''):
|
||||
"""Like %who, but gives some extra information about each variable.
|
||||
|
||||
The same type filtering of %who can be applied here.
|
||||
|
||||
For all variables, the type is printed. Additionally it prints:
|
||||
|
||||
- For {},[],(): their length.
|
||||
|
||||
- For numpy arrays, a summary with shape, number of
|
||||
elements, typecode and size in memory.
|
||||
|
||||
- Everything else: a string representation, snipping their middle if
|
||||
too long.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Define two variables and list them with whos::
|
||||
|
||||
In [1]: alpha = 123
|
||||
|
||||
In [2]: beta = 'test'
|
||||
|
||||
In [3]: %whos
|
||||
Variable Type Data/Info
|
||||
--------------------------------
|
||||
alpha int 123
|
||||
beta str test
|
||||
"""
|
||||
|
||||
varnames = self.who_ls(parameter_s)
|
||||
if not varnames:
|
||||
if parameter_s:
|
||||
print('No variables match your requested type.')
|
||||
else:
|
||||
print('Interactive namespace is empty.')
|
||||
return
|
||||
|
||||
# if we have variables, move on...
|
||||
|
||||
# for these types, show len() instead of data:
|
||||
seq_types = ['dict', 'list', 'tuple']
|
||||
|
||||
# for numpy arrays, display summary info
|
||||
ndarray_type = None
|
||||
if 'numpy' in sys.modules:
|
||||
try:
|
||||
from numpy import ndarray
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ndarray_type = ndarray.__name__
|
||||
|
||||
# Find all variable names and types so we can figure out column sizes
|
||||
|
||||
# some types are well known and can be shorter
|
||||
abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
|
||||
def type_name(v):
|
||||
tn = type(v).__name__
|
||||
return abbrevs.get(tn,tn)
|
||||
|
||||
varlist = [self.shell.user_ns[n] for n in varnames]
|
||||
|
||||
typelist = []
|
||||
for vv in varlist:
|
||||
tt = type_name(vv)
|
||||
|
||||
if tt=='instance':
|
||||
typelist.append( abbrevs.get(str(vv.__class__),
|
||||
str(vv.__class__)))
|
||||
else:
|
||||
typelist.append(tt)
|
||||
|
||||
# column labels and # of spaces as separator
|
||||
varlabel = 'Variable'
|
||||
typelabel = 'Type'
|
||||
datalabel = 'Data/Info'
|
||||
colsep = 3
|
||||
# variable format strings
|
||||
vformat = "{0:<{varwidth}}{1:<{typewidth}}"
|
||||
aformat = "%s: %s elems, type `%s`, %s bytes"
|
||||
# find the size of the columns to format the output nicely
|
||||
varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
|
||||
typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
|
||||
# table header
|
||||
print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
|
||||
' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
|
||||
# and the table itself
|
||||
kb = 1024
|
||||
Mb = 1048576 # kb**2
|
||||
for vname,var,vtype in zip(varnames,varlist,typelist):
|
||||
print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
|
||||
if vtype in seq_types:
|
||||
print("n="+str(len(var)))
|
||||
elif vtype == ndarray_type:
|
||||
vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
|
||||
if vtype==ndarray_type:
|
||||
# numpy
|
||||
vsize = var.size
|
||||
vbytes = vsize*var.itemsize
|
||||
vdtype = var.dtype
|
||||
|
||||
if vbytes < 100000:
|
||||
print(aformat % (vshape, vsize, vdtype, vbytes))
|
||||
else:
|
||||
print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
|
||||
if vbytes < Mb:
|
||||
print('(%s kb)' % (vbytes/kb,))
|
||||
else:
|
||||
print('(%s Mb)' % (vbytes/Mb,))
|
||||
else:
|
||||
try:
|
||||
vstr = str(var)
|
||||
except UnicodeEncodeError:
|
||||
vstr = var.encode(DEFAULT_ENCODING,
|
||||
'backslashreplace')
|
||||
except:
|
||||
vstr = "<object with id %d (str() failed)>" % id(var)
|
||||
vstr = vstr.replace('\n', '\\n')
|
||||
if len(vstr) < 50:
|
||||
print(vstr)
|
||||
else:
|
||||
print(vstr[:25] + "<...>" + vstr[-25:])
|
||||
|
||||
@line_magic
|
||||
def reset(self, parameter_s=''):
|
||||
"""Resets the namespace by removing all names defined by the user, if
|
||||
called without arguments, or by removing some types of objects, such
|
||||
as everything currently in IPython's In[] and Out[] containers (see
|
||||
the parameters for details).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
-f : force reset without asking for confirmation.
|
||||
|
||||
-s : 'Soft' reset: Only clears your namespace, leaving history intact.
|
||||
References to objects may be kept. By default (without this option),
|
||||
we do a 'hard' reset, giving you a new session and removing all
|
||||
references to objects from the current session.
|
||||
|
||||
in : reset input history
|
||||
|
||||
out : reset output history
|
||||
|
||||
dhist : reset directory history
|
||||
|
||||
array : reset only variables that are NumPy arrays
|
||||
|
||||
See Also
|
||||
--------
|
||||
reset_selective : invoked as ``%reset_selective``
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [6]: a = 1
|
||||
|
||||
In [7]: a
|
||||
Out[7]: 1
|
||||
|
||||
In [8]: 'a' in get_ipython().user_ns
|
||||
Out[8]: True
|
||||
|
||||
In [9]: %reset -f
|
||||
|
||||
In [1]: 'a' in get_ipython().user_ns
|
||||
Out[1]: False
|
||||
|
||||
In [2]: %reset -f in
|
||||
Flushing input history
|
||||
|
||||
In [3]: %reset -f dhist in
|
||||
Flushing directory history
|
||||
Flushing input history
|
||||
|
||||
Notes
|
||||
-----
|
||||
Calling this magic from clients that do not implement standard input,
|
||||
such as the ipython notebook interface, will reset the namespace
|
||||
without confirmation.
|
||||
"""
|
||||
opts, args = self.parse_options(parameter_s,'sf', mode='list')
|
||||
if 'f' in opts:
|
||||
ans = True
|
||||
else:
|
||||
try:
|
||||
ans = self.shell.ask_yes_no(
|
||||
"Once deleted, variables cannot be recovered. Proceed (y/[n])?",
|
||||
default='n')
|
||||
except StdinNotImplementedError:
|
||||
ans = True
|
||||
if not ans:
|
||||
print('Nothing done.')
|
||||
return
|
||||
|
||||
if 's' in opts: # Soft reset
|
||||
user_ns = self.shell.user_ns
|
||||
for i in self.who_ls():
|
||||
del(user_ns[i])
|
||||
elif len(args) == 0: # Hard reset
|
||||
self.shell.reset(new_session = False)
|
||||
|
||||
# reset in/out/dhist/array: previously extensinions/clearcmd.py
|
||||
ip = self.shell
|
||||
user_ns = self.shell.user_ns # local lookup, heavily used
|
||||
|
||||
for target in args:
|
||||
target = target.lower() # make matches case insensitive
|
||||
if target == 'out':
|
||||
print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
|
||||
self.shell.displayhook.flush()
|
||||
|
||||
elif target == 'in':
|
||||
print("Flushing input history")
|
||||
pc = self.shell.displayhook.prompt_count + 1
|
||||
for n in range(1, pc):
|
||||
key = '_i'+repr(n)
|
||||
user_ns.pop(key,None)
|
||||
user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
|
||||
hm = ip.history_manager
|
||||
# don't delete these, as %save and %macro depending on the
|
||||
# length of these lists to be preserved
|
||||
hm.input_hist_parsed[:] = [''] * pc
|
||||
hm.input_hist_raw[:] = [''] * pc
|
||||
# hm has internal machinery for _i,_ii,_iii, clear it out
|
||||
hm._i = hm._ii = hm._iii = hm._i00 = u''
|
||||
|
||||
elif target == 'array':
|
||||
# Support cleaning up numpy arrays
|
||||
try:
|
||||
from numpy import ndarray
|
||||
# This must be done with items and not iteritems because
|
||||
# we're going to modify the dict in-place.
|
||||
for x,val in list(user_ns.items()):
|
||||
if isinstance(val,ndarray):
|
||||
del user_ns[x]
|
||||
except ImportError:
|
||||
print("reset array only works if Numpy is available.")
|
||||
|
||||
elif target == 'dhist':
|
||||
print("Flushing directory history")
|
||||
del user_ns['_dh'][:]
|
||||
|
||||
else:
|
||||
print("Don't know how to reset ", end=' ')
|
||||
print(target + ", please run `%reset?` for details")
|
||||
|
||||
gc.collect()
|
||||
|
||||
@line_magic
|
||||
def reset_selective(self, parameter_s=''):
|
||||
"""Resets the namespace by removing names defined by the user.
|
||||
|
||||
Input/Output history are left around in case you need them.
|
||||
|
||||
%reset_selective [-f] regex
|
||||
|
||||
No action is taken if regex is not included
|
||||
|
||||
Options
|
||||
-f : force reset without asking for confirmation.
|
||||
|
||||
See Also
|
||||
--------
|
||||
reset : invoked as ``%reset``
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
We first fully reset the namespace so your output looks identical to
|
||||
this example for pedagogical reasons; in practice you do not need a
|
||||
full reset::
|
||||
|
||||
In [1]: %reset -f
|
||||
|
||||
Now, with a clean namespace we can make a few variables and use
|
||||
``%reset_selective`` to only delete names that match our regexp::
|
||||
|
||||
In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
|
||||
|
||||
In [3]: who_ls
|
||||
Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
|
||||
|
||||
In [4]: %reset_selective -f b[2-3]m
|
||||
|
||||
In [5]: who_ls
|
||||
Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
|
||||
|
||||
In [6]: %reset_selective -f d
|
||||
|
||||
In [7]: who_ls
|
||||
Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
|
||||
|
||||
In [8]: %reset_selective -f c
|
||||
|
||||
In [9]: who_ls
|
||||
Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
|
||||
|
||||
In [10]: %reset_selective -f b
|
||||
|
||||
In [11]: who_ls
|
||||
Out[11]: ['a']
|
||||
|
||||
Notes
|
||||
-----
|
||||
Calling this magic from clients that do not implement standard input,
|
||||
such as the ipython notebook interface, will reset the namespace
|
||||
without confirmation.
|
||||
"""
|
||||
|
||||
opts, regex = self.parse_options(parameter_s,'f')
|
||||
|
||||
if 'f' in opts:
|
||||
ans = True
|
||||
else:
|
||||
try:
|
||||
ans = self.shell.ask_yes_no(
|
||||
"Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
|
||||
default='n')
|
||||
except StdinNotImplementedError:
|
||||
ans = True
|
||||
if not ans:
|
||||
print('Nothing done.')
|
||||
return
|
||||
user_ns = self.shell.user_ns
|
||||
if not regex:
|
||||
print('No regex pattern specified. Nothing done.')
|
||||
return
|
||||
else:
|
||||
try:
|
||||
m = re.compile(regex)
|
||||
except TypeError:
|
||||
raise TypeError('regex must be a string or compiled pattern')
|
||||
for i in self.who_ls():
|
||||
if m.search(i):
|
||||
del(user_ns[i])
|
||||
|
||||
@line_magic
|
||||
def xdel(self, parameter_s=''):
|
||||
"""Delete a variable, trying to clear it from anywhere that
|
||||
IPython's machinery has references to it. By default, this uses
|
||||
the identity of the named object in the user namespace to remove
|
||||
references held under other names. The object is also removed
|
||||
from the output history.
|
||||
|
||||
Options
|
||||
-n : Delete the specified name from all namespaces, without
|
||||
checking their identity.
|
||||
"""
|
||||
opts, varname = self.parse_options(parameter_s,'n')
|
||||
try:
|
||||
self.shell.del_var(varname, ('n' in opts))
|
||||
except (NameError, ValueError) as e:
|
||||
print(type(e).__name__ +": "+ str(e))
|
857
venv/Lib/site-packages/IPython/core/magics/osm.py
Normal file
857
venv/Lib/site-packages/IPython/core/magics/osm.py
Normal file
|
@ -0,0 +1,857 @@
|
|||
"""Implementation of magic functions for interaction with the OS.
|
||||
|
||||
Note: this module is named 'osm' instead of 'os' to avoid a collision with the
|
||||
builtin.
|
||||
"""
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pprint import pformat
|
||||
|
||||
from IPython.core import magic_arguments
|
||||
from IPython.core import oinspect
|
||||
from IPython.core import page
|
||||
from IPython.core.alias import AliasError, Alias
|
||||
from IPython.core.error import UsageError
|
||||
from IPython.core.magic import (
|
||||
Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
|
||||
)
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from IPython.utils.openpy import source_to_unicode
|
||||
from IPython.utils.process import abbrev_cwd
|
||||
from IPython.utils.terminal import set_term_title
|
||||
from traitlets import Bool
|
||||
from warnings import warn
|
||||
|
||||
|
||||
@magics_class
|
||||
class OSMagics(Magics):
|
||||
"""Magics to interact with the underlying OS (shell-type functionality).
|
||||
"""
|
||||
|
||||
cd_force_quiet = Bool(False,
|
||||
help="Force %cd magic to be quiet even if -q is not passed."
|
||||
).tag(config=True)
|
||||
|
||||
def __init__(self, shell=None, **kwargs):
|
||||
|
||||
# Now define isexec in a cross platform manner.
|
||||
self.is_posix = False
|
||||
self.execre = None
|
||||
if os.name == 'posix':
|
||||
self.is_posix = True
|
||||
else:
|
||||
try:
|
||||
winext = os.environ['pathext'].replace(';','|').replace('.','')
|
||||
except KeyError:
|
||||
winext = 'exe|com|bat|py'
|
||||
try:
|
||||
self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
|
||||
except re.error:
|
||||
warn("Seems like your pathext environmental "
|
||||
"variable is malformed. Please check it to "
|
||||
"enable a proper handle of file extensions "
|
||||
"managed for your system")
|
||||
winext = 'exe|com|bat|py'
|
||||
self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
|
||||
|
||||
# call up the chain
|
||||
super().__init__(shell=shell, **kwargs)
|
||||
|
||||
|
||||
@skip_doctest
|
||||
def _isexec_POSIX(self, file):
|
||||
"""
|
||||
Test for executable on a POSIX system
|
||||
"""
|
||||
if os.access(file.path, os.X_OK):
|
||||
# will fail on maxOS if access is not X_OK
|
||||
return file.is_file()
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@skip_doctest
|
||||
def _isexec_WIN(self, file):
|
||||
"""
|
||||
Test for executable file on non POSIX system
|
||||
"""
|
||||
return file.is_file() and self.execre.match(file.name) is not None
|
||||
|
||||
@skip_doctest
|
||||
def isexec(self, file):
|
||||
"""
|
||||
Test for executable file on non POSIX system
|
||||
"""
|
||||
if self.is_posix:
|
||||
return self._isexec_POSIX(file)
|
||||
else:
|
||||
return self._isexec_WIN(file)
|
||||
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def alias(self, parameter_s=''):
|
||||
"""Define an alias for a system command.
|
||||
|
||||
'%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
|
||||
|
||||
Then, typing 'alias_name params' will execute the system command 'cmd
|
||||
params' (from your underlying operating system).
|
||||
|
||||
Aliases have lower precedence than magic functions and Python normal
|
||||
variables, so if 'foo' is both a Python variable and an alias, the
|
||||
alias can not be executed until 'del foo' removes the Python variable.
|
||||
|
||||
You can use the %l specifier in an alias definition to represent the
|
||||
whole line when the alias is called. For example::
|
||||
|
||||
In [2]: alias bracket echo "Input in brackets: <%l>"
|
||||
In [3]: bracket hello world
|
||||
Input in brackets: <hello world>
|
||||
|
||||
You can also define aliases with parameters using %s specifiers (one
|
||||
per parameter)::
|
||||
|
||||
In [1]: alias parts echo first %s second %s
|
||||
In [2]: %parts A B
|
||||
first A second B
|
||||
In [3]: %parts A
|
||||
Incorrect number of arguments: 2 expected.
|
||||
parts is an alias to: 'echo first %s second %s'
|
||||
|
||||
Note that %l and %s are mutually exclusive. You can only use one or
|
||||
the other in your aliases.
|
||||
|
||||
Aliases expand Python variables just like system calls using ! or !!
|
||||
do: all expressions prefixed with '$' get expanded. For details of
|
||||
the semantic rules, see PEP-215:
|
||||
http://www.python.org/peps/pep-0215.html. This is the library used by
|
||||
IPython for variable expansion. If you want to access a true shell
|
||||
variable, an extra $ is necessary to prevent its expansion by
|
||||
IPython::
|
||||
|
||||
In [6]: alias show echo
|
||||
In [7]: PATH='A Python string'
|
||||
In [8]: show $PATH
|
||||
A Python string
|
||||
In [9]: show $$PATH
|
||||
/usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
|
||||
|
||||
You can use the alias facility to access all of $PATH. See the %rehashx
|
||||
function, which automatically creates aliases for the contents of your
|
||||
$PATH.
|
||||
|
||||
If called with no parameters, %alias prints the current alias table
|
||||
for your system. For posix systems, the default aliases are 'cat',
|
||||
'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
|
||||
aliases are added. For windows-based systems, the default aliases are
|
||||
'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
|
||||
|
||||
You can see the definition of alias by adding a question mark in the
|
||||
end::
|
||||
|
||||
In [1]: cat?
|
||||
Repr: <alias cat for 'cat'>"""
|
||||
|
||||
par = parameter_s.strip()
|
||||
if not par:
|
||||
aliases = sorted(self.shell.alias_manager.aliases)
|
||||
# stored = self.shell.db.get('stored_aliases', {} )
|
||||
# for k, v in stored:
|
||||
# atab.append(k, v[0])
|
||||
|
||||
print("Total number of aliases:", len(aliases))
|
||||
sys.stdout.flush()
|
||||
return aliases
|
||||
|
||||
# Now try to define a new one
|
||||
try:
|
||||
alias,cmd = par.split(None, 1)
|
||||
except TypeError:
|
||||
print(oinspect.getdoc(self.alias))
|
||||
return
|
||||
|
||||
try:
|
||||
self.shell.alias_manager.define_alias(alias, cmd)
|
||||
except AliasError as e:
|
||||
print(e)
|
||||
# end magic_alias
|
||||
|
||||
@line_magic
|
||||
def unalias(self, parameter_s=''):
|
||||
"""Remove an alias"""
|
||||
|
||||
aname = parameter_s.strip()
|
||||
try:
|
||||
self.shell.alias_manager.undefine_alias(aname)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
return
|
||||
|
||||
stored = self.shell.db.get('stored_aliases', {} )
|
||||
if aname in stored:
|
||||
print("Removing %stored alias",aname)
|
||||
del stored[aname]
|
||||
self.shell.db['stored_aliases'] = stored
|
||||
|
||||
@line_magic
|
||||
def rehashx(self, parameter_s=''):
|
||||
"""Update the alias table with all executable files in $PATH.
|
||||
|
||||
rehashx explicitly checks that every entry in $PATH is a file
|
||||
with execute access (os.X_OK).
|
||||
|
||||
Under Windows, it checks executability as a match against a
|
||||
'|'-separated string of extensions, stored in the IPython config
|
||||
variable win_exec_ext. This defaults to 'exe|com|bat'.
|
||||
|
||||
This function also resets the root module cache of module completer,
|
||||
used on slow filesystems.
|
||||
"""
|
||||
from IPython.core.alias import InvalidAliasError
|
||||
|
||||
# for the benefit of module completer in ipy_completers.py
|
||||
del self.shell.db['rootmodules_cache']
|
||||
|
||||
path = [os.path.abspath(os.path.expanduser(p)) for p in
|
||||
os.environ.get('PATH','').split(os.pathsep)]
|
||||
|
||||
syscmdlist = []
|
||||
savedir = os.getcwd()
|
||||
|
||||
# Now walk the paths looking for executables to alias.
|
||||
try:
|
||||
# write the whole loop for posix/Windows so we don't have an if in
|
||||
# the innermost part
|
||||
if self.is_posix:
|
||||
for pdir in path:
|
||||
try:
|
||||
os.chdir(pdir)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
# for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
|
||||
dirlist = os.scandir(path=pdir)
|
||||
for ff in dirlist:
|
||||
if self.isexec(ff):
|
||||
fname = ff.name
|
||||
try:
|
||||
# Removes dots from the name since ipython
|
||||
# will assume names with dots to be python.
|
||||
if not self.shell.alias_manager.is_alias(fname):
|
||||
self.shell.alias_manager.define_alias(
|
||||
fname.replace('.',''), fname)
|
||||
except InvalidAliasError:
|
||||
pass
|
||||
else:
|
||||
syscmdlist.append(fname)
|
||||
else:
|
||||
no_alias = Alias.blacklist
|
||||
for pdir in path:
|
||||
try:
|
||||
os.chdir(pdir)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
# for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
|
||||
dirlist = os.scandir(pdir)
|
||||
for ff in dirlist:
|
||||
fname = ff.name
|
||||
base, ext = os.path.splitext(fname)
|
||||
if self.isexec(ff) and base.lower() not in no_alias:
|
||||
if ext.lower() == '.exe':
|
||||
fname = base
|
||||
try:
|
||||
# Removes dots from the name since ipython
|
||||
# will assume names with dots to be python.
|
||||
self.shell.alias_manager.define_alias(
|
||||
base.lower().replace('.',''), fname)
|
||||
except InvalidAliasError:
|
||||
pass
|
||||
syscmdlist.append(fname)
|
||||
|
||||
self.shell.db['syscmdlist'] = syscmdlist
|
||||
finally:
|
||||
os.chdir(savedir)
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def pwd(self, parameter_s=''):
|
||||
"""Return the current working directory path.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [9]: pwd
|
||||
Out[9]: '/home/tsuser/sprint/ipython'
|
||||
"""
|
||||
try:
|
||||
return os.getcwd()
|
||||
except FileNotFoundError:
|
||||
raise UsageError("CWD no longer exists - please use %cd to change directory.")
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def cd(self, parameter_s=''):
|
||||
"""Change the current working directory.
|
||||
|
||||
This command automatically maintains an internal list of directories
|
||||
you visit during your IPython session, in the variable _dh. The
|
||||
command %dhist shows this history nicely formatted. You can also
|
||||
do 'cd -<tab>' to see directory history conveniently.
|
||||
|
||||
Usage:
|
||||
|
||||
cd 'dir': changes to directory 'dir'.
|
||||
|
||||
cd -: changes to the last visited directory.
|
||||
|
||||
cd -<n>: changes to the n-th directory in the directory history.
|
||||
|
||||
cd --foo: change to directory that matches 'foo' in history
|
||||
|
||||
cd -b <bookmark_name>: jump to a bookmark set by %bookmark
|
||||
(note: cd <bookmark_name> is enough if there is no
|
||||
directory <bookmark_name>, but a bookmark with the name exists.)
|
||||
'cd -b <tab>' allows you to tab-complete bookmark names.
|
||||
|
||||
Options:
|
||||
|
||||
-q: quiet. Do not print the working directory after the cd command is
|
||||
executed. By default IPython's cd command does print this directory,
|
||||
since the default prompts do not display path information.
|
||||
|
||||
Note that !cd doesn't work for this purpose because the shell where
|
||||
!command runs is immediately discarded after executing 'command'.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [10]: cd parent/child
|
||||
/home/tsuser/parent/child
|
||||
"""
|
||||
|
||||
try:
|
||||
oldcwd = os.getcwd()
|
||||
except FileNotFoundError:
|
||||
# Happens if the CWD has been deleted.
|
||||
oldcwd = None
|
||||
|
||||
numcd = re.match(r'(-)(\d+)$',parameter_s)
|
||||
# jump in directory history by number
|
||||
if numcd:
|
||||
nn = int(numcd.group(2))
|
||||
try:
|
||||
ps = self.shell.user_ns['_dh'][nn]
|
||||
except IndexError:
|
||||
print('The requested directory does not exist in history.')
|
||||
return
|
||||
else:
|
||||
opts = {}
|
||||
elif parameter_s.startswith('--'):
|
||||
ps = None
|
||||
fallback = None
|
||||
pat = parameter_s[2:]
|
||||
dh = self.shell.user_ns['_dh']
|
||||
# first search only by basename (last component)
|
||||
for ent in reversed(dh):
|
||||
if pat in os.path.basename(ent) and os.path.isdir(ent):
|
||||
ps = ent
|
||||
break
|
||||
|
||||
if fallback is None and pat in ent and os.path.isdir(ent):
|
||||
fallback = ent
|
||||
|
||||
# if we have no last part match, pick the first full path match
|
||||
if ps is None:
|
||||
ps = fallback
|
||||
|
||||
if ps is None:
|
||||
print("No matching entry in directory history")
|
||||
return
|
||||
else:
|
||||
opts = {}
|
||||
|
||||
|
||||
else:
|
||||
opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
|
||||
# jump to previous
|
||||
if ps == '-':
|
||||
try:
|
||||
ps = self.shell.user_ns['_dh'][-2]
|
||||
except IndexError:
|
||||
raise UsageError('%cd -: No previous directory to change to.')
|
||||
# jump to bookmark if needed
|
||||
else:
|
||||
if not os.path.isdir(ps) or 'b' in opts:
|
||||
bkms = self.shell.db.get('bookmarks', {})
|
||||
|
||||
if ps in bkms:
|
||||
target = bkms[ps]
|
||||
print('(bookmark:%s) -> %s' % (ps, target))
|
||||
ps = target
|
||||
else:
|
||||
if 'b' in opts:
|
||||
raise UsageError("Bookmark '%s' not found. "
|
||||
"Use '%%bookmark -l' to see your bookmarks." % ps)
|
||||
|
||||
# at this point ps should point to the target dir
|
||||
if ps:
|
||||
try:
|
||||
os.chdir(os.path.expanduser(ps))
|
||||
if hasattr(self.shell, 'term_title') and self.shell.term_title:
|
||||
set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
|
||||
except OSError:
|
||||
print(sys.exc_info()[1])
|
||||
else:
|
||||
cwd = os.getcwd()
|
||||
dhist = self.shell.user_ns['_dh']
|
||||
if oldcwd != cwd:
|
||||
dhist.append(cwd)
|
||||
self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
|
||||
|
||||
else:
|
||||
os.chdir(self.shell.home_dir)
|
||||
if hasattr(self.shell, 'term_title') and self.shell.term_title:
|
||||
set_term_title(self.shell.term_title_format.format(cwd="~"))
|
||||
cwd = os.getcwd()
|
||||
dhist = self.shell.user_ns['_dh']
|
||||
|
||||
if oldcwd != cwd:
|
||||
dhist.append(cwd)
|
||||
self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
|
||||
if not 'q' in opts and not self.cd_force_quiet and self.shell.user_ns['_dh']:
|
||||
print(self.shell.user_ns['_dh'][-1])
|
||||
|
||||
@line_magic
|
||||
def env(self, parameter_s=''):
|
||||
"""Get, set, or list environment variables.
|
||||
|
||||
Usage:\\
|
||||
|
||||
%env: lists all environment variables/values
|
||||
%env var: get value for var
|
||||
%env var val: set value for var
|
||||
%env var=val: set value for var
|
||||
%env var=$val: set value for var, using python expansion if possible
|
||||
"""
|
||||
if parameter_s.strip():
|
||||
split = '=' if '=' in parameter_s else ' '
|
||||
bits = parameter_s.split(split)
|
||||
if len(bits) == 1:
|
||||
key = parameter_s.strip()
|
||||
if key in os.environ:
|
||||
return os.environ[key]
|
||||
else:
|
||||
err = "Environment does not have key: {0}".format(key)
|
||||
raise UsageError(err)
|
||||
if len(bits) > 1:
|
||||
return self.set_env(parameter_s)
|
||||
env = dict(os.environ)
|
||||
# hide likely secrets when printing the whole environment
|
||||
for key in list(env):
|
||||
if any(s in key.lower() for s in ('key', 'token', 'secret')):
|
||||
env[key] = '<hidden>'
|
||||
|
||||
return env
|
||||
|
||||
@line_magic
|
||||
def set_env(self, parameter_s):
|
||||
"""Set environment variables. Assumptions are that either "val" is a
|
||||
name in the user namespace, or val is something that evaluates to a
|
||||
string.
|
||||
|
||||
Usage:\\
|
||||
%set_env var val: set value for var
|
||||
%set_env var=val: set value for var
|
||||
%set_env var=$val: set value for var, using python expansion if possible
|
||||
"""
|
||||
split = '=' if '=' in parameter_s else ' '
|
||||
bits = parameter_s.split(split, 1)
|
||||
if not parameter_s.strip() or len(bits)<2:
|
||||
raise UsageError("usage is 'set_env var=val'")
|
||||
var = bits[0].strip()
|
||||
val = bits[1].strip()
|
||||
if re.match(r'.*\s.*', var):
|
||||
# an environment variable with whitespace is almost certainly
|
||||
# not what the user intended. what's more likely is the wrong
|
||||
# split was chosen, ie for "set_env cmd_args A=B", we chose
|
||||
# '=' for the split and should have chosen ' '. to get around
|
||||
# this, users should just assign directly to os.environ or use
|
||||
# standard magic {var} expansion.
|
||||
err = "refusing to set env var with whitespace: '{0}'"
|
||||
err = err.format(val)
|
||||
raise UsageError(err)
|
||||
os.environ[var] = val
|
||||
print('env: {0}={1}'.format(var,val))
|
||||
|
||||
@line_magic
|
||||
def pushd(self, parameter_s=''):
|
||||
"""Place the current dir on stack and change directory.
|
||||
|
||||
Usage:\\
|
||||
%pushd ['dirname']
|
||||
"""
|
||||
|
||||
dir_s = self.shell.dir_stack
|
||||
tgt = os.path.expanduser(parameter_s)
|
||||
cwd = os.getcwd().replace(self.shell.home_dir,'~')
|
||||
if tgt:
|
||||
self.cd(parameter_s)
|
||||
dir_s.insert(0,cwd)
|
||||
return self.shell.magic('dirs')
|
||||
|
||||
@line_magic
|
||||
def popd(self, parameter_s=''):
|
||||
"""Change to directory popped off the top of the stack.
|
||||
"""
|
||||
if not self.shell.dir_stack:
|
||||
raise UsageError("%popd on empty stack")
|
||||
top = self.shell.dir_stack.pop(0)
|
||||
self.cd(top)
|
||||
print("popd ->",top)
|
||||
|
||||
@line_magic
|
||||
def dirs(self, parameter_s=''):
|
||||
"""Return the current directory stack."""
|
||||
|
||||
return self.shell.dir_stack
|
||||
|
||||
@line_magic
|
||||
def dhist(self, parameter_s=''):
|
||||
"""Print your history of visited directories.
|
||||
|
||||
%dhist -> print full history\\
|
||||
%dhist n -> print last n entries only\\
|
||||
%dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
|
||||
|
||||
This history is automatically maintained by the %cd command, and
|
||||
always available as the global list variable _dh. You can use %cd -<n>
|
||||
to go to directory number <n>.
|
||||
|
||||
Note that most of time, you should view directory history by entering
|
||||
cd -<TAB>.
|
||||
|
||||
"""
|
||||
|
||||
dh = self.shell.user_ns['_dh']
|
||||
if parameter_s:
|
||||
try:
|
||||
args = map(int,parameter_s.split())
|
||||
except:
|
||||
self.arg_err(self.dhist)
|
||||
return
|
||||
if len(args) == 1:
|
||||
ini,fin = max(len(dh)-(args[0]),0),len(dh)
|
||||
elif len(args) == 2:
|
||||
ini,fin = args
|
||||
fin = min(fin, len(dh))
|
||||
else:
|
||||
self.arg_err(self.dhist)
|
||||
return
|
||||
else:
|
||||
ini,fin = 0,len(dh)
|
||||
print('Directory history (kept in _dh)')
|
||||
for i in range(ini, fin):
|
||||
print("%d: %s" % (i, dh[i]))
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
def sc(self, parameter_s=''):
|
||||
"""Shell capture - run shell command and capture output (DEPRECATED use !).
|
||||
|
||||
DEPRECATED. Suboptimal, retained for backwards compatibility.
|
||||
|
||||
You should use the form 'var = !command' instead. Example:
|
||||
|
||||
"%sc -l myfiles = ls ~" should now be written as
|
||||
|
||||
"myfiles = !ls ~"
|
||||
|
||||
myfiles.s, myfiles.l and myfiles.n still apply as documented
|
||||
below.
|
||||
|
||||
--
|
||||
%sc [options] varname=command
|
||||
|
||||
IPython will run the given command using commands.getoutput(), and
|
||||
will then update the user's interactive namespace with a variable
|
||||
called varname, containing the value of the call. Your command can
|
||||
contain shell wildcards, pipes, etc.
|
||||
|
||||
The '=' sign in the syntax is mandatory, and the variable name you
|
||||
supply must follow Python's standard conventions for valid names.
|
||||
|
||||
(A special format without variable name exists for internal use)
|
||||
|
||||
Options:
|
||||
|
||||
-l: list output. Split the output on newlines into a list before
|
||||
assigning it to the given variable. By default the output is stored
|
||||
as a single string.
|
||||
|
||||
-v: verbose. Print the contents of the variable.
|
||||
|
||||
In most cases you should not need to split as a list, because the
|
||||
returned value is a special type of string which can automatically
|
||||
provide its contents either as a list (split on newlines) or as a
|
||||
space-separated string. These are convenient, respectively, either
|
||||
for sequential processing or to be passed to a shell command.
|
||||
|
||||
For example::
|
||||
|
||||
# Capture into variable a
|
||||
In [1]: sc a=ls *py
|
||||
|
||||
# a is a string with embedded newlines
|
||||
In [2]: a
|
||||
Out[2]: 'setup.py\\nwin32_manual_post_install.py'
|
||||
|
||||
# which can be seen as a list:
|
||||
In [3]: a.l
|
||||
Out[3]: ['setup.py', 'win32_manual_post_install.py']
|
||||
|
||||
# or as a whitespace-separated string:
|
||||
In [4]: a.s
|
||||
Out[4]: 'setup.py win32_manual_post_install.py'
|
||||
|
||||
# a.s is useful to pass as a single command line:
|
||||
In [5]: !wc -l $a.s
|
||||
146 setup.py
|
||||
130 win32_manual_post_install.py
|
||||
276 total
|
||||
|
||||
# while the list form is useful to loop over:
|
||||
In [6]: for f in a.l:
|
||||
...: !wc -l $f
|
||||
...:
|
||||
146 setup.py
|
||||
130 win32_manual_post_install.py
|
||||
|
||||
Similarly, the lists returned by the -l option are also special, in
|
||||
the sense that you can equally invoke the .s attribute on them to
|
||||
automatically get a whitespace-separated string from their contents::
|
||||
|
||||
In [7]: sc -l b=ls *py
|
||||
|
||||
In [8]: b
|
||||
Out[8]: ['setup.py', 'win32_manual_post_install.py']
|
||||
|
||||
In [9]: b.s
|
||||
Out[9]: 'setup.py win32_manual_post_install.py'
|
||||
|
||||
In summary, both the lists and strings used for output capture have
|
||||
the following special attributes::
|
||||
|
||||
.l (or .list) : value as list.
|
||||
.n (or .nlstr): value as newline-separated string.
|
||||
.s (or .spstr): value as space-separated string.
|
||||
"""
|
||||
|
||||
opts,args = self.parse_options(parameter_s, 'lv')
|
||||
# Try to get a variable name and command to run
|
||||
try:
|
||||
# the variable name must be obtained from the parse_options
|
||||
# output, which uses shlex.split to strip options out.
|
||||
var,_ = args.split('=', 1)
|
||||
var = var.strip()
|
||||
# But the command has to be extracted from the original input
|
||||
# parameter_s, not on what parse_options returns, to avoid the
|
||||
# quote stripping which shlex.split performs on it.
|
||||
_,cmd = parameter_s.split('=', 1)
|
||||
except ValueError:
|
||||
var,cmd = '',''
|
||||
# If all looks ok, proceed
|
||||
split = 'l' in opts
|
||||
out = self.shell.getoutput(cmd, split=split)
|
||||
if 'v' in opts:
|
||||
print('%s ==\n%s' % (var, pformat(out)))
|
||||
if var:
|
||||
self.shell.user_ns.update({var:out})
|
||||
else:
|
||||
return out
|
||||
|
||||
@line_cell_magic
|
||||
def sx(self, line='', cell=None):
|
||||
"""Shell execute - run shell command and capture output (!! is short-hand).
|
||||
|
||||
%sx command
|
||||
|
||||
IPython will run the given command using commands.getoutput(), and
|
||||
return the result formatted as a list (split on '\\n'). Since the
|
||||
output is _returned_, it will be stored in ipython's regular output
|
||||
cache Out[N] and in the '_N' automatic variables.
|
||||
|
||||
Notes:
|
||||
|
||||
1) If an input line begins with '!!', then %sx is automatically
|
||||
invoked. That is, while::
|
||||
|
||||
!ls
|
||||
|
||||
causes ipython to simply issue system('ls'), typing::
|
||||
|
||||
!!ls
|
||||
|
||||
is a shorthand equivalent to::
|
||||
|
||||
%sx ls
|
||||
|
||||
2) %sx differs from %sc in that %sx automatically splits into a list,
|
||||
like '%sc -l'. The reason for this is to make it as easy as possible
|
||||
to process line-oriented shell output via further python commands.
|
||||
%sc is meant to provide much finer control, but requires more
|
||||
typing.
|
||||
|
||||
3) Just like %sc -l, this is a list with special attributes:
|
||||
::
|
||||
|
||||
.l (or .list) : value as list.
|
||||
.n (or .nlstr): value as newline-separated string.
|
||||
.s (or .spstr): value as whitespace-separated string.
|
||||
|
||||
This is very useful when trying to use such lists as arguments to
|
||||
system commands."""
|
||||
|
||||
if cell is None:
|
||||
# line magic
|
||||
return self.shell.getoutput(line)
|
||||
else:
|
||||
opts,args = self.parse_options(line, '', 'out=')
|
||||
output = self.shell.getoutput(cell)
|
||||
out_name = opts.get('out', opts.get('o'))
|
||||
if out_name:
|
||||
self.shell.user_ns[out_name] = output
|
||||
else:
|
||||
return output
|
||||
|
||||
system = line_cell_magic('system')(sx)
|
||||
bang = cell_magic('!')(sx)
|
||||
|
||||
@line_magic
|
||||
def bookmark(self, parameter_s=''):
|
||||
"""Manage IPython's bookmark system.
|
||||
|
||||
%bookmark <name> - set bookmark to current dir
|
||||
%bookmark <name> <dir> - set bookmark to <dir>
|
||||
%bookmark -l - list all bookmarks
|
||||
%bookmark -d <name> - remove bookmark
|
||||
%bookmark -r - remove all bookmarks
|
||||
|
||||
You can later on access a bookmarked folder with::
|
||||
|
||||
%cd -b <name>
|
||||
|
||||
or simply '%cd <name>' if there is no directory called <name> AND
|
||||
there is such a bookmark defined.
|
||||
|
||||
Your bookmarks persist through IPython sessions, but they are
|
||||
associated with each profile."""
|
||||
|
||||
opts,args = self.parse_options(parameter_s,'drl',mode='list')
|
||||
if len(args) > 2:
|
||||
raise UsageError("%bookmark: too many arguments")
|
||||
|
||||
bkms = self.shell.db.get('bookmarks',{})
|
||||
|
||||
if 'd' in opts:
|
||||
try:
|
||||
todel = args[0]
|
||||
except IndexError:
|
||||
raise UsageError(
|
||||
"%bookmark -d: must provide a bookmark to delete")
|
||||
else:
|
||||
try:
|
||||
del bkms[todel]
|
||||
except KeyError:
|
||||
raise UsageError(
|
||||
"%%bookmark -d: Can't delete bookmark '%s'" % todel)
|
||||
|
||||
elif 'r' in opts:
|
||||
bkms = {}
|
||||
elif 'l' in opts:
|
||||
bks = sorted(bkms)
|
||||
if bks:
|
||||
size = max(map(len, bks))
|
||||
else:
|
||||
size = 0
|
||||
fmt = '%-'+str(size)+'s -> %s'
|
||||
print('Current bookmarks:')
|
||||
for bk in bks:
|
||||
print(fmt % (bk, bkms[bk]))
|
||||
else:
|
||||
if not args:
|
||||
raise UsageError("%bookmark: You must specify the bookmark name")
|
||||
elif len(args)==1:
|
||||
bkms[args[0]] = os.getcwd()
|
||||
elif len(args)==2:
|
||||
bkms[args[0]] = args[1]
|
||||
self.shell.db['bookmarks'] = bkms
|
||||
|
||||
@line_magic
|
||||
def pycat(self, parameter_s=''):
|
||||
"""Show a syntax-highlighted file through a pager.
|
||||
|
||||
This magic is similar to the cat utility, but it will assume the file
|
||||
to be Python source and will show it with syntax highlighting.
|
||||
|
||||
This magic command can either take a local filename, an url,
|
||||
an history range (see %history) or a macro as argument ::
|
||||
|
||||
%pycat myscript.py
|
||||
%pycat 7-27
|
||||
%pycat myMacro
|
||||
%pycat http://www.example.com/myscript.py
|
||||
"""
|
||||
if not parameter_s:
|
||||
raise UsageError('Missing filename, URL, input history range, '
|
||||
'or macro.')
|
||||
|
||||
try :
|
||||
cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
|
||||
except (ValueError, IOError):
|
||||
print("Error: no such file, variable, URL, history range or macro")
|
||||
return
|
||||
|
||||
page.page(self.shell.pycolorize(source_to_unicode(cont)))
|
||||
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument(
|
||||
'-a', '--append', action='store_true', default=False,
|
||||
help='Append contents of the cell to an existing file. '
|
||||
'The file will be created if it does not exist.'
|
||||
)
|
||||
@magic_arguments.argument(
|
||||
'filename', type=str,
|
||||
help='file to write'
|
||||
)
|
||||
@cell_magic
|
||||
def writefile(self, line, cell):
|
||||
"""Write the contents of the cell to a file.
|
||||
|
||||
The file will be overwritten unless the -a (--append) flag is specified.
|
||||
"""
|
||||
args = magic_arguments.parse_argstring(self.writefile, line)
|
||||
if re.match(r'^(\'.*\')|(".*")$', args.filename):
|
||||
filename = os.path.expanduser(args.filename[1:-1])
|
||||
else:
|
||||
filename = os.path.expanduser(args.filename)
|
||||
|
||||
if os.path.exists(filename):
|
||||
if args.append:
|
||||
print("Appending to %s" % filename)
|
||||
else:
|
||||
print("Overwriting %s" % filename)
|
||||
else:
|
||||
print("Writing %s" % filename)
|
||||
|
||||
mode = 'a' if args.append else 'w'
|
||||
with io.open(filename, mode, encoding='utf-8') as f:
|
||||
f.write(cell)
|
103
venv/Lib/site-packages/IPython/core/magics/packaging.py
Normal file
103
venv/Lib/site-packages/IPython/core/magics/packaging.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
"""Implementation of packaging-related magic functions.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2018 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
|
||||
|
||||
def _is_conda_environment():
|
||||
"""Return True if the current Python executable is in a conda env"""
|
||||
# TODO: does this need to change on windows?
|
||||
conda_history = os.path.join(sys.prefix, 'conda-meta', 'history')
|
||||
return os.path.exists(conda_history)
|
||||
|
||||
|
||||
def _get_conda_executable():
|
||||
"""Find the path to the conda executable"""
|
||||
# Check if there is a conda executable in the same directory as the Python executable.
|
||||
# This is the case within conda's root environment.
|
||||
conda = os.path.join(os.path.dirname(sys.executable), 'conda')
|
||||
if os.path.isfile(conda):
|
||||
return conda
|
||||
|
||||
# Otherwise, attempt to extract the executable from conda history.
|
||||
# This applies in any conda environment.
|
||||
R = re.compile(r"^#\s*cmd:\s*(?P<command>.*conda)\s[create|install]")
|
||||
with open(os.path.join(sys.prefix, 'conda-meta', 'history')) as f:
|
||||
for line in f:
|
||||
match = R.match(line)
|
||||
if match:
|
||||
return match.groupdict()['command']
|
||||
|
||||
# Fallback: assume conda is available on the system path.
|
||||
return "conda"
|
||||
|
||||
|
||||
CONDA_COMMANDS_REQUIRING_PREFIX = {
|
||||
'install', 'list', 'remove', 'uninstall', 'update', 'upgrade',
|
||||
}
|
||||
CONDA_COMMANDS_REQUIRING_YES = {
|
||||
'install', 'remove', 'uninstall', 'update', 'upgrade',
|
||||
}
|
||||
CONDA_ENV_FLAGS = {'-p', '--prefix', '-n', '--name'}
|
||||
CONDA_YES_FLAGS = {'-y', '--y'}
|
||||
|
||||
|
||||
@magics_class
|
||||
class PackagingMagics(Magics):
|
||||
"""Magics related to packaging & installation"""
|
||||
|
||||
@line_magic
|
||||
def pip(self, line):
|
||||
"""Run the pip package manager within the current kernel.
|
||||
|
||||
Usage:
|
||||
%pip install [pkgs]
|
||||
"""
|
||||
self.shell.system(' '.join([sys.executable, '-m', 'pip', line]))
|
||||
print("Note: you may need to restart the kernel to use updated packages.")
|
||||
|
||||
@line_magic
|
||||
def conda(self, line):
|
||||
"""Run the conda package manager within the current kernel.
|
||||
|
||||
Usage:
|
||||
%conda install [pkgs]
|
||||
"""
|
||||
if not _is_conda_environment():
|
||||
raise ValueError("The python kernel does not appear to be a conda environment. "
|
||||
"Please use ``%pip install`` instead.")
|
||||
|
||||
conda = _get_conda_executable()
|
||||
args = shlex.split(line)
|
||||
command = args[0]
|
||||
args = args[1:]
|
||||
extra_args = []
|
||||
|
||||
# When the subprocess does not allow us to respond "yes" during the installation,
|
||||
# we need to insert --yes in the argument list for some commands
|
||||
stdin_disabled = getattr(self.shell, 'kernel', None) is not None
|
||||
needs_yes = command in CONDA_COMMANDS_REQUIRING_YES
|
||||
has_yes = set(args).intersection(CONDA_YES_FLAGS)
|
||||
if stdin_disabled and needs_yes and not has_yes:
|
||||
extra_args.append("--yes")
|
||||
|
||||
# Add --prefix to point conda installation to the current environment
|
||||
needs_prefix = command in CONDA_COMMANDS_REQUIRING_PREFIX
|
||||
has_prefix = set(args).intersection(CONDA_ENV_FLAGS)
|
||||
if needs_prefix and not has_prefix:
|
||||
extra_args.extend(["--prefix", sys.prefix])
|
||||
|
||||
self.shell.system(' '.join([conda, command] + extra_args + args))
|
||||
print("\nNote: you may need to restart the kernel to use updated packages.")
|
166
venv/Lib/site-packages/IPython/core/magics/pylab.py
Normal file
166
venv/Lib/site-packages/IPython/core/magics/pylab.py
Normal file
|
@ -0,0 +1,166 @@
|
|||
"""Implementation of magic functions for matplotlib/pylab support.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Our own packages
|
||||
from traitlets.config.application import Application
|
||||
from IPython.core import magic_arguments
|
||||
from IPython.core.magic import Magics, magics_class, line_magic
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
from warnings import warn
|
||||
from IPython.core.pylabtools import backends
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
magic_gui_arg = magic_arguments.argument(
|
||||
'gui', nargs='?',
|
||||
help="""Name of the matplotlib backend to use %s.
|
||||
If given, the corresponding matplotlib backend is used,
|
||||
otherwise it will be matplotlib's default
|
||||
(which you can set in your matplotlib config file).
|
||||
""" % str(tuple(sorted(backends.keys())))
|
||||
)
|
||||
|
||||
|
||||
@magics_class
|
||||
class PylabMagics(Magics):
|
||||
"""Magics related to matplotlib's pylab support"""
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument('-l', '--list', action='store_true',
|
||||
help='Show available matplotlib backends')
|
||||
@magic_gui_arg
|
||||
def matplotlib(self, line=''):
|
||||
"""Set up matplotlib to work interactively.
|
||||
|
||||
This function lets you activate matplotlib interactive support
|
||||
at any point during an IPython session. It does not import anything
|
||||
into the interactive namespace.
|
||||
|
||||
If you are using the inline matplotlib backend in the IPython Notebook
|
||||
you can set which figure formats are enabled using the following::
|
||||
|
||||
In [1]: from IPython.display import set_matplotlib_formats
|
||||
|
||||
In [2]: set_matplotlib_formats('pdf', 'svg')
|
||||
|
||||
The default for inline figures sets `bbox_inches` to 'tight'. This can
|
||||
cause discrepancies between the displayed image and the identical
|
||||
image created using `savefig`. This behavior can be disabled using the
|
||||
`%config` magic::
|
||||
|
||||
In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
|
||||
|
||||
In addition, see the docstring of
|
||||
`IPython.display.set_matplotlib_formats` and
|
||||
`IPython.display.set_matplotlib_close` for more information on
|
||||
changing additional behaviors of the inline backend.
|
||||
|
||||
Examples
|
||||
--------
|
||||
To enable the inline backend for usage with the IPython Notebook::
|
||||
|
||||
In [1]: %matplotlib inline
|
||||
|
||||
In this case, where the matplotlib default is TkAgg::
|
||||
|
||||
In [2]: %matplotlib
|
||||
Using matplotlib backend: TkAgg
|
||||
|
||||
But you can explicitly request a different GUI backend::
|
||||
|
||||
In [3]: %matplotlib qt
|
||||
|
||||
You can list the available backends using the -l/--list option::
|
||||
|
||||
In [4]: %matplotlib --list
|
||||
Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'notebook', 'wx', 'qt', 'nbagg',
|
||||
'gtk', 'tk', 'inline']
|
||||
"""
|
||||
args = magic_arguments.parse_argstring(self.matplotlib, line)
|
||||
if args.list:
|
||||
backends_list = list(backends.keys())
|
||||
print("Available matplotlib backends: %s" % backends_list)
|
||||
else:
|
||||
gui, backend = self.shell.enable_matplotlib(args.gui.lower() if isinstance(args.gui, str) else args.gui)
|
||||
self._show_matplotlib_backend(args.gui, backend)
|
||||
|
||||
@skip_doctest
|
||||
@line_magic
|
||||
@magic_arguments.magic_arguments()
|
||||
@magic_arguments.argument(
|
||||
'--no-import-all', action='store_true', default=None,
|
||||
help="""Prevent IPython from performing ``import *`` into the interactive namespace.
|
||||
|
||||
You can govern the default behavior of this flag with the
|
||||
InteractiveShellApp.pylab_import_all configurable.
|
||||
"""
|
||||
)
|
||||
@magic_gui_arg
|
||||
def pylab(self, line=''):
|
||||
"""Load numpy and matplotlib to work interactively.
|
||||
|
||||
This function lets you activate pylab (matplotlib, numpy and
|
||||
interactive support) at any point during an IPython session.
|
||||
|
||||
%pylab makes the following imports::
|
||||
|
||||
import numpy
|
||||
import matplotlib
|
||||
from matplotlib import pylab, mlab, pyplot
|
||||
np = numpy
|
||||
plt = pyplot
|
||||
|
||||
from IPython.display import display
|
||||
from IPython.core.pylabtools import figsize, getfigs
|
||||
|
||||
from pylab import *
|
||||
from numpy import *
|
||||
|
||||
If you pass `--no-import-all`, the last two `*` imports will be excluded.
|
||||
|
||||
See the %matplotlib magic for more details about activating matplotlib
|
||||
without affecting the interactive namespace.
|
||||
"""
|
||||
args = magic_arguments.parse_argstring(self.pylab, line)
|
||||
if args.no_import_all is None:
|
||||
# get default from Application
|
||||
if Application.initialized():
|
||||
app = Application.instance()
|
||||
try:
|
||||
import_all = app.pylab_import_all
|
||||
except AttributeError:
|
||||
import_all = True
|
||||
else:
|
||||
# nothing specified, no app - default True
|
||||
import_all = True
|
||||
else:
|
||||
# invert no-import flag
|
||||
import_all = not args.no_import_all
|
||||
|
||||
gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all)
|
||||
self._show_matplotlib_backend(args.gui, backend)
|
||||
print ("Populating the interactive namespace from numpy and matplotlib")
|
||||
if clobbered:
|
||||
warn("pylab import has clobbered these variables: %s" % clobbered +
|
||||
"\n`%matplotlib` prevents importing * from pylab and numpy"
|
||||
)
|
||||
|
||||
def _show_matplotlib_backend(self, gui, backend):
|
||||
"""show matplotlib message backend message"""
|
||||
if not gui or gui == 'auto':
|
||||
print("Using matplotlib backend: %s" % backend)
|
294
venv/Lib/site-packages/IPython/core/magics/script.py
Normal file
294
venv/Lib/site-packages/IPython/core/magics/script.py
Normal file
|
@ -0,0 +1,294 @@
|
|||
"""Magic functions for running cells in various scripts."""
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import time
|
||||
from subprocess import Popen, PIPE, CalledProcessError
|
||||
import atexit
|
||||
|
||||
from IPython.core import magic_arguments
|
||||
from IPython.core.magic import (
|
||||
Magics, magics_class, line_magic, cell_magic
|
||||
)
|
||||
from IPython.lib.backgroundjobs import BackgroundJobManager
|
||||
from IPython.utils import py3compat
|
||||
from IPython.utils.process import arg_split
|
||||
from traitlets import List, Dict, default
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Magic implementation classes
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def script_args(f):
|
||||
"""single decorator for adding script args"""
|
||||
args = [
|
||||
magic_arguments.argument(
|
||||
'--out', type=str,
|
||||
help="""The variable in which to store stdout from the script.
|
||||
If the script is backgrounded, this will be the stdout *pipe*,
|
||||
instead of the stderr text itself and will not be auto closed.
|
||||
"""
|
||||
),
|
||||
magic_arguments.argument(
|
||||
'--err', type=str,
|
||||
help="""The variable in which to store stderr from the script.
|
||||
If the script is backgrounded, this will be the stderr *pipe*,
|
||||
instead of the stderr text itself and will not be autoclosed.
|
||||
"""
|
||||
),
|
||||
magic_arguments.argument(
|
||||
'--bg', action="store_true",
|
||||
help="""Whether to run the script in the background.
|
||||
If given, the only way to see the output of the command is
|
||||
with --out/err.
|
||||
"""
|
||||
),
|
||||
magic_arguments.argument(
|
||||
'--proc', type=str,
|
||||
help="""The variable in which to store Popen instance.
|
||||
This is used only when --bg option is given.
|
||||
"""
|
||||
),
|
||||
magic_arguments.argument(
|
||||
'--no-raise-error', action="store_false", dest='raise_error',
|
||||
help="""Whether you should raise an error message in addition to
|
||||
a stream on stderr if you get a nonzero exit code.
|
||||
"""
|
||||
)
|
||||
]
|
||||
for arg in args:
|
||||
f = arg(f)
|
||||
return f
|
||||
|
||||
@magics_class
|
||||
class ScriptMagics(Magics):
|
||||
"""Magics for talking to scripts
|
||||
|
||||
This defines a base `%%script` cell magic for running a cell
|
||||
with a program in a subprocess, and registers a few top-level
|
||||
magics that call %%script with common interpreters.
|
||||
"""
|
||||
script_magics = List(
|
||||
help="""Extra script cell magics to define
|
||||
|
||||
This generates simple wrappers of `%%script foo` as `%%foo`.
|
||||
|
||||
If you want to add script magics that aren't on your path,
|
||||
specify them in script_paths
|
||||
""",
|
||||
).tag(config=True)
|
||||
@default('script_magics')
|
||||
def _script_magics_default(self):
|
||||
"""default to a common list of programs"""
|
||||
|
||||
defaults = [
|
||||
'sh',
|
||||
'bash',
|
||||
'perl',
|
||||
'ruby',
|
||||
'python',
|
||||
'python2',
|
||||
'python3',
|
||||
'pypy',
|
||||
]
|
||||
if os.name == 'nt':
|
||||
defaults.extend([
|
||||
'cmd',
|
||||
])
|
||||
|
||||
return defaults
|
||||
|
||||
script_paths = Dict(
|
||||
help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
|
||||
|
||||
Only necessary for items in script_magics where the default path will not
|
||||
find the right interpreter.
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
def __init__(self, shell=None):
|
||||
super(ScriptMagics, self).__init__(shell=shell)
|
||||
self._generate_script_magics()
|
||||
self.job_manager = BackgroundJobManager()
|
||||
self.bg_processes = []
|
||||
atexit.register(self.kill_bg_processes)
|
||||
|
||||
def __del__(self):
|
||||
self.kill_bg_processes()
|
||||
|
||||
def _generate_script_magics(self):
|
||||
cell_magics = self.magics['cell']
|
||||
for name in self.script_magics:
|
||||
cell_magics[name] = self._make_script_magic(name)
|
||||
|
||||
def _make_script_magic(self, name):
|
||||
"""make a named magic, that calls %%script with a particular program"""
|
||||
# expand to explicit path if necessary:
|
||||
script = self.script_paths.get(name, name)
|
||||
|
||||
@magic_arguments.magic_arguments()
|
||||
@script_args
|
||||
def named_script_magic(line, cell):
|
||||
# if line, add it as cl-flags
|
||||
if line:
|
||||
line = "%s %s" % (script, line)
|
||||
else:
|
||||
line = script
|
||||
return self.shebang(line, cell)
|
||||
|
||||
# write a basic docstring:
|
||||
named_script_magic.__doc__ = \
|
||||
"""%%{name} script magic
|
||||
|
||||
Run cells with {script} in a subprocess.
|
||||
|
||||
This is a shortcut for `%%script {script}`
|
||||
""".format(**locals())
|
||||
|
||||
return named_script_magic
|
||||
|
||||
@magic_arguments.magic_arguments()
|
||||
@script_args
|
||||
@cell_magic("script")
|
||||
def shebang(self, line, cell):
|
||||
"""Run a cell via a shell command
|
||||
|
||||
The `%%script` line is like the #! line of script,
|
||||
specifying a program (bash, perl, ruby, etc.) with which to run.
|
||||
|
||||
The rest of the cell is run by that program.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
In [1]: %%script bash
|
||||
...: for i in 1 2 3; do
|
||||
...: echo $i
|
||||
...: done
|
||||
1
|
||||
2
|
||||
3
|
||||
"""
|
||||
argv = arg_split(line, posix = not sys.platform.startswith('win'))
|
||||
args, cmd = self.shebang.parser.parse_known_args(argv)
|
||||
|
||||
try:
|
||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
print("Couldn't find program: %r" % cmd[0])
|
||||
return
|
||||
else:
|
||||
raise
|
||||
|
||||
if not cell.endswith('\n'):
|
||||
cell += '\n'
|
||||
cell = cell.encode('utf8', 'replace')
|
||||
if args.bg:
|
||||
self.bg_processes.append(p)
|
||||
self._gc_bg_processes()
|
||||
to_close = []
|
||||
if args.out:
|
||||
self.shell.user_ns[args.out] = p.stdout
|
||||
else:
|
||||
to_close.append(p.stdout)
|
||||
if args.err:
|
||||
self.shell.user_ns[args.err] = p.stderr
|
||||
else:
|
||||
to_close.append(p.stderr)
|
||||
self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
|
||||
if args.proc:
|
||||
self.shell.user_ns[args.proc] = p
|
||||
return
|
||||
|
||||
try:
|
||||
out, err = p.communicate(cell)
|
||||
except KeyboardInterrupt:
|
||||
try:
|
||||
p.send_signal(signal.SIGINT)
|
||||
time.sleep(0.1)
|
||||
if p.poll() is not None:
|
||||
print("Process is interrupted.")
|
||||
return
|
||||
p.terminate()
|
||||
time.sleep(0.1)
|
||||
if p.poll() is not None:
|
||||
print("Process is terminated.")
|
||||
return
|
||||
p.kill()
|
||||
print("Process is killed.")
|
||||
except OSError:
|
||||
pass
|
||||
except Exception as e:
|
||||
print("Error while terminating subprocess (pid=%i): %s" \
|
||||
% (p.pid, e))
|
||||
return
|
||||
out = py3compat.decode(out)
|
||||
err = py3compat.decode(err)
|
||||
if args.out:
|
||||
self.shell.user_ns[args.out] = out
|
||||
else:
|
||||
sys.stdout.write(out)
|
||||
sys.stdout.flush()
|
||||
if args.err:
|
||||
self.shell.user_ns[args.err] = err
|
||||
else:
|
||||
sys.stderr.write(err)
|
||||
sys.stderr.flush()
|
||||
if args.raise_error and p.returncode!=0:
|
||||
raise CalledProcessError(p.returncode, cell, output=out, stderr=err)
|
||||
|
||||
def _run_script(self, p, cell, to_close):
|
||||
"""callback for running the script in the background"""
|
||||
p.stdin.write(cell)
|
||||
p.stdin.close()
|
||||
for s in to_close:
|
||||
s.close()
|
||||
p.wait()
|
||||
|
||||
@line_magic("killbgscripts")
|
||||
def killbgscripts(self, _nouse_=''):
|
||||
"""Kill all BG processes started by %%script and its family."""
|
||||
self.kill_bg_processes()
|
||||
print("All background processes were killed.")
|
||||
|
||||
def kill_bg_processes(self):
|
||||
"""Kill all BG processes which are still running."""
|
||||
if not self.bg_processes:
|
||||
return
|
||||
for p in self.bg_processes:
|
||||
if p.poll() is None:
|
||||
try:
|
||||
p.send_signal(signal.SIGINT)
|
||||
except:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
self._gc_bg_processes()
|
||||
if not self.bg_processes:
|
||||
return
|
||||
for p in self.bg_processes:
|
||||
if p.poll() is None:
|
||||
try:
|
||||
p.terminate()
|
||||
except:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
self._gc_bg_processes()
|
||||
if not self.bg_processes:
|
||||
return
|
||||
for p in self.bg_processes:
|
||||
if p.poll() is None:
|
||||
try:
|
||||
p.kill()
|
||||
except:
|
||||
pass
|
||||
self._gc_bg_processes()
|
||||
|
||||
def _gc_bg_processes(self):
|
||||
self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
|
Loading…
Add table
Add a link
Reference in a new issue