diff options
author | Mikhail Borisov <borisov.mikhail@gmail.com> | 2022-02-10 16:45:40 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:40 +0300 |
commit | 5d50718e66d9c037dc587a0211110b7d25a66185 (patch) | |
tree | e98df59de24d2ef7c77baed9f41e4875a2fef972 /contrib/python/ipython/py2/IPython/core/magics | |
parent | a6a92afe03e02795227d2641b49819b687f088f8 (diff) | |
download | ydb-5d50718e66d9c037dc587a0211110b7d25a66185.tar.gz |
Restoring authorship annotation for Mikhail Borisov <borisov.mikhail@gmail.com>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/ipython/py2/IPython/core/magics')
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/__init__.py | 82 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/auto.py | 256 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/basic.py | 1094 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/code.py | 1420 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/config.py | 314 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/display.py | 98 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/execution.py | 2616 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/extension.py | 134 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/history.py | 636 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/logging.py | 366 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/namespace.py | 1408 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/osm.py | 1572 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/pylab.py | 332 | ||||
-rw-r--r-- | contrib/python/ipython/py2/IPython/core/magics/script.py | 528 |
14 files changed, 5428 insertions, 5428 deletions
diff --git a/contrib/python/ipython/py2/IPython/core/magics/__init__.py b/contrib/python/ipython/py2/IPython/core/magics/__init__.py index 78d4a45aa0..d2fd5a6cfb 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/__init__.py +++ b/contrib/python/ipython/py2/IPython/core/magics/__init__.py @@ -1,41 +1,41 @@ -"""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 -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 .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. - """ +"""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 +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 .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. + """ diff --git a/contrib/python/ipython/py2/IPython/core/magics/auto.py b/contrib/python/ipython/py2/IPython/core/magics/auto.py index be6b218854..f87bafdeb1 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/auto.py +++ b/contrib/python/ipython/py2/IPython/core/magics/auto.py @@ -1,130 +1,130 @@ -"""Implementation of magic functions that control various automatic behaviors. -""" -from __future__ import print_function +"""Implementation of magic functions that control various automatic behaviors. +""" +from __future__ import print_function from __future__ import absolute_import -#----------------------------------------------------------------------------- -# 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 +#----------------------------------------------------------------------------- +# 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 argumentsl 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]) + +#----------------------------------------------------------------------------- +# 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 argumentsl 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]) diff --git a/contrib/python/ipython/py2/IPython/core/magics/basic.py b/contrib/python/ipython/py2/IPython/core/magics/basic.py index 75b1275211..ca69e2e698 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/basic.py +++ b/contrib/python/ipython/py2/IPython/core/magics/basic.py @@ -1,575 +1,575 @@ -"""Implementation of basic magic functions.""" - -from __future__ import print_function +"""Implementation of basic magic functions.""" + +from __future__ import print_function from __future__ import absolute_import - + import argparse -import io -import sys -from pprint import pformat - -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 -from IPython.utils.py3compat import unicode_type +import io +import sys +from pprint import pformat + +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 +from IPython.utils.py3compat import unicode_type from warnings import warn from logging import error - - -class MagicsDisplay(object): - def __init__(self, magics_manager): - 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(magics['line'])), - '', - 'Available cell magics:', - cesc + (' '+cesc).join(sorted(magics['cell'])), - '', - 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.""" - ) - @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' - """ - 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) - - # 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) - - if args.line: - mman.register_alias(name, target, 'line') - print('Created `%s%s` as an alias for `%s%s`.' % ( - magic_escapes['line'], name, - magic_escapes['line'], target)) - - if args.cell: - mman.register_alias(name, target, 'cell') - print('Created `%s%s` as an alias for `%s%s`.' % ( - magic_escapes['cell'], name, - magic_escapes['cell'], target)) - - @line_magic - def lsmagic(self, parameter_s=''): - """List currently available magic functions.""" - return MagicsDisplay(self.shell.magics_manager) - - 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 profile(self, parameter_s=''): + + +class MagicsDisplay(object): + def __init__(self, magics_manager): + 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(magics['line'])), + '', + 'Available cell magics:', + cesc + (' '+cesc).join(sorted(magics['cell'])), + '', + 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.""" + ) + @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' + """ + 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) + + # 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) + + if args.line: + mman.register_alias(name, target, 'line') + print('Created `%s%s` as an alias for `%s%s`.' % ( + magic_escapes['line'], name, + magic_escapes['line'], target)) + + if args.cell: + mman.register_alias(name, target, 'cell') + print('Created `%s%s` as an alias for `%s%s`.' % ( + magic_escapes['cell'], name, + magic_escapes['cell'], target)) + + @line_magic + def lsmagic(self, parameter_s=''): + """List currently available magic functions.""" + return MagicsDisplay(self.shell.magics_manager) + + 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 profile(self, parameter_s=''): """DEPRECATED since IPython 2.0. - + Raise `UsageError`. To profile code use the :magic:`prun` magic. - See Also - -------- + See Also + -------- prun : run code using the Python profiler (:magic:`prun`) - """ - warn("%profile is now deprecated. Please use get_ipython().profile instead.") - from IPython.core.application import BaseIPythonApplication - if BaseIPythonApplication.initialized(): - print(BaseIPythonApplication.instance().profile) - else: - error("profile is an application-level value, but you don't appear to be in an IPython application") - - @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' % + """ + warn("%profile is now deprecated. Please use get_ipython().profile instead.") + from IPython.core.application import BaseIPythonApplication + if BaseIPythonApplication.initialized(): + print(BaseIPythonApplication.instance().profile) + else: + error("profile is an application-level value, but you don't appear to be in an IPython application") + + @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 - + + + 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: + try: shell.colors = new_scheme shell.refresh_style() - except: + 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 and Verbose. - - If called without arguments, acts as a toggle.""" - - def xmode_switch_err(name): - warn('Error changing %s exception modes.\n%s' % - (name,sys.exc_info()[1])) - - shell = self.shell - 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) - + # 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 and Verbose. + + If called without arguments, acts as a toggle.""" + + def xmode_switch_err(name): + warn('Error changing %s exception modes.\n%s' % + (name,sys.exc_info()[1])) + + shell = self.shell + 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 + # 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, + 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=unicode_type, - 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. + ) + @magic_arguments.argument( + 'filename', type=unicode_type, + 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 + """ + args = magic_arguments.parse_argstring(self.notebook, s) + + from nbformat import write, v4 cells = [] hist = list(self.shell.history_manager.get_range()) diff --git a/contrib/python/ipython/py2/IPython/core/magics/code.py b/contrib/python/ipython/py2/IPython/core/magics/code.py index 4f17cda0c0..4c1a40f197 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/code.py +++ b/contrib/python/ipython/py2/IPython/core/magics/code.py @@ -1,146 +1,146 @@ -"""Implementation of code management magic functions. -""" -from __future__ import print_function +"""Implementation of code management magic functions. +""" +from __future__ import print_function from __future__ import absolute_import -#----------------------------------------------------------------------------- -# 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 - -# 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 import py3compat -from IPython.utils.py3compat import string_types -from IPython.utils.contexts import preserve_keys +#----------------------------------------------------------------------------- +# 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 + +# 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 import py3compat +from IPython.utils.py3compat import string_types +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 splitted 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) - - -@skip_doctest -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:: - - >>> code = '''a = 10 - - def b(): return 42 - - class A: pass''' - - >>> extract_symbols(code, 'A,b,z') - (["class A: pass", "def b(): return 42"], ['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 - +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 splitted 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) + + +@skip_doctest +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:: + + >>> code = '''a = 10 + + def b(): return 42 + + class A: pass''' + + >>> extract_symbols(code, 'A,b,z') + (["class A: pass", "def b(): return 42"], ['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+') @@ -169,578 +169,578 @@ def strip_initial_indent(lines): 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 = u'.ipy' if raw else u'.py' +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 = u'.ipy' if raw else u'.py' fname, codefrom = args[0], " ".join(args[1:]) - if not fname.endswith((u'.py',u'.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 - out = py3compat.cast_unicode(cmds) - with io.open(fname, mode, encoding="utf-8") as f: - if not file_exists or not append: - f.write(u"# coding: utf-8\n") - f.write(out) - # make sure we end on a newline - if not out.endswith(u'\n'): - f.write(u'\n') - print('The following commands were written to file `%s`:' % fname) - print(cmds) - - @line_magic - def pastebin(self, parameter_s=''): - """Upload code to Github's Gist 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 - - # Deferred import - try: - from urllib.request import urlopen # Py 3 - except ImportError: - from urllib2 import urlopen - import json - post_data = json.dumps({ - "description": opts.get('d', "Pasted from IPython"), - "public": True, - "files": { - "file1.py": { - "content": code - } - } - }).encode('utf-8') - - response = urlopen("https://api.github.com/gists", post_data) - response_data = json.loads(response.read().decode('utf-8')) - return response_data['html_url'] - - @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] + if not fname.endswith((u'.py',u'.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 + out = py3compat.cast_unicode(cmds) + with io.open(fname, mode, encoding="utf-8") as f: + if not file_exists or not append: + f.write(u"# coding: utf-8\n") + f.write(out) + # make sure we end on a newline + if not out.endswith(u'\n'): + f.write(u'\n') + print('The following commands were written to file `%s`:' % fname) + print(cmds) + + @line_magic + def pastebin(self, parameter_s=''): + """Upload code to Github's Gist 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 + + # Deferred import + try: + from urllib.request import urlopen # Py 3 + except ImportError: + from urllib2 import urlopen + import json + post_data = json.dumps({ + "description": opts.get('d', "Pasted from IPython"), + "public": True, + "files": { + "file1.py": { + "content": code + } + } + }).encode('utf-8') + + response = urlopen("https://api.github.com/gists", post_data) + response_data = json.loads(response.read().decode('utf-8')) + return response_data['html_url'] + + @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 caracter 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: - #asume 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, string_types): - 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: - return open(filename).read() - except IOError as msg: - if msg.filename == filename: - warn('File not found. Did you forget to save?') - return - else: - self.shell.showtraceback() + + l = len(contents) + + # 200 000 is ~ 2500 full 80 caracter 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: + #asume 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, string_types): + 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: + return open(filename).read() + except IOError as msg: + if msg.filename == filename: + warn('File not found. Did you forget to save?') + return + else: + self.shell.showtraceback() diff --git a/contrib/python/ipython/py2/IPython/core/magics/config.py b/contrib/python/ipython/py2/IPython/core/magics/config.py index f023cf9267..9505697791 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/config.py +++ b/contrib/python/ipython/py2/IPython/core/magics/config.py @@ -1,159 +1,159 @@ -"""Implementation of configuration-related magic functions. -""" -from __future__ import print_function +"""Implementation of configuration-related magic functions. +""" +from __future__ import print_function from __future__ import absolute_import -#----------------------------------------------------------------------------- -# 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 +#----------------------------------------------------------------------------- +# 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('^\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 = [ c for c in self.shell.configurables - if c.__class__.class_traits(config=True) ] - 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) + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + +reg = re.compile('^\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 = [ c for c in self.shell.configurables + if c.__class__.class_traits(config=True) ] + 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) diff --git a/contrib/python/ipython/py2/IPython/core/magics/display.py b/contrib/python/ipython/py2/IPython/core/magics/display.py index 156a86b10a..c4a8f44d9a 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/display.py +++ b/contrib/python/ipython/py2/IPython/core/magics/display.py @@ -1,36 +1,36 @@ -"""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 -from IPython.core.magic import ( - Magics, magics_class, cell_magic -) - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - - -@magics_class -class DisplayMagics(Magics): - """Magics for displaying various output types with literals +"""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 +from IPython.core.magic import ( + Magics, magics_class, cell_magic +) + +#----------------------------------------------------------------------------- +# 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. - """ + blocks in those languages, to be rendered in the frontend. + """ - @cell_magic + @cell_magic def js(self, line, cell): """Run the cell block of Javascript code @@ -39,27 +39,27 @@ class DisplayMagics(Magics): self.javascript(line, cell) @cell_magic - def javascript(self, line, cell): - """Run the cell block of Javascript code""" - display(Javascript(cell)) + 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 + @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 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)) - - @cell_magic - def html(self, line, cell): - """Render the cell as a block of HTML""" - display(HTML(cell)) + [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)) + + @cell_magic + def html(self, line, cell): + """Render the cell as a block of HTML""" + display(HTML(cell)) diff --git a/contrib/python/ipython/py2/IPython/core/magics/execution.py b/contrib/python/ipython/py2/IPython/core/magics/execution.py index a10c3409bc..3734b0cdae 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/execution.py +++ b/contrib/python/ipython/py2/IPython/core/magics/execution.py @@ -1,710 +1,710 @@ -# -*- coding: utf-8 -*- -"""Implementation of execution-related magic functions.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from __future__ import print_function +# -*- coding: utf-8 -*- +"""Implementation of execution-related magic functions.""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +from __future__ import print_function from __future__ import absolute_import - -import ast -import bdb -import gc -import itertools -import os -import sys -import time -import timeit -from pdb import Restart - -# cProfile was added in Python2.5 -try: - import cProfile as profile - import pstats -except ImportError: - # profile isn't bundled by default in Debian for license reasons - try: - import profile, pstats - except ImportError: - profile = pstats = None - + +import ast +import bdb +import gc +import itertools +import os +import sys +import time +import timeit +from pdb import Restart + +# cProfile was added in Python2.5 +try: + import cProfile as profile + import pstats +except ImportError: + # profile isn't bundled by default in Debian for license reasons + try: + import profile, pstats + except ImportError: + profile = pstats = None + from IPython.core import oinspect -from IPython.core import magic_arguments -from IPython.core import page -from IPython.core.error import UsageError -from IPython.core.macro import Macro -from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic, - line_cell_magic, on_off, needs_local_scope) -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils import py3compat -from IPython.utils.py3compat import builtin_mod, iteritems, PY3 -from IPython.utils.contexts import preserve_keys -from IPython.utils.capture import capture_output -from IPython.utils.ipstruct import Struct -from IPython.utils.module_paths import find_mod +from IPython.core import magic_arguments +from IPython.core import page +from IPython.core.error import UsageError +from IPython.core.macro import Macro +from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic, + line_cell_magic, on_off, needs_local_scope) +from IPython.testing.skipdoctest import skip_doctest +from IPython.utils import py3compat +from IPython.utils.py3compat import builtin_mod, iteritems, PY3 +from IPython.utils.contexts import preserve_keys +from IPython.utils.capture import capture_output +from IPython.utils.ipstruct import Struct +from IPython.utils.module_paths import find_mod from IPython.utils.path import get_py_filename, shellglob -from IPython.utils.timing import clock, clock2 +from IPython.utils.timing import clock, clock2 from warnings import warn from logging import error - -if PY3: - from io import StringIO -else: - from StringIO import StringIO - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - - -class TimeitResult(object): - """ - Object returned by the timeit magic with info about the run. - + +if PY3: + from io import StringIO +else: + from StringIO import StringIO + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + + +class TimeitResult(object): + """ + Object returned by the timeit magic with info about the run. + Contains the following attributes : - + loops: (int) number of loops done per measurement repeat: (int) number of times the measurement has been repeated best: (float) best execution time / number all_runs: (list of float) execution time of each run (in s) - compile_time: (float) time of statement compilation (s) - - """ - - def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision): - self.loops = loops - self.repeat = repeat - self.best = best - self.worst = worst - self.all_runs = all_runs - self.compile_time = compile_time - self._precision = precision - - def _repr_pretty_(self, p , cycle): - if self.loops == 1: # No s at "loops" if only one loop - unic = u"%d loop, best of %d: %s per loop" % (self.loops, self.repeat, - _format_time(self.best, self._precision)) - else: - unic = u"%d loops, best of %d: %s per loop" % (self.loops, self.repeat, - _format_time(self.best, self._precision)) - p.text(u'<TimeitResult : '+unic+u'>') - - -class TimeitTemplateFiller(ast.NodeTransformer): - """Fill in the AST template for timing execution. - - This is quite closely tied to the template definition, which is in - :meth:`ExecutionMagics.timeit`. - """ - def __init__(self, ast_setup, ast_stmt): - self.ast_setup = ast_setup - self.ast_stmt = ast_stmt - - def visit_FunctionDef(self, node): - "Fill in the setup statement" - self.generic_visit(node) - if node.name == "inner": - node.body[:1] = self.ast_setup.body - - return node - - def visit_For(self, node): - "Fill in the statement to be timed" - if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt': - node.body = self.ast_stmt.body - return node - - -class Timer(timeit.Timer): - """Timer class that explicitly uses self.inner - - which is an undocumented implementation detail of CPython, - not shared by PyPy. - """ - # Timer.timeit copied from CPython 3.4.2 - def timeit(self, number=timeit.default_number): - """Time 'number' executions of the main statement. - - To be precise, this executes the setup statement once, and - then returns the time it takes to execute the main statement - a number of times, as a float measured in seconds. The - argument is the number of times through the loop, defaulting - to one million. The main statement, the setup statement and - the timer function to be used are passed to the constructor. - """ - it = itertools.repeat(None, number) - gcold = gc.isenabled() - gc.disable() - try: - timing = self.inner(it, self.timer) - finally: - if gcold: - gc.enable() - return timing - - -@magics_class -class ExecutionMagics(Magics): - """Magics related to code execution, debugging, profiling, etc. - - """ - - def __init__(self, shell): - super(ExecutionMagics, self).__init__(shell) - if profile is None: - self.prun = self.profile_missing_notice - # Default execution function used to actually run user code. - self.default_runner = None - - def profile_missing_notice(self, *args, **kwargs): - error("""\ -The profile module could not be found. It has been removed from the standard -python packages because of its non-free license. To use profiling, install the -python-profiler package from non-free.""") - - @skip_doctest - @line_cell_magic - def prun(self, parameter_s='', cell=None): - - """Run a statement through the python code profiler. - - Usage, in line mode: - %prun [options] statement - - Usage, in cell mode: - %%prun [options] [statement] - code... - code... - - In cell mode, the additional code lines are appended to the (possibly - empty) statement in the first line. Cell mode allows you to easily - profile multiline blocks without having to put them in a separate - function. - - The given statement (which doesn't require quote marks) is run via the - python profiler in a manner similar to the profile.run() function. - Namespaces are internally managed to work correctly; profile.run - cannot be used in IPython because it makes certain assumptions about - namespaces which do not hold under IPython. - - Options: - - -l <limit> - you can place restrictions on what or how much of the - profile gets printed. The limit value can be: - - * A string: only information for function names containing this string - is printed. - - * An integer: only these many lines are printed. - - * A float (between 0 and 1): this fraction of the report is printed - (for example, use a limit of 0.4 to see the topmost 40% only). - - You can combine several limits with repeated use of the option. For - example, ``-l __init__ -l 5`` will print only the topmost 5 lines of - information about class constructors. - - -r - return the pstats.Stats object generated by the profiling. This - object has all the information about the profile in it, and you can - later use it for further analysis or in other functions. - - -s <key> - sort profile by given key. You can provide more than one key - by using the option several times: '-s key1 -s key2 -s key3...'. The - default sorting key is 'time'. - - The following is copied verbatim from the profile documentation - referenced below: - - When more than one key is provided, additional keys are used as - secondary criteria when the there is equality in all keys selected - before them. - - Abbreviations can be used for any key names, as long as the - abbreviation is unambiguous. The following are the keys currently - defined: - - ============ ===================== - Valid Arg Meaning - ============ ===================== - "calls" call count - "cumulative" cumulative time - "file" file name - "module" file name - "pcalls" primitive call count - "line" line number - "name" function name - "nfl" name/file/line - "stdname" standard name - "time" internal time - ============ ===================== - - Note that all sorts on statistics are in descending order (placing - most time consuming items first), where as name, file, and line number - searches are in ascending order (i.e., alphabetical). The subtle - distinction between "nfl" and "stdname" is that the standard name is a - sort of the name as printed, which means that the embedded line - numbers get compared in an odd way. For example, lines 3, 20, and 40 - would (if the file names were the same) appear in the string order - "20" "3" and "40". In contrast, "nfl" does a numeric compare of the - line numbers. In fact, sort_stats("nfl") is the same as - sort_stats("name", "file", "line"). - - -T <filename> - save profile results as shown on screen to a text - file. The profile is still shown on screen. - - -D <filename> - save (via dump_stats) profile statistics to given - filename. This data is in a format understood by the pstats module, and - is generated by a call to the dump_stats() method of profile - objects. The profile is still shown on screen. - - -q - suppress output to the pager. Best used with -T and/or -D above. - - If you want to run complete programs under the profiler's control, use - ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts - contains profiler specific options as described here. - - You can read the complete documentation for the profile module with:: - - In [1]: import profile; profile.help() - """ - opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q', - list_all=True, posix=False) - if cell is not None: - arg_str += '\n' + cell - arg_str = self.shell.input_splitter.transform_cell(arg_str) - return self._run_with_profiler(arg_str, opts, self.shell.user_ns) - - def _run_with_profiler(self, code, opts, namespace): - """ - Run `code` with profiler. Used by ``%prun`` and ``%run -p``. - - Parameters - ---------- - code : str - Code to be executed. - opts : Struct - Options parsed by `self.parse_options`. - namespace : dict - A dictionary for Python namespace (e.g., `self.shell.user_ns`). - - """ - - # Fill default values for unspecified options: - opts.merge(Struct(D=[''], l=[], s=['time'], T=[''])) - - prof = profile.Profile() - try: - prof = prof.runctx(code, namespace, namespace) - sys_exit = '' - except SystemExit: - sys_exit = """*** SystemExit exception caught in code being profiled.""" - - stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s) - - lims = opts.l - if lims: - lims = [] # rebuild lims with ints/floats/strings - for lim in opts.l: - try: - lims.append(int(lim)) - except ValueError: - try: - lims.append(float(lim)) - except ValueError: - lims.append(lim) - - # Trap output. - stdout_trap = StringIO() - stats_stream = stats.stream - try: - stats.stream = stdout_trap - stats.print_stats(*lims) - finally: - stats.stream = stats_stream - - output = stdout_trap.getvalue() - output = output.rstrip() - - if 'q' not in opts: - page.page(output) - print(sys_exit, end=' ') - - dump_file = opts.D[0] - text_file = opts.T[0] - if dump_file: - prof.dump_stats(dump_file) - print('\n*** Profile stats marshalled to file',\ - repr(dump_file)+'.',sys_exit) - if text_file: - pfile = open(text_file,'w') - pfile.write(output) - pfile.close() - print('\n*** Profile printout saved to text file',\ - repr(text_file)+'.',sys_exit) - - if 'r' in opts: - return stats - else: - return None - - @line_magic - def pdb(self, parameter_s=''): - """Control the automatic calling of the pdb interactive debugger. - - Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without - argument it works as a toggle. - - When an exception is triggered, IPython can optionally call the - interactive pdb debugger after the traceback printout. %pdb toggles - this feature on and off. - - The initial state of this feature is set in your configuration - file (the option is ``InteractiveShell.pdb``). - - If you want to just activate the debugger AFTER an exception has fired, - without having to type '%pdb on' and rerunning your code, you can use - the %debug magic.""" - - par = parameter_s.strip().lower() - - if par: - try: - new_pdb = {'off':0,'0':0,'on':1,'1':1}[par] - except KeyError: - print ('Incorrect argument. Use on/1, off/0, ' - 'or nothing for a toggle.') - return - else: - # toggle - new_pdb = not self.shell.call_pdb - - # set on the shell - self.shell.call_pdb = new_pdb - print('Automatic pdb calling has been turned',on_off(new_pdb)) - - @skip_doctest - @magic_arguments.magic_arguments() - @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE', - help=""" - Set break point at LINE in FILE. - """ - ) - @magic_arguments.argument('statement', nargs='*', - help=""" - Code to run in debugger. - You can omit this in cell magic mode. - """ - ) - @line_cell_magic - def debug(self, line='', cell=None): - """Activate the interactive debugger. - - This magic command support two ways of activating debugger. - One is to activate debugger before executing code. This way, you - can set a break point, to step through the code from the point. - You can use this mode by giving statements to execute and optionally - a breakpoint. - - The other one is to activate debugger in post-mortem mode. You can - activate this mode simply running %debug without any argument. - If an exception has just occurred, this lets you inspect its stack - frames interactively. Note that this will always work only on the last - traceback that occurred, so you must call this quickly after an - exception that you wish to inspect has fired, because if another one - occurs, it clobbers the previous one. - - If you want IPython to automatically do this on every exception, see - the %pdb magic for more details. - """ - args = magic_arguments.parse_argstring(self.debug, line) - - if not (args.breakpoint or args.statement or cell): - self._debug_post_mortem() - else: - code = "\n".join(args.statement) - if cell: - code += "\n" + cell - self._debug_exec(code, args.breakpoint) - - def _debug_post_mortem(self): - self.shell.debugger(force=True) - - def _debug_exec(self, code, breakpoint): - if breakpoint: + compile_time: (float) time of statement compilation (s) + + """ + + def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision): + self.loops = loops + self.repeat = repeat + self.best = best + self.worst = worst + self.all_runs = all_runs + self.compile_time = compile_time + self._precision = precision + + def _repr_pretty_(self, p , cycle): + if self.loops == 1: # No s at "loops" if only one loop + unic = u"%d loop, best of %d: %s per loop" % (self.loops, self.repeat, + _format_time(self.best, self._precision)) + else: + unic = u"%d loops, best of %d: %s per loop" % (self.loops, self.repeat, + _format_time(self.best, self._precision)) + p.text(u'<TimeitResult : '+unic+u'>') + + +class TimeitTemplateFiller(ast.NodeTransformer): + """Fill in the AST template for timing execution. + + This is quite closely tied to the template definition, which is in + :meth:`ExecutionMagics.timeit`. + """ + def __init__(self, ast_setup, ast_stmt): + self.ast_setup = ast_setup + self.ast_stmt = ast_stmt + + def visit_FunctionDef(self, node): + "Fill in the setup statement" + self.generic_visit(node) + if node.name == "inner": + node.body[:1] = self.ast_setup.body + + return node + + def visit_For(self, node): + "Fill in the statement to be timed" + if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt': + node.body = self.ast_stmt.body + return node + + +class Timer(timeit.Timer): + """Timer class that explicitly uses self.inner + + which is an undocumented implementation detail of CPython, + not shared by PyPy. + """ + # Timer.timeit copied from CPython 3.4.2 + def timeit(self, number=timeit.default_number): + """Time 'number' executions of the main statement. + + To be precise, this executes the setup statement once, and + then returns the time it takes to execute the main statement + a number of times, as a float measured in seconds. The + argument is the number of times through the loop, defaulting + to one million. The main statement, the setup statement and + the timer function to be used are passed to the constructor. + """ + it = itertools.repeat(None, number) + gcold = gc.isenabled() + gc.disable() + try: + timing = self.inner(it, self.timer) + finally: + if gcold: + gc.enable() + return timing + + +@magics_class +class ExecutionMagics(Magics): + """Magics related to code execution, debugging, profiling, etc. + + """ + + def __init__(self, shell): + super(ExecutionMagics, self).__init__(shell) + if profile is None: + self.prun = self.profile_missing_notice + # Default execution function used to actually run user code. + self.default_runner = None + + def profile_missing_notice(self, *args, **kwargs): + error("""\ +The profile module could not be found. It has been removed from the standard +python packages because of its non-free license. To use profiling, install the +python-profiler package from non-free.""") + + @skip_doctest + @line_cell_magic + def prun(self, parameter_s='', cell=None): + + """Run a statement through the python code profiler. + + Usage, in line mode: + %prun [options] statement + + Usage, in cell mode: + %%prun [options] [statement] + code... + code... + + In cell mode, the additional code lines are appended to the (possibly + empty) statement in the first line. Cell mode allows you to easily + profile multiline blocks without having to put them in a separate + function. + + The given statement (which doesn't require quote marks) is run via the + python profiler in a manner similar to the profile.run() function. + Namespaces are internally managed to work correctly; profile.run + cannot be used in IPython because it makes certain assumptions about + namespaces which do not hold under IPython. + + Options: + + -l <limit> + you can place restrictions on what or how much of the + profile gets printed. The limit value can be: + + * A string: only information for function names containing this string + is printed. + + * An integer: only these many lines are printed. + + * A float (between 0 and 1): this fraction of the report is printed + (for example, use a limit of 0.4 to see the topmost 40% only). + + You can combine several limits with repeated use of the option. For + example, ``-l __init__ -l 5`` will print only the topmost 5 lines of + information about class constructors. + + -r + return the pstats.Stats object generated by the profiling. This + object has all the information about the profile in it, and you can + later use it for further analysis or in other functions. + + -s <key> + sort profile by given key. You can provide more than one key + by using the option several times: '-s key1 -s key2 -s key3...'. The + default sorting key is 'time'. + + The following is copied verbatim from the profile documentation + referenced below: + + When more than one key is provided, additional keys are used as + secondary criteria when the there is equality in all keys selected + before them. + + Abbreviations can be used for any key names, as long as the + abbreviation is unambiguous. The following are the keys currently + defined: + + ============ ===================== + Valid Arg Meaning + ============ ===================== + "calls" call count + "cumulative" cumulative time + "file" file name + "module" file name + "pcalls" primitive call count + "line" line number + "name" function name + "nfl" name/file/line + "stdname" standard name + "time" internal time + ============ ===================== + + Note that all sorts on statistics are in descending order (placing + most time consuming items first), where as name, file, and line number + searches are in ascending order (i.e., alphabetical). The subtle + distinction between "nfl" and "stdname" is that the standard name is a + sort of the name as printed, which means that the embedded line + numbers get compared in an odd way. For example, lines 3, 20, and 40 + would (if the file names were the same) appear in the string order + "20" "3" and "40". In contrast, "nfl" does a numeric compare of the + line numbers. In fact, sort_stats("nfl") is the same as + sort_stats("name", "file", "line"). + + -T <filename> + save profile results as shown on screen to a text + file. The profile is still shown on screen. + + -D <filename> + save (via dump_stats) profile statistics to given + filename. This data is in a format understood by the pstats module, and + is generated by a call to the dump_stats() method of profile + objects. The profile is still shown on screen. + + -q + suppress output to the pager. Best used with -T and/or -D above. + + If you want to run complete programs under the profiler's control, use + ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts + contains profiler specific options as described here. + + You can read the complete documentation for the profile module with:: + + In [1]: import profile; profile.help() + """ + opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q', + list_all=True, posix=False) + if cell is not None: + arg_str += '\n' + cell + arg_str = self.shell.input_splitter.transform_cell(arg_str) + return self._run_with_profiler(arg_str, opts, self.shell.user_ns) + + def _run_with_profiler(self, code, opts, namespace): + """ + Run `code` with profiler. Used by ``%prun`` and ``%run -p``. + + Parameters + ---------- + code : str + Code to be executed. + opts : Struct + Options parsed by `self.parse_options`. + namespace : dict + A dictionary for Python namespace (e.g., `self.shell.user_ns`). + + """ + + # Fill default values for unspecified options: + opts.merge(Struct(D=[''], l=[], s=['time'], T=[''])) + + prof = profile.Profile() + try: + prof = prof.runctx(code, namespace, namespace) + sys_exit = '' + except SystemExit: + sys_exit = """*** SystemExit exception caught in code being profiled.""" + + stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s) + + lims = opts.l + if lims: + lims = [] # rebuild lims with ints/floats/strings + for lim in opts.l: + try: + lims.append(int(lim)) + except ValueError: + try: + lims.append(float(lim)) + except ValueError: + lims.append(lim) + + # Trap output. + stdout_trap = StringIO() + stats_stream = stats.stream + try: + stats.stream = stdout_trap + stats.print_stats(*lims) + finally: + stats.stream = stats_stream + + output = stdout_trap.getvalue() + output = output.rstrip() + + if 'q' not in opts: + page.page(output) + print(sys_exit, end=' ') + + dump_file = opts.D[0] + text_file = opts.T[0] + if dump_file: + prof.dump_stats(dump_file) + print('\n*** Profile stats marshalled to file',\ + repr(dump_file)+'.',sys_exit) + if text_file: + pfile = open(text_file,'w') + pfile.write(output) + pfile.close() + print('\n*** Profile printout saved to text file',\ + repr(text_file)+'.',sys_exit) + + if 'r' in opts: + return stats + else: + return None + + @line_magic + def pdb(self, parameter_s=''): + """Control the automatic calling of the pdb interactive debugger. + + Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without + argument it works as a toggle. + + When an exception is triggered, IPython can optionally call the + interactive pdb debugger after the traceback printout. %pdb toggles + this feature on and off. + + The initial state of this feature is set in your configuration + file (the option is ``InteractiveShell.pdb``). + + If you want to just activate the debugger AFTER an exception has fired, + without having to type '%pdb on' and rerunning your code, you can use + the %debug magic.""" + + par = parameter_s.strip().lower() + + if par: + try: + new_pdb = {'off':0,'0':0,'on':1,'1':1}[par] + except KeyError: + print ('Incorrect argument. Use on/1, off/0, ' + 'or nothing for a toggle.') + return + else: + # toggle + new_pdb = not self.shell.call_pdb + + # set on the shell + self.shell.call_pdb = new_pdb + print('Automatic pdb calling has been turned',on_off(new_pdb)) + + @skip_doctest + @magic_arguments.magic_arguments() + @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE', + help=""" + Set break point at LINE in FILE. + """ + ) + @magic_arguments.argument('statement', nargs='*', + help=""" + Code to run in debugger. + You can omit this in cell magic mode. + """ + ) + @line_cell_magic + def debug(self, line='', cell=None): + """Activate the interactive debugger. + + This magic command support two ways of activating debugger. + One is to activate debugger before executing code. This way, you + can set a break point, to step through the code from the point. + You can use this mode by giving statements to execute and optionally + a breakpoint. + + The other one is to activate debugger in post-mortem mode. You can + activate this mode simply running %debug without any argument. + If an exception has just occurred, this lets you inspect its stack + frames interactively. Note that this will always work only on the last + traceback that occurred, so you must call this quickly after an + exception that you wish to inspect has fired, because if another one + occurs, it clobbers the previous one. + + If you want IPython to automatically do this on every exception, see + the %pdb magic for more details. + """ + args = magic_arguments.parse_argstring(self.debug, line) + + if not (args.breakpoint or args.statement or cell): + self._debug_post_mortem() + else: + code = "\n".join(args.statement) + if cell: + code += "\n" + cell + self._debug_exec(code, args.breakpoint) + + def _debug_post_mortem(self): + self.shell.debugger(force=True) + + def _debug_exec(self, code, breakpoint): + if breakpoint: (filename, bp_line) = breakpoint.rsplit(':', 1) - bp_line = int(bp_line) - else: - (filename, bp_line) = (None, None) - self._run_with_debugger(code, self.shell.user_ns, filename, bp_line) - - @line_magic - def tb(self, s): - """Print the last traceback with the currently active exception mode. - - See %xmode for changing exception reporting modes.""" - self.shell.showtraceback() - - @skip_doctest - @line_magic - def run(self, parameter_s='', runner=None, - file_finder=get_py_filename): - """Run the named file inside IPython as a program. - - Usage:: - - %run [-n -i -e -G] - [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )] - ( -m mod | file ) [args] - - Parameters after the filename are passed as command-line arguments to - the program (put in sys.argv). Then, control returns to IPython's - prompt. - - This is similar to running at a system prompt ``python file args``, - but with the advantage of giving you IPython's tracebacks, and of - loading all variables into your interactive namespace for further use - (unless -p is used, see below). - - The file is executed in a namespace initially consisting only of - ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus - sees its environment as if it were being run as a stand-alone program - (except for sharing global objects such as previously imported - modules). But after execution, the IPython interactive namespace gets - updated with all variables defined in the program (except for __name__ - and sys.argv). This allows for very convenient loading of code for - interactive work, while giving each program a 'clean sheet' to run in. - - Arguments are expanded using shell-like glob match. Patterns - '*', '?', '[seq]' and '[!seq]' can be used. Additionally, - tilde '~' will be expanded into user's home directory. Unlike - real shells, quotation does not suppress expansions. Use - *two* back slashes (e.g. ``\\\\*``) to suppress expansions. - To completely disable these expansions, you can use -G flag. - - Options: - - -n - __name__ is NOT set to '__main__', but to the running file's name - without extension (as python does under import). This allows running - scripts and reloading the definitions in them without calling code - protected by an ``if __name__ == "__main__"`` clause. - - -i - run the file in IPython's namespace instead of an empty one. This - is useful if you are experimenting with code written in a text editor - which depends on variables defined interactively. - - -e - ignore sys.exit() calls or SystemExit exceptions in the script - being run. This is particularly useful if IPython is being used to - run unittests, which always exit with a sys.exit() call. In such - cases you are interested in the output of the test results, not in - seeing a traceback of the unittest module. - - -t - print timing information at the end of the run. IPython will give - you an estimated CPU time consumption for your script, which under - Unix uses the resource module to avoid the wraparound problems of - time.clock(). Under Unix, an estimate of time spent on system tasks - is also given (for Windows platforms this is reported as 0.0). - - If -t is given, an additional ``-N<N>`` option can be given, where <N> - must be an integer indicating how many times you want the script to - run. The final timing report will include total and per run results. - - For example (testing the script uniq_stable.py):: - - In [1]: run -t uniq_stable - - IPython CPU timings (estimated): - User : 0.19597 s. - System: 0.0 s. - - In [2]: run -t -N5 uniq_stable - - IPython CPU timings (estimated): - Total runs performed: 5 - Times : Total Per run - User : 0.910862 s, 0.1821724 s. - System: 0.0 s, 0.0 s. - - -d - run your program under the control of pdb, the Python debugger. - This allows you to execute your program step by step, watch variables, - etc. Internally, what IPython does is similar to calling:: - - pdb.run('execfile("YOURFILENAME")') - - with a breakpoint set on line 1 of your file. You can change the line - number for this automatic breakpoint to be <N> by using the -bN option - (where N must be an integer). For example:: - - %run -d -b40 myscript - - will set the first breakpoint at line 40 in myscript.py. Note that - the first breakpoint must be set on a line which actually does - something (not a comment or docstring) for it to stop execution. - - Or you can specify a breakpoint in a different file:: - - %run -d -b myotherfile.py:20 myscript - - When the pdb debugger starts, you will see a (Pdb) prompt. You must - first enter 'c' (without quotes) to start execution up to the first - breakpoint. - - Entering 'help' gives information about the use of the debugger. You - can easily see pdb's full documentation with "import pdb;pdb.help()" - at a prompt. - - -p - run program under the control of the Python profiler module (which - prints a detailed report of execution times, function calls, etc). - - You can pass other options after -p which affect the behavior of the - profiler itself. See the docs for %prun for details. - - In this mode, the program's variables do NOT propagate back to the - IPython interactive namespace (because they remain in the namespace - where the profiler executes them). - - Internally this triggers a call to %prun, see its documentation for - details on the options available specifically for profiling. - - There is one special usage for which the text above doesn't apply: - if the filename ends with .ipy[nb], the file is run as ipython script, - just as if the commands were written on IPython prompt. - - -m - specify module name to load instead of script path. Similar to - the -m option for the python interpreter. Use this option last if you - want to combine with other %run options. Unlike the python interpreter - only source modules are allowed no .pyc or .pyo files. - For example:: - - %run -m example - - will run the example module. - - -G - disable shell-like glob expansion of arguments. - - """ - - # get arguments and set sys.argv for program to be run. - opts, arg_lst = self.parse_options(parameter_s, - 'nidtN:b:pD:l:rs:T:em:G', - mode='list', list_all=1) - if "m" in opts: - modulename = opts["m"][0] - modpath = find_mod(modulename) - if modpath is None: - warn('%r is not a valid modulename on sys.path'%modulename) - return - arg_lst = [modpath] + arg_lst - try: - filename = file_finder(arg_lst[0]) - except IndexError: - warn('you must provide at least a filename.') - print('\n%run:\n', oinspect.getdoc(self.run)) - return - except IOError as e: - try: - msg = str(e) - except UnicodeError: - msg = e.message - error(msg) - return - - if filename.lower().endswith(('.ipy', '.ipynb')): - with preserve_keys(self.shell.user_ns, '__file__'): - self.shell.user_ns['__file__'] = filename - self.shell.safe_execfile_ipy(filename) - return - - # Control the response to exit() calls made by the script being run - exit_ignore = 'e' in opts - - # Make sure that the running script gets a proper sys.argv as if it - # were run from a system shell. - save_argv = sys.argv # save it for later restoring - - if 'G' in opts: - args = arg_lst[1:] - else: - # tilde and glob expansion - args = shellglob(map(os.path.expanduser, arg_lst[1:])) - - sys.argv = [filename] + args # put in the proper filename - # protect sys.argv from potential unicode strings on Python 2: - if not py3compat.PY3: - sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ] - - if 'i' in opts: - # Run in user's interactive namespace - prog_ns = self.shell.user_ns - __name__save = self.shell.user_ns['__name__'] - prog_ns['__name__'] = '__main__' - main_mod = self.shell.user_module - - # Since '%run foo' emulates 'python foo.py' at the cmd line, we must - # set the __file__ global in the script's namespace - # TK: Is this necessary in interactive mode? - prog_ns['__file__'] = filename - else: - # Run in a fresh, empty namespace - if 'n' in opts: - name = os.path.splitext(os.path.basename(filename))[0] - else: - name = '__main__' - - # The shell MUST hold a reference to prog_ns so after %run - # exits, the python deletion mechanism doesn't zero it out - # (leaving dangling references). See interactiveshell for details - main_mod = self.shell.new_main_mod(filename, name) - prog_ns = main_mod.__dict__ - - # pickle fix. See interactiveshell for an explanation. But we need to - # make sure that, if we overwrite __main__, we replace it at the end - main_mod_name = prog_ns['__name__'] - - if main_mod_name == '__main__': - restore_main = sys.modules['__main__'] - else: - restore_main = False - - # This needs to be undone at the end to prevent holding references to - # every single object ever created. - sys.modules[main_mod_name] = main_mod - - if 'p' in opts or 'd' in opts: - if 'm' in opts: - code = 'run_module(modulename, prog_ns)' - code_ns = { - 'run_module': self.shell.safe_run_module, - 'prog_ns': prog_ns, - 'modulename': modulename, - } - else: - if 'd' in opts: - # allow exceptions to raise in debug mode - code = 'execfile(filename, prog_ns, raise_exceptions=True)' - else: - code = 'execfile(filename, prog_ns)' - code_ns = { - 'execfile': self.shell.safe_execfile, - 'prog_ns': prog_ns, - 'filename': get_py_filename(filename), - } - - try: - stats = None + bp_line = int(bp_line) + else: + (filename, bp_line) = (None, None) + self._run_with_debugger(code, self.shell.user_ns, filename, bp_line) + + @line_magic + def tb(self, s): + """Print the last traceback with the currently active exception mode. + + See %xmode for changing exception reporting modes.""" + self.shell.showtraceback() + + @skip_doctest + @line_magic + def run(self, parameter_s='', runner=None, + file_finder=get_py_filename): + """Run the named file inside IPython as a program. + + Usage:: + + %run [-n -i -e -G] + [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )] + ( -m mod | file ) [args] + + Parameters after the filename are passed as command-line arguments to + the program (put in sys.argv). Then, control returns to IPython's + prompt. + + This is similar to running at a system prompt ``python file args``, + but with the advantage of giving you IPython's tracebacks, and of + loading all variables into your interactive namespace for further use + (unless -p is used, see below). + + The file is executed in a namespace initially consisting only of + ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus + sees its environment as if it were being run as a stand-alone program + (except for sharing global objects such as previously imported + modules). But after execution, the IPython interactive namespace gets + updated with all variables defined in the program (except for __name__ + and sys.argv). This allows for very convenient loading of code for + interactive work, while giving each program a 'clean sheet' to run in. + + Arguments are expanded using shell-like glob match. Patterns + '*', '?', '[seq]' and '[!seq]' can be used. Additionally, + tilde '~' will be expanded into user's home directory. Unlike + real shells, quotation does not suppress expansions. Use + *two* back slashes (e.g. ``\\\\*``) to suppress expansions. + To completely disable these expansions, you can use -G flag. + + Options: + + -n + __name__ is NOT set to '__main__', but to the running file's name + without extension (as python does under import). This allows running + scripts and reloading the definitions in them without calling code + protected by an ``if __name__ == "__main__"`` clause. + + -i + run the file in IPython's namespace instead of an empty one. This + is useful if you are experimenting with code written in a text editor + which depends on variables defined interactively. + + -e + ignore sys.exit() calls or SystemExit exceptions in the script + being run. This is particularly useful if IPython is being used to + run unittests, which always exit with a sys.exit() call. In such + cases you are interested in the output of the test results, not in + seeing a traceback of the unittest module. + + -t + print timing information at the end of the run. IPython will give + you an estimated CPU time consumption for your script, which under + Unix uses the resource module to avoid the wraparound problems of + time.clock(). Under Unix, an estimate of time spent on system tasks + is also given (for Windows platforms this is reported as 0.0). + + If -t is given, an additional ``-N<N>`` option can be given, where <N> + must be an integer indicating how many times you want the script to + run. The final timing report will include total and per run results. + + For example (testing the script uniq_stable.py):: + + In [1]: run -t uniq_stable + + IPython CPU timings (estimated): + User : 0.19597 s. + System: 0.0 s. + + In [2]: run -t -N5 uniq_stable + + IPython CPU timings (estimated): + Total runs performed: 5 + Times : Total Per run + User : 0.910862 s, 0.1821724 s. + System: 0.0 s, 0.0 s. + + -d + run your program under the control of pdb, the Python debugger. + This allows you to execute your program step by step, watch variables, + etc. Internally, what IPython does is similar to calling:: + + pdb.run('execfile("YOURFILENAME")') + + with a breakpoint set on line 1 of your file. You can change the line + number for this automatic breakpoint to be <N> by using the -bN option + (where N must be an integer). For example:: + + %run -d -b40 myscript + + will set the first breakpoint at line 40 in myscript.py. Note that + the first breakpoint must be set on a line which actually does + something (not a comment or docstring) for it to stop execution. + + Or you can specify a breakpoint in a different file:: + + %run -d -b myotherfile.py:20 myscript + + When the pdb debugger starts, you will see a (Pdb) prompt. You must + first enter 'c' (without quotes) to start execution up to the first + breakpoint. + + Entering 'help' gives information about the use of the debugger. You + can easily see pdb's full documentation with "import pdb;pdb.help()" + at a prompt. + + -p + run program under the control of the Python profiler module (which + prints a detailed report of execution times, function calls, etc). + + You can pass other options after -p which affect the behavior of the + profiler itself. See the docs for %prun for details. + + In this mode, the program's variables do NOT propagate back to the + IPython interactive namespace (because they remain in the namespace + where the profiler executes them). + + Internally this triggers a call to %prun, see its documentation for + details on the options available specifically for profiling. + + There is one special usage for which the text above doesn't apply: + if the filename ends with .ipy[nb], the file is run as ipython script, + just as if the commands were written on IPython prompt. + + -m + specify module name to load instead of script path. Similar to + the -m option for the python interpreter. Use this option last if you + want to combine with other %run options. Unlike the python interpreter + only source modules are allowed no .pyc or .pyo files. + For example:: + + %run -m example + + will run the example module. + + -G + disable shell-like glob expansion of arguments. + + """ + + # get arguments and set sys.argv for program to be run. + opts, arg_lst = self.parse_options(parameter_s, + 'nidtN:b:pD:l:rs:T:em:G', + mode='list', list_all=1) + if "m" in opts: + modulename = opts["m"][0] + modpath = find_mod(modulename) + if modpath is None: + warn('%r is not a valid modulename on sys.path'%modulename) + return + arg_lst = [modpath] + arg_lst + try: + filename = file_finder(arg_lst[0]) + except IndexError: + warn('you must provide at least a filename.') + print('\n%run:\n', oinspect.getdoc(self.run)) + return + except IOError as e: + try: + msg = str(e) + except UnicodeError: + msg = e.message + error(msg) + return + + if filename.lower().endswith(('.ipy', '.ipynb')): + with preserve_keys(self.shell.user_ns, '__file__'): + self.shell.user_ns['__file__'] = filename + self.shell.safe_execfile_ipy(filename) + return + + # Control the response to exit() calls made by the script being run + exit_ignore = 'e' in opts + + # Make sure that the running script gets a proper sys.argv as if it + # were run from a system shell. + save_argv = sys.argv # save it for later restoring + + if 'G' in opts: + args = arg_lst[1:] + else: + # tilde and glob expansion + args = shellglob(map(os.path.expanduser, arg_lst[1:])) + + sys.argv = [filename] + args # put in the proper filename + # protect sys.argv from potential unicode strings on Python 2: + if not py3compat.PY3: + sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ] + + if 'i' in opts: + # Run in user's interactive namespace + prog_ns = self.shell.user_ns + __name__save = self.shell.user_ns['__name__'] + prog_ns['__name__'] = '__main__' + main_mod = self.shell.user_module + + # Since '%run foo' emulates 'python foo.py' at the cmd line, we must + # set the __file__ global in the script's namespace + # TK: Is this necessary in interactive mode? + prog_ns['__file__'] = filename + else: + # Run in a fresh, empty namespace + if 'n' in opts: + name = os.path.splitext(os.path.basename(filename))[0] + else: + name = '__main__' + + # The shell MUST hold a reference to prog_ns so after %run + # exits, the python deletion mechanism doesn't zero it out + # (leaving dangling references). See interactiveshell for details + main_mod = self.shell.new_main_mod(filename, name) + prog_ns = main_mod.__dict__ + + # pickle fix. See interactiveshell for an explanation. But we need to + # make sure that, if we overwrite __main__, we replace it at the end + main_mod_name = prog_ns['__name__'] + + if main_mod_name == '__main__': + restore_main = sys.modules['__main__'] + else: + restore_main = False + + # This needs to be undone at the end to prevent holding references to + # every single object ever created. + sys.modules[main_mod_name] = main_mod + + if 'p' in opts or 'd' in opts: + if 'm' in opts: + code = 'run_module(modulename, prog_ns)' + code_ns = { + 'run_module': self.shell.safe_run_module, + 'prog_ns': prog_ns, + 'modulename': modulename, + } + else: + if 'd' in opts: + # allow exceptions to raise in debug mode + code = 'execfile(filename, prog_ns, raise_exceptions=True)' + else: + code = 'execfile(filename, prog_ns)' + code_ns = { + 'execfile': self.shell.safe_execfile, + 'prog_ns': prog_ns, + 'filename': get_py_filename(filename), + } + + try: + stats = None if 'p' in opts: stats = self._run_with_profiler(code, opts, code_ns) else: @@ -713,20 +713,20 @@ python-profiler package from non-free.""") opts.get('b', ['1'])[0], filename) self._run_with_debugger( code, code_ns, filename, bp_line, bp_file) - else: + else: if 'm' in opts: def run(): self.shell.safe_run_module(modulename, prog_ns) - else: + else: if runner is None: runner = self.default_runner if runner is None: runner = self.shell.safe_execfile - + def run(): runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore) - + if 't' in opts: # timed execution try: @@ -740,67 +740,67 @@ python-profiler package from non-free.""") else: # regular execution run() - + if 'i' in opts: self.shell.user_ns['__name__'] = __name__save else: # update IPython interactive namespace - + # Some forms of read errors on the file may mean the # __name__ key was never set; using pop we don't have to # worry about a possible KeyError. prog_ns.pop('__name__', None) - + with preserve_keys(self.shell.user_ns, '__file__'): self.shell.user_ns.update(prog_ns) - finally: - # It's a bit of a mystery why, but __builtins__ can change from - # being a module to becoming a dict missing some key data after - # %run. As best I can see, this is NOT something IPython is doing - # at all, and similar problems have been reported before: - # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html - # Since this seems to be done by the interpreter itself, the best - # we can do is to at least restore __builtins__ for the user on - # exit. - self.shell.user_ns['__builtins__'] = builtin_mod - - # Ensure key global structures are restored - sys.argv = save_argv - if restore_main: - sys.modules['__main__'] = restore_main - else: - # Remove from sys.modules the reference to main_mod we'd - # added. Otherwise it will trap references to objects - # contained therein. - del sys.modules[main_mod_name] - - return stats - - def _run_with_debugger(self, code, code_ns, filename=None, - bp_line=None, bp_file=None): - """ - Run `code` in debugger with a break point. - - Parameters - ---------- - code : str - Code to execute. - code_ns : dict - A namespace in which `code` is executed. - filename : str - `code` is ran as if it is in `filename`. - bp_line : int, optional - Line number of the break point. - bp_file : str, optional - Path to the file in which break point is specified. - `filename` is used if not given. - - Raises - ------ - UsageError - If the break point given by `bp_line` is not valid. - - """ + finally: + # It's a bit of a mystery why, but __builtins__ can change from + # being a module to becoming a dict missing some key data after + # %run. As best I can see, this is NOT something IPython is doing + # at all, and similar problems have been reported before: + # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html + # Since this seems to be done by the interpreter itself, the best + # we can do is to at least restore __builtins__ for the user on + # exit. + self.shell.user_ns['__builtins__'] = builtin_mod + + # Ensure key global structures are restored + sys.argv = save_argv + if restore_main: + sys.modules['__main__'] = restore_main + else: + # Remove from sys.modules the reference to main_mod we'd + # added. Otherwise it will trap references to objects + # contained therein. + del sys.modules[main_mod_name] + + return stats + + def _run_with_debugger(self, code, code_ns, filename=None, + bp_line=None, bp_file=None): + """ + Run `code` in debugger with a break point. + + Parameters + ---------- + code : str + Code to execute. + code_ns : dict + A namespace in which `code` is executed. + filename : str + `code` is ran as if it is in `filename`. + bp_line : int, optional + Line number of the break point. + bp_file : str, optional + Path to the file in which break point is specified. + `filename` is used if not given. + + Raises + ------ + UsageError + If the break point given by `bp_line` is not valid. + + """ deb = self.shell.InteractiveTB.pdb if not deb: self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls() @@ -811,208 +811,208 @@ python-profiler package from non-free.""") if hasattr(deb, 'curframe'): del deb.curframe - # reset Breakpoint state, which is moronically kept - # in a class - bdb.Breakpoint.next = 1 - bdb.Breakpoint.bplist = {} - bdb.Breakpoint.bpbynumber = [None] + # reset Breakpoint state, which is moronically kept + # in a class + bdb.Breakpoint.next = 1 + bdb.Breakpoint.bplist = {} + bdb.Breakpoint.bpbynumber = [None] deb.clear_all_breaks() - if bp_line is not None: - # Set an initial breakpoint to stop execution - maxtries = 10 - bp_file = bp_file or filename - checkline = deb.checkline(bp_file, bp_line) - if not checkline: - for bp in range(bp_line + 1, bp_line + maxtries + 1): - if deb.checkline(bp_file, bp): - break - else: - msg = ("\nI failed to find a valid line to set " - "a breakpoint\n" - "after trying up to line: %s.\n" - "Please set a valid breakpoint manually " - "with the -b option." % bp) - raise UsageError(msg) - # if we find a good linenumber, set the breakpoint - deb.do_break('%s:%s' % (bp_file, bp_line)) - - if filename: - # Mimic Pdb._runscript(...) - deb._wait_for_mainpyfile = True - deb.mainpyfile = deb.canonic(filename) - - # Start file run - print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt) - try: - if filename: - # save filename so it can be used by methods on the deb object - deb._exec_filename = filename - while True: - try: - deb.run(code, code_ns) - except Restart: - print("Restarting") - if filename: - deb._wait_for_mainpyfile = True - deb.mainpyfile = deb.canonic(filename) - continue - else: - break - - - except: - etype, value, tb = sys.exc_info() - # Skip three frames in the traceback: the %run one, - # one inside bdb.py, and the command-line typed by the - # user (run by exec in pdb itself). - self.shell.InteractiveTB(etype, value, tb, tb_offset=3) - - @staticmethod - def _run_with_timing(run, nruns): - """ - Run function `run` and print timing information. - - Parameters - ---------- - run : callable - Any callable object which takes no argument. - nruns : int - Number of times to execute `run`. - - """ - twall0 = time.time() - if nruns == 1: - t0 = clock2() - run() - t1 = clock2() - t_usr = t1[0] - t0[0] - t_sys = t1[1] - t0[1] - print("\nIPython CPU timings (estimated):") - print(" User : %10.2f s." % t_usr) - print(" System : %10.2f s." % t_sys) - else: - runs = range(nruns) - t0 = clock2() - for nr in runs: - run() - t1 = clock2() - t_usr = t1[0] - t0[0] - t_sys = t1[1] - t0[1] - print("\nIPython CPU timings (estimated):") - print("Total runs performed:", nruns) - print(" Times : %10s %10s" % ('Total', 'Per run')) - print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)) - print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)) - twall1 = time.time() - print("Wall time: %10.2f s." % (twall1 - twall0)) - - @skip_doctest - @line_cell_magic - def timeit(self, line='', cell=None): - """Time execution of a Python statement or expression - - Usage, in line mode: - %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement - or in cell mode: - %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code - code - code... - - Time execution of a Python statement or expression using the timeit - module. This function can be used both as a line and cell magic: - - - In line mode you can time a single-line statement (though multiple - ones can be chained with using semicolons). - - - In cell mode, the statement in the first line is used as setup code - (executed but not timed) and the body of the cell is timed. The cell - body has access to any variables created in the setup code. - - Options: - -n<N>: execute the given statement <N> times in a loop. If this value - is not given, a fitting value is chosen. - - -r<R>: repeat the loop iteration <R> times and take the best result. - Default: 3 - - -t: use time.time to measure the time, which is the default on Unix. - This function measures wall time. - - -c: use time.clock to measure the time, which is the default on - Windows and measures wall time. On Unix, resource.getrusage is used - instead and returns the CPU user time. - - -p<P>: use a precision of <P> digits to display the timing result. - Default: 3 - - -q: Quiet, do not print result. - - -o: return a TimeitResult that can be stored in a variable to inspect - the result in more details. - - - Examples - -------- - :: - - In [1]: %timeit pass - 10000000 loops, best of 3: 53.3 ns per loop - - In [2]: u = None - - In [3]: %timeit u is None - 10000000 loops, best of 3: 184 ns per loop - - In [4]: %timeit -r 4 u == None - 1000000 loops, best of 4: 242 ns per loop - - In [5]: import time - - In [6]: %timeit -n1 time.sleep(2) - 1 loop, best of 3: 2 s per loop - - - The times reported by %timeit will be slightly higher than those - reported by the timeit.py script when variables are accessed. This is - due to the fact that %timeit executes the statement in the namespace - of the shell, compared with timeit.py, which uses a single setup - statement to import function or create variables. Generally, the bias - does not matter as long as results from timeit.py are not mixed with - those from %timeit.""" - - opts, stmt = self.parse_options(line,'n:r:tcp:qo', - posix=False, strict=False) - if stmt == "" and cell is None: - return - - timefunc = timeit.default_timer - number = int(getattr(opts, "n", 0)) - repeat = int(getattr(opts, "r", timeit.default_repeat)) - precision = int(getattr(opts, "p", 3)) - quiet = 'q' in opts - return_result = 'o' in opts - if hasattr(opts, "t"): - timefunc = time.time - if hasattr(opts, "c"): - timefunc = clock - - timer = Timer(timer=timefunc) - # this code has tight coupling to the inner workings of timeit.Timer, - # but is there a better way to achieve that the code stmt has access - # to the shell namespace? - transform = self.shell.input_splitter.transform_cell - - if cell is None: - # called as line magic - ast_setup = self.shell.compile.ast_parse("pass") - ast_stmt = self.shell.compile.ast_parse(transform(stmt)) - else: - ast_setup = self.shell.compile.ast_parse(transform(stmt)) - ast_stmt = self.shell.compile.ast_parse(transform(cell)) - - ast_setup = self.shell.transform_ast(ast_setup) - ast_stmt = self.shell.transform_ast(ast_stmt) - + if bp_line is not None: + # Set an initial breakpoint to stop execution + maxtries = 10 + bp_file = bp_file or filename + checkline = deb.checkline(bp_file, bp_line) + if not checkline: + for bp in range(bp_line + 1, bp_line + maxtries + 1): + if deb.checkline(bp_file, bp): + break + else: + msg = ("\nI failed to find a valid line to set " + "a breakpoint\n" + "after trying up to line: %s.\n" + "Please set a valid breakpoint manually " + "with the -b option." % bp) + raise UsageError(msg) + # if we find a good linenumber, set the breakpoint + deb.do_break('%s:%s' % (bp_file, bp_line)) + + if filename: + # Mimic Pdb._runscript(...) + deb._wait_for_mainpyfile = True + deb.mainpyfile = deb.canonic(filename) + + # Start file run + print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt) + try: + if filename: + # save filename so it can be used by methods on the deb object + deb._exec_filename = filename + while True: + try: + deb.run(code, code_ns) + except Restart: + print("Restarting") + if filename: + deb._wait_for_mainpyfile = True + deb.mainpyfile = deb.canonic(filename) + continue + else: + break + + + except: + etype, value, tb = sys.exc_info() + # Skip three frames in the traceback: the %run one, + # one inside bdb.py, and the command-line typed by the + # user (run by exec in pdb itself). + self.shell.InteractiveTB(etype, value, tb, tb_offset=3) + + @staticmethod + def _run_with_timing(run, nruns): + """ + Run function `run` and print timing information. + + Parameters + ---------- + run : callable + Any callable object which takes no argument. + nruns : int + Number of times to execute `run`. + + """ + twall0 = time.time() + if nruns == 1: + t0 = clock2() + run() + t1 = clock2() + t_usr = t1[0] - t0[0] + t_sys = t1[1] - t0[1] + print("\nIPython CPU timings (estimated):") + print(" User : %10.2f s." % t_usr) + print(" System : %10.2f s." % t_sys) + else: + runs = range(nruns) + t0 = clock2() + for nr in runs: + run() + t1 = clock2() + t_usr = t1[0] - t0[0] + t_sys = t1[1] - t0[1] + print("\nIPython CPU timings (estimated):") + print("Total runs performed:", nruns) + print(" Times : %10s %10s" % ('Total', 'Per run')) + print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)) + print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)) + twall1 = time.time() + print("Wall time: %10.2f s." % (twall1 - twall0)) + + @skip_doctest + @line_cell_magic + def timeit(self, line='', cell=None): + """Time execution of a Python statement or expression + + Usage, in line mode: + %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement + or in cell mode: + %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code + code + code... + + Time execution of a Python statement or expression using the timeit + module. This function can be used both as a line and cell magic: + + - In line mode you can time a single-line statement (though multiple + ones can be chained with using semicolons). + + - In cell mode, the statement in the first line is used as setup code + (executed but not timed) and the body of the cell is timed. The cell + body has access to any variables created in the setup code. + + Options: + -n<N>: execute the given statement <N> times in a loop. If this value + is not given, a fitting value is chosen. + + -r<R>: repeat the loop iteration <R> times and take the best result. + Default: 3 + + -t: use time.time to measure the time, which is the default on Unix. + This function measures wall time. + + -c: use time.clock to measure the time, which is the default on + Windows and measures wall time. On Unix, resource.getrusage is used + instead and returns the CPU user time. + + -p<P>: use a precision of <P> digits to display the timing result. + Default: 3 + + -q: Quiet, do not print result. + + -o: return a TimeitResult that can be stored in a variable to inspect + the result in more details. + + + Examples + -------- + :: + + In [1]: %timeit pass + 10000000 loops, best of 3: 53.3 ns per loop + + In [2]: u = None + + In [3]: %timeit u is None + 10000000 loops, best of 3: 184 ns per loop + + In [4]: %timeit -r 4 u == None + 1000000 loops, best of 4: 242 ns per loop + + In [5]: import time + + In [6]: %timeit -n1 time.sleep(2) + 1 loop, best of 3: 2 s per loop + + + The times reported by %timeit will be slightly higher than those + reported by the timeit.py script when variables are accessed. This is + due to the fact that %timeit executes the statement in the namespace + of the shell, compared with timeit.py, which uses a single setup + statement to import function or create variables. Generally, the bias + does not matter as long as results from timeit.py are not mixed with + those from %timeit.""" + + opts, stmt = self.parse_options(line,'n:r:tcp:qo', + posix=False, strict=False) + if stmt == "" and cell is None: + return + + timefunc = timeit.default_timer + number = int(getattr(opts, "n", 0)) + repeat = int(getattr(opts, "r", timeit.default_repeat)) + precision = int(getattr(opts, "p", 3)) + quiet = 'q' in opts + return_result = 'o' in opts + if hasattr(opts, "t"): + timefunc = time.time + if hasattr(opts, "c"): + timefunc = clock + + timer = Timer(timer=timefunc) + # this code has tight coupling to the inner workings of timeit.Timer, + # but is there a better way to achieve that the code stmt has access + # to the shell namespace? + transform = self.shell.input_splitter.transform_cell + + if cell is None: + # called as line magic + ast_setup = self.shell.compile.ast_parse("pass") + ast_stmt = self.shell.compile.ast_parse(transform(stmt)) + else: + ast_setup = self.shell.compile.ast_parse(transform(stmt)) + ast_stmt = self.shell.compile.ast_parse(transform(cell)) + + ast_setup = self.shell.transform_ast(ast_setup) + ast_stmt = self.shell.transform_ast(ast_stmt) + # Check that these compile to valid Python code *outside* the timer func # Invalid code may become valid when put inside the function & loop, # which messes up error messages. @@ -1020,359 +1020,359 @@ python-profiler package from non-free.""") self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec") self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec") - # This codestring is taken from timeit.template - we fill it in as an - # AST, so that we can apply our AST transformations to the user code - # without affecting the timing code. - timeit_ast_template = ast.parse('def inner(_it, _timer):\n' - ' setup\n' - ' _t0 = _timer()\n' - ' for _i in _it:\n' - ' stmt\n' - ' _t1 = _timer()\n' - ' return _t1 - _t0\n') - - timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template) - timeit_ast = ast.fix_missing_locations(timeit_ast) - - # Track compilation time so it can be reported if too long - # Minimum time above which compilation time will be reported - tc_min = 0.1 - - t0 = clock() - code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec") - tc = clock()-t0 - - ns = {} - exec(code, self.shell.user_ns, ns) - timer.inner = ns["inner"] - - # This is used to check if there is a huge difference between the - # best and worst timings. - # Issue: https://github.com/ipython/ipython/issues/6471 - worst_tuning = 0 - if number == 0: - # determine number so that 0.2 <= total time < 2.0 - number = 1 - for _ in range(1, 10): - time_number = timer.timeit(number) - worst_tuning = max(worst_tuning, time_number / number) - if time_number >= 0.2: - break - number *= 10 - all_runs = timer.repeat(repeat, number) - best = min(all_runs) / number - - worst = max(all_runs) / number - if worst_tuning: - worst = max(worst, worst_tuning) - - if not quiet : - # Check best timing is greater than zero to avoid a - # ZeroDivisionError. - # In cases where the slowest timing is lesser than a micosecond - # we assume that it does not really matter if the fastest - # timing is 4 times faster than the slowest timing or not. - if worst > 4 * best and best > 0 and worst > 1e-6: - print("The slowest run took %0.2f times longer than the " - "fastest. This could mean that an intermediate result " - "is being cached." % (worst / best)) - if number == 1: # No s at "loops" if only one loop - print(u"%d loop, best of %d: %s per loop" % (number, repeat, - _format_time(best, precision))) - else: - print(u"%d loops, best of %d: %s per loop" % (number, repeat, - _format_time(best, precision))) - if tc > tc_min: - print("Compiler time: %.2f s" % tc) - if return_result: - return TimeitResult(number, repeat, best, worst, all_runs, tc, precision) - - @skip_doctest - @needs_local_scope - @line_cell_magic - def time(self,line='', cell=None, local_ns=None): - """Time execution of a Python statement or expression. - - The CPU and wall clock times are printed, and the value of the - expression (if any) is returned. Note that under Win32, system time - is always reported as 0, since it can not be measured. - - This function can be used both as a line and cell magic: - - - In line mode you can time a single-line statement (though multiple - ones can be chained with using semicolons). - - - In cell mode, you can time the cell body (a directly - following statement raises an error). - - This function provides very basic timing functionality. Use the timeit - magic for more control over the measurement. - - Examples - -------- - :: - - In [1]: %time 2**128 - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 - Out[1]: 340282366920938463463374607431768211456L - - In [2]: n = 1000000 - - In [3]: %time sum(range(n)) - CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s - Wall time: 1.37 - Out[3]: 499999500000L - - In [4]: %time print 'hello world' - hello world - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 - - Note that the time needed by Python to compile the given expression - will be reported if it is more than 0.1s. In this example, the - actual exponentiation is done by Python at compilation time, so while - the expression can take a noticeable amount of time to compute, that - time is purely due to the compilation: - - In [5]: %time 3**9999; - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 s - - In [6]: %time 3**999999; - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 s - Compiler : 0.78 s - """ - - # fail immediately if the given expression can't be compiled - - if line and cell: - raise UsageError("Can't use statement directly after '%%time'!") - - if cell: - expr = self.shell.input_transformer_manager.transform_cell(cell) - else: - expr = self.shell.input_transformer_manager.transform_cell(line) - - # Minimum time above which parse time will be reported - tp_min = 0.1 - - t0 = clock() - expr_ast = self.shell.compile.ast_parse(expr) - tp = clock()-t0 - - # Apply AST transformations - expr_ast = self.shell.transform_ast(expr_ast) - - # Minimum time above which compilation time will be reported - tc_min = 0.1 - - if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr): - mode = 'eval' - source = '<timed eval>' - expr_ast = ast.Expression(expr_ast.body[0].value) - else: - mode = 'exec' - source = '<timed exec>' - t0 = clock() - code = self.shell.compile(expr_ast, source, mode) - tc = clock()-t0 - - # skew measurement as little as possible - glob = self.shell.user_ns - wtime = time.time - # time execution - wall_st = wtime() - if mode=='eval': - st = clock2() - out = eval(code, glob, local_ns) - end = clock2() - else: - st = clock2() - exec(code, glob, local_ns) - end = clock2() - out = None - wall_end = wtime() - # Compute actual times and report - wall_time = wall_end-wall_st - cpu_user = end[0]-st[0] - cpu_sys = end[1]-st[1] - cpu_tot = cpu_user+cpu_sys - # On windows cpu_sys is always zero, so no new information to the next print - if sys.platform != 'win32': - print("CPU times: user %s, sys: %s, total: %s" % \ - (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot))) - print("Wall time: %s" % _format_time(wall_time)) - if tc > tc_min: - print("Compiler : %s" % _format_time(tc)) - if tp > tp_min: - print("Parser : %s" % _format_time(tp)) - return out - - @skip_doctest - @line_magic - def macro(self, parameter_s=''): - """Define a macro for future re-execution. It accepts ranges of history, - filenames or string objects. - - Usage:\\ - %macro [options] name 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 at the - command line is used instead. - - -q: quiet macro definition. By default, a tag line is printed - to indicate the macro has been created, and then the contents of - the macro are printed. If this option is given, then no printout - is produced once the macro is created. - - This will define a global variable called `name` which is a string - made of joining the slices and lines you specify (n1,n2,... numbers - above) from your input history into a single string. This variable - acts like an automatic function which re-executes those lines as if - you had typed them. You just type 'name' at the prompt and the code - executes. - - The syntax for indicating input ranges is described in %history. - - Note: as a 'hidden' feature, you can also use traditional python slice - notation, where N:M means numbers N through M-1. - - For example, if your history contains (print using %hist -n ):: - - 44: x=1 - 45: y=3 - 46: z=x+y - 47: print x - 48: a=5 - 49: print 'x',x,'y',y - - you can create a macro with lines 44 through 47 (included) and line 49 - called my_macro with:: - - In [55]: %macro my_macro 44-47 49 - - Now, typing `my_macro` (without quotes) will re-execute all this code - in one pass. - - You don't need to give the line-numbers in order, and any given line - number can appear multiple times. You can assemble macros with any - lines from your input history in any order. - - The macro is a simple object which holds its value in an attribute, - but IPython's display system checks for macros and executes them as - code instead of printing them when you type their name. - - You can view a macro's contents by explicitly printing it with:: - - print macro_name - - """ - opts,args = self.parse_options(parameter_s,'rq',mode='list') - if not args: # List existing macros - return sorted(k for k,v in iteritems(self.shell.user_ns) if\ - isinstance(v, Macro)) - if len(args) == 1: - raise UsageError( - "%macro insufficient args; usage '%macro name n1-n2 n3-4...") - name, codefrom = args[0], " ".join(args[1:]) - - #print 'rng',ranges # dbg - try: - lines = self.shell.find_user_code(codefrom, 'r' in opts) - except (ValueError, TypeError) as e: - print(e.args[0]) - return - macro = Macro(lines) - self.shell.define_macro(name, macro) - if not ( 'q' in opts) : - print('Macro `%s` created. To execute, type its name (without quotes).' % name) - print('=== Macro contents: ===') - print(macro, end=' ') - - @magic_arguments.magic_arguments() - @magic_arguments.argument('output', type=str, default='', nargs='?', - help="""The name of the variable in which to store output. - This is a utils.io.CapturedIO object with stdout/err attributes - for the text of the captured output. - - CapturedOutput also has a show() method for displaying the output, - and __call__ as well, so you can use that to quickly display the - output. - - If unspecified, captured output is discarded. - """ - ) - @magic_arguments.argument('--no-stderr', action="store_true", - help="""Don't capture stderr.""" - ) - @magic_arguments.argument('--no-stdout', action="store_true", - help="""Don't capture stdout.""" - ) - @magic_arguments.argument('--no-display', action="store_true", - help="""Don't capture IPython's rich display.""" - ) - @cell_magic - def capture(self, line, cell): - """run the cell, capturing stdout, stderr, and IPython's rich display() calls.""" - args = magic_arguments.parse_argstring(self.capture, line) - out = not args.no_stdout - err = not args.no_stderr - disp = not args.no_display - with capture_output(out, err, disp) as io: - self.shell.run_cell(cell) - if args.output: - self.shell.user_ns[args.output] = io - -def parse_breakpoint(text, current_file): - '''Returns (file, line) for file:line and (current_file, line) for line''' - colon = text.find(':') - if colon == -1: - return current_file, int(text) - else: - return text[:colon], int(text[colon+1:]) - -def _format_time(timespan, precision=3): - """Formats the timespan in a human readable form""" - import math - - if timespan >= 60.0: - # we have more than a minute, format that in a human readable form - # Idea from http://snipplr.com/view/5713/ - parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)] - time = [] - leftover = timespan - for suffix, length in parts: - value = int(leftover / length) - if value > 0: - leftover = leftover % length - time.append(u'%s%s' % (str(value), suffix)) - if leftover < 1: - break - return " ".join(time) - - - # Unfortunately the unicode 'micro' symbol can cause problems in - # certain terminals. - # See bug: https://bugs.launchpad.net/ipython/+bug/348466 - # Try to prevent crashes by being more secure than it needs to - # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set. - units = [u"s", u"ms",u'us',"ns"] # the save value - if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding: - try: - u'\xb5'.encode(sys.stdout.encoding) - units = [u"s", u"ms",u'\xb5s',"ns"] - except: - pass - scaling = [1, 1e3, 1e6, 1e9] - - if timespan > 0.0: - order = min(-int(math.floor(math.log10(timespan)) // 3), 3) - else: - order = 3 - return u"%.*g %s" % (precision, timespan * scaling[order], units[order]) + # This codestring is taken from timeit.template - we fill it in as an + # AST, so that we can apply our AST transformations to the user code + # without affecting the timing code. + timeit_ast_template = ast.parse('def inner(_it, _timer):\n' + ' setup\n' + ' _t0 = _timer()\n' + ' for _i in _it:\n' + ' stmt\n' + ' _t1 = _timer()\n' + ' return _t1 - _t0\n') + + timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template) + timeit_ast = ast.fix_missing_locations(timeit_ast) + + # Track compilation time so it can be reported if too long + # Minimum time above which compilation time will be reported + tc_min = 0.1 + + t0 = clock() + code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec") + tc = clock()-t0 + + ns = {} + exec(code, self.shell.user_ns, ns) + timer.inner = ns["inner"] + + # This is used to check if there is a huge difference between the + # best and worst timings. + # Issue: https://github.com/ipython/ipython/issues/6471 + worst_tuning = 0 + if number == 0: + # determine number so that 0.2 <= total time < 2.0 + number = 1 + for _ in range(1, 10): + time_number = timer.timeit(number) + worst_tuning = max(worst_tuning, time_number / number) + if time_number >= 0.2: + break + number *= 10 + all_runs = timer.repeat(repeat, number) + best = min(all_runs) / number + + worst = max(all_runs) / number + if worst_tuning: + worst = max(worst, worst_tuning) + + if not quiet : + # Check best timing is greater than zero to avoid a + # ZeroDivisionError. + # In cases where the slowest timing is lesser than a micosecond + # we assume that it does not really matter if the fastest + # timing is 4 times faster than the slowest timing or not. + if worst > 4 * best and best > 0 and worst > 1e-6: + print("The slowest run took %0.2f times longer than the " + "fastest. This could mean that an intermediate result " + "is being cached." % (worst / best)) + if number == 1: # No s at "loops" if only one loop + print(u"%d loop, best of %d: %s per loop" % (number, repeat, + _format_time(best, precision))) + else: + print(u"%d loops, best of %d: %s per loop" % (number, repeat, + _format_time(best, precision))) + if tc > tc_min: + print("Compiler time: %.2f s" % tc) + if return_result: + return TimeitResult(number, repeat, best, worst, all_runs, tc, precision) + + @skip_doctest + @needs_local_scope + @line_cell_magic + def time(self,line='', cell=None, local_ns=None): + """Time execution of a Python statement or expression. + + The CPU and wall clock times are printed, and the value of the + expression (if any) is returned. Note that under Win32, system time + is always reported as 0, since it can not be measured. + + This function can be used both as a line and cell magic: + + - In line mode you can time a single-line statement (though multiple + ones can be chained with using semicolons). + + - In cell mode, you can time the cell body (a directly + following statement raises an error). + + This function provides very basic timing functionality. Use the timeit + magic for more control over the measurement. + + Examples + -------- + :: + + In [1]: %time 2**128 + CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s + Wall time: 0.00 + Out[1]: 340282366920938463463374607431768211456L + + In [2]: n = 1000000 + + In [3]: %time sum(range(n)) + CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s + Wall time: 1.37 + Out[3]: 499999500000L + + In [4]: %time print 'hello world' + hello world + CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s + Wall time: 0.00 + + Note that the time needed by Python to compile the given expression + will be reported if it is more than 0.1s. In this example, the + actual exponentiation is done by Python at compilation time, so while + the expression can take a noticeable amount of time to compute, that + time is purely due to the compilation: + + In [5]: %time 3**9999; + CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s + Wall time: 0.00 s + + In [6]: %time 3**999999; + CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s + Wall time: 0.00 s + Compiler : 0.78 s + """ + + # fail immediately if the given expression can't be compiled + + if line and cell: + raise UsageError("Can't use statement directly after '%%time'!") + + if cell: + expr = self.shell.input_transformer_manager.transform_cell(cell) + else: + expr = self.shell.input_transformer_manager.transform_cell(line) + + # Minimum time above which parse time will be reported + tp_min = 0.1 + + t0 = clock() + expr_ast = self.shell.compile.ast_parse(expr) + tp = clock()-t0 + + # Apply AST transformations + expr_ast = self.shell.transform_ast(expr_ast) + + # Minimum time above which compilation time will be reported + tc_min = 0.1 + + if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr): + mode = 'eval' + source = '<timed eval>' + expr_ast = ast.Expression(expr_ast.body[0].value) + else: + mode = 'exec' + source = '<timed exec>' + t0 = clock() + code = self.shell.compile(expr_ast, source, mode) + tc = clock()-t0 + + # skew measurement as little as possible + glob = self.shell.user_ns + wtime = time.time + # time execution + wall_st = wtime() + if mode=='eval': + st = clock2() + out = eval(code, glob, local_ns) + end = clock2() + else: + st = clock2() + exec(code, glob, local_ns) + end = clock2() + out = None + wall_end = wtime() + # Compute actual times and report + wall_time = wall_end-wall_st + cpu_user = end[0]-st[0] + cpu_sys = end[1]-st[1] + cpu_tot = cpu_user+cpu_sys + # On windows cpu_sys is always zero, so no new information to the next print + if sys.platform != 'win32': + print("CPU times: user %s, sys: %s, total: %s" % \ + (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot))) + print("Wall time: %s" % _format_time(wall_time)) + if tc > tc_min: + print("Compiler : %s" % _format_time(tc)) + if tp > tp_min: + print("Parser : %s" % _format_time(tp)) + return out + + @skip_doctest + @line_magic + def macro(self, parameter_s=''): + """Define a macro for future re-execution. It accepts ranges of history, + filenames or string objects. + + Usage:\\ + %macro [options] name 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 at the + command line is used instead. + + -q: quiet macro definition. By default, a tag line is printed + to indicate the macro has been created, and then the contents of + the macro are printed. If this option is given, then no printout + is produced once the macro is created. + + This will define a global variable called `name` which is a string + made of joining the slices and lines you specify (n1,n2,... numbers + above) from your input history into a single string. This variable + acts like an automatic function which re-executes those lines as if + you had typed them. You just type 'name' at the prompt and the code + executes. + + The syntax for indicating input ranges is described in %history. + + Note: as a 'hidden' feature, you can also use traditional python slice + notation, where N:M means numbers N through M-1. + + For example, if your history contains (print using %hist -n ):: + + 44: x=1 + 45: y=3 + 46: z=x+y + 47: print x + 48: a=5 + 49: print 'x',x,'y',y + + you can create a macro with lines 44 through 47 (included) and line 49 + called my_macro with:: + + In [55]: %macro my_macro 44-47 49 + + Now, typing `my_macro` (without quotes) will re-execute all this code + in one pass. + + You don't need to give the line-numbers in order, and any given line + number can appear multiple times. You can assemble macros with any + lines from your input history in any order. + + The macro is a simple object which holds its value in an attribute, + but IPython's display system checks for macros and executes them as + code instead of printing them when you type their name. + + You can view a macro's contents by explicitly printing it with:: + + print macro_name + + """ + opts,args = self.parse_options(parameter_s,'rq',mode='list') + if not args: # List existing macros + return sorted(k for k,v in iteritems(self.shell.user_ns) if\ + isinstance(v, Macro)) + if len(args) == 1: + raise UsageError( + "%macro insufficient args; usage '%macro name n1-n2 n3-4...") + name, codefrom = args[0], " ".join(args[1:]) + + #print 'rng',ranges # dbg + try: + lines = self.shell.find_user_code(codefrom, 'r' in opts) + except (ValueError, TypeError) as e: + print(e.args[0]) + return + macro = Macro(lines) + self.shell.define_macro(name, macro) + if not ( 'q' in opts) : + print('Macro `%s` created. To execute, type its name (without quotes).' % name) + print('=== Macro contents: ===') + print(macro, end=' ') + + @magic_arguments.magic_arguments() + @magic_arguments.argument('output', type=str, default='', nargs='?', + help="""The name of the variable in which to store output. + This is a utils.io.CapturedIO object with stdout/err attributes + for the text of the captured output. + + CapturedOutput also has a show() method for displaying the output, + and __call__ as well, so you can use that to quickly display the + output. + + If unspecified, captured output is discarded. + """ + ) + @magic_arguments.argument('--no-stderr', action="store_true", + help="""Don't capture stderr.""" + ) + @magic_arguments.argument('--no-stdout', action="store_true", + help="""Don't capture stdout.""" + ) + @magic_arguments.argument('--no-display', action="store_true", + help="""Don't capture IPython's rich display.""" + ) + @cell_magic + def capture(self, line, cell): + """run the cell, capturing stdout, stderr, and IPython's rich display() calls.""" + args = magic_arguments.parse_argstring(self.capture, line) + out = not args.no_stdout + err = not args.no_stderr + disp = not args.no_display + with capture_output(out, err, disp) as io: + self.shell.run_cell(cell) + if args.output: + self.shell.user_ns[args.output] = io + +def parse_breakpoint(text, current_file): + '''Returns (file, line) for file:line and (current_file, line) for line''' + colon = text.find(':') + if colon == -1: + return current_file, int(text) + else: + return text[:colon], int(text[colon+1:]) + +def _format_time(timespan, precision=3): + """Formats the timespan in a human readable form""" + import math + + if timespan >= 60.0: + # we have more than a minute, format that in a human readable form + # Idea from http://snipplr.com/view/5713/ + parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)] + time = [] + leftover = timespan + for suffix, length in parts: + value = int(leftover / length) + if value > 0: + leftover = leftover % length + time.append(u'%s%s' % (str(value), suffix)) + if leftover < 1: + break + return " ".join(time) + + + # Unfortunately the unicode 'micro' symbol can cause problems in + # certain terminals. + # See bug: https://bugs.launchpad.net/ipython/+bug/348466 + # Try to prevent crashes by being more secure than it needs to + # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set. + units = [u"s", u"ms",u'us',"ns"] # the save value + if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding: + try: + u'\xb5'.encode(sys.stdout.encoding) + units = [u"s", u"ms",u'\xb5s',"ns"] + except: + pass + scaling = [1, 1e3, 1e6, 1e9] + + if timespan > 0.0: + order = min(-int(math.floor(math.log10(timespan)) // 3), 3) + else: + order = 3 + return u"%.*g %s" % (precision, timespan * scaling[order], units[order]) diff --git a/contrib/python/ipython/py2/IPython/core/magics/extension.py b/contrib/python/ipython/py2/IPython/core/magics/extension.py index cf9a9ab9d1..2991d55ca4 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/extension.py +++ b/contrib/python/ipython/py2/IPython/core/magics/extension.py @@ -1,67 +1,67 @@ -"""Implementation of magic functions for the extension machinery. -""" -from __future__ import print_function -#----------------------------------------------------------------------------- -# 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 - -# Our own packages -from IPython.core.error import UsageError -from IPython.core.magic import Magics, magics_class, line_magic -from warnings import warn - -#----------------------------------------------------------------------------- -# 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) +"""Implementation of magic functions for the extension machinery. +""" +from __future__ import print_function +#----------------------------------------------------------------------------- +# 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 + +# Our own packages +from IPython.core.error import UsageError +from IPython.core.magic import Magics, magics_class, line_magic +from warnings import warn + +#----------------------------------------------------------------------------- +# 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) diff --git a/contrib/python/ipython/py2/IPython/core/magics/history.py b/contrib/python/ipython/py2/IPython/core/magics/history.py index 342e641d48..5967591394 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/history.py +++ b/contrib/python/ipython/py2/IPython/core/magics/history.py @@ -1,320 +1,320 @@ -"""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 -#----------------------------------------------------------------------------- -from __future__ import print_function - -# Stdlib -import os +"""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 +#----------------------------------------------------------------------------- +from __future__ import print_function + +# 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 -from IPython.utils.py3compat import cast_unicode_py2 - -#----------------------------------------------------------------------------- -# 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().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: +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 +from IPython.utils.py3compat import cast_unicode_py2 + +#----------------------------------------------------------------------------- +# 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().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(cast_unicode_py2(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) + # 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(cast_unicode_py2(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) diff --git a/contrib/python/ipython/py2/IPython/core/magics/logging.py b/contrib/python/ipython/py2/IPython/core/magics/logging.py index 0fafdeff6b..90214ab54a 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/logging.py +++ b/contrib/python/ipython/py2/IPython/core/magics/logging.py @@ -1,184 +1,184 @@ -"""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 +"""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 IPython.utils.py3compat import str_to_unicode - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -@magics_class -class LoggingMagics(Magics): - """Magics related to all logging machinery.""" - - @line_magic - def logstart(self, parameter_s=''): - """Start logging anywhere in a session. - - %logstart [-o|-r|-t] [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). - """ - - opts,par = self.parse_options(parameter_s,'ort') - log_output = 'o' in opts - log_raw_input = 'r' in opts - timestamp = 't' 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(str_to_unicode(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 - - 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() +from IPython.utils.py3compat import str_to_unicode + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + +@magics_class +class LoggingMagics(Magics): + """Magics related to all logging machinery.""" + + @line_magic + def logstart(self, parameter_s=''): + """Start logging anywhere in a session. + + %logstart [-o|-r|-t] [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). + """ + + opts,par = self.parse_options(parameter_s,'ort') + log_output = 'o' in opts + log_raw_input = 'r' in opts + timestamp = 't' 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(str_to_unicode(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 + + 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() diff --git a/contrib/python/ipython/py2/IPython/core/magics/namespace.py b/contrib/python/ipython/py2/IPython/core/magics/namespace.py index fafecb191b..c02b38716b 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/namespace.py +++ b/contrib/python/ipython/py2/IPython/core/magics/namespace.py @@ -1,704 +1,704 @@ -"""Implementation of namespace-related magic functions. -""" -from __future__ import print_function -#----------------------------------------------------------------------------- -# 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 -from IPython.utils.py3compat import unicode_type - -#----------------------------------------------------------------------------- -# 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('(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. - - '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 - """ - try: - parameter_s.encode('ascii') - except UnicodeEncodeError: - print('Python identifiers can only contain ascii characters.') - return - - # default namespaces to be searched - def_search = ['user_local', 'user_global', 'builtin'] - - # Process options/args - opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True) - opt = opts.get - shell = self.shell - psearch = shell.inspector.psearch - - # 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) - 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 = unicode_type(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 _ip.user_ns - Out[8]: True - - In [9]: %reset -f - - In [1]: 'a' in _ip.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)) +"""Implementation of namespace-related magic functions. +""" +from __future__ import print_function +#----------------------------------------------------------------------------- +# 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 +from IPython.utils.py3compat import unicode_type + +#----------------------------------------------------------------------------- +# 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('(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. + + '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 + """ + try: + parameter_s.encode('ascii') + except UnicodeEncodeError: + print('Python identifiers can only contain ascii characters.') + return + + # default namespaces to be searched + def_search = ['user_local', 'user_global', 'builtin'] + + # Process options/args + opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True) + opt = opts.get + shell = self.shell + psearch = shell.inspector.psearch + + # 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) + 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 = unicode_type(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 _ip.user_ns + Out[8]: True + + In [9]: %reset -f + + In [1]: 'a' in _ip.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)) diff --git a/contrib/python/ipython/py2/IPython/core/magics/osm.py b/contrib/python/ipython/py2/IPython/core/magics/osm.py index e4c3bbc7b6..352cf2d451 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/osm.py +++ b/contrib/python/ipython/py2/IPython/core/magics/osm.py @@ -1,790 +1,790 @@ -"""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. -""" -from __future__ import print_function -#----------------------------------------------------------------------------- -# 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 io -import os -import re -import sys -from pprint import pformat - -# Our own packages -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 import py3compat -from IPython.utils.py3compat import unicode_type -from IPython.utils.terminal import set_term_title - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- -@magics_class -class OSMagics(Magics): - """Magics to interact with the underlying OS (shell-type functionality). - """ - - @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 acess 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.""" - - 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 = [] - # Now define isexec in a cross platform manner. - if os.name == 'posix': - isexec = lambda fname:os.path.isfile(fname) and \ - os.access(fname,os.X_OK) - else: - try: - winext = os.environ['pathext'].replace(';','|').replace('.','') - except KeyError: - winext = 'exe|com|bat|py' - if 'py' not in winext: - winext += '|py' - execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) - isexec = lambda fname:os.path.isfile(fname) and execre.match(fname) - savedir = py3compat.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 os.name == 'posix': - for pdir in path: - try: - os.chdir(pdir) - dirlist = os.listdir(pdir) - except OSError: - continue - for ff in dirlist: - if isexec(ff): - try: - # Removes dots from the name since ipython - # will assume names with dots to be python. - if not self.shell.alias_manager.is_alias(ff): - self.shell.alias_manager.define_alias( - ff.replace('.',''), ff) - except InvalidAliasError: - pass - else: - syscmdlist.append(ff) - else: - no_alias = Alias.blacklist - for pdir in path: - try: - os.chdir(pdir) - dirlist = os.listdir(pdir) - except OSError: - continue - for ff in dirlist: - base, ext = os.path.splitext(ff) - if isexec(ff) and base.lower() not in no_alias: - if ext.lower() == '.exe': - ff = 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('.',''), ff) - except InvalidAliasError: - pass - syscmdlist.append(ff) - 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' - """ - return py3compat.getcwd() - - @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 - """ - - oldcwd = py3compat.getcwd() - 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: +"""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. +""" +from __future__ import print_function +#----------------------------------------------------------------------------- +# 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 io +import os +import re +import sys +from pprint import pformat + +# Our own packages +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 import py3compat +from IPython.utils.py3compat import unicode_type +from IPython.utils.terminal import set_term_title + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- +@magics_class +class OSMagics(Magics): + """Magics to interact with the underlying OS (shell-type functionality). + """ + + @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 acess 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.""" + + 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 = [] + # Now define isexec in a cross platform manner. + if os.name == 'posix': + isexec = lambda fname:os.path.isfile(fname) and \ + os.access(fname,os.X_OK) + else: + try: + winext = os.environ['pathext'].replace(';','|').replace('.','') + except KeyError: + winext = 'exe|com|bat|py' + if 'py' not in winext: + winext += '|py' + execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) + isexec = lambda fname:os.path.isfile(fname) and execre.match(fname) + savedir = py3compat.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 os.name == 'posix': + for pdir in path: + try: + os.chdir(pdir) + dirlist = os.listdir(pdir) + except OSError: + continue + for ff in dirlist: + if isexec(ff): + try: + # Removes dots from the name since ipython + # will assume names with dots to be python. + if not self.shell.alias_manager.is_alias(ff): + self.shell.alias_manager.define_alias( + ff.replace('.',''), ff) + except InvalidAliasError: + pass + else: + syscmdlist.append(ff) + else: + no_alias = Alias.blacklist + for pdir in path: + try: + os.chdir(pdir) + dirlist = os.listdir(pdir) + except OSError: + continue + for ff in dirlist: + base, ext = os.path.splitext(ff) + if isexec(ff) and base.lower() not in no_alias: + if ext.lower() == '.exe': + ff = 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('.',''), ff) + except InvalidAliasError: + pass + syscmdlist.append(ff) + 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' + """ + return py3compat.getcwd() + + @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 + """ + + oldcwd = py3compat.getcwd() + 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('IPython: ' + abbrev_cwd()) - except OSError: - print(sys.exc_info()[1]) - else: - cwd = py3compat.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('IPython: ' + '~') - cwd = py3compat.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 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) - return dict(os.environ) - - @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[py3compat.cast_bytes_py2(var)] = py3compat.cast_bytes_py2(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 + # 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('IPython: ' + abbrev_cwd()) + except OSError: + print(sys.exc_info()[1]) + else: + cwd = py3compat.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('IPython: ' + '~') + cwd = py3compat.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 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) + return dict(os.environ) + + @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[py3compat.cast_bytes_py2(var)] = py3compat.cast_bytes_py2(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 = py3compat.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]] = py3compat.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=unicode_type, - 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) + cwd = py3compat.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]] = py3compat.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=unicode_type, + 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) 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) + 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) diff --git a/contrib/python/ipython/py2/IPython/core/magics/pylab.py b/contrib/python/ipython/py2/IPython/core/magics/pylab.py index deec14cb7c..6c5cd68a59 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/pylab.py +++ b/contrib/python/ipython/py2/IPython/core/magics/pylab.py @@ -1,167 +1,167 @@ -"""Implementation of magic functions for matplotlib/pylab support. -""" -from __future__ import print_function -#----------------------------------------------------------------------------- -# 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 +"""Implementation of magic functions for matplotlib/pylab support. +""" +from __future__ import print_function +#----------------------------------------------------------------------------- +# 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) - 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) +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) + 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) diff --git a/contrib/python/ipython/py2/IPython/core/magics/script.py b/contrib/python/ipython/py2/IPython/core/magics/script.py index d381d97234..3fbddc38a8 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/script.py +++ b/contrib/python/ipython/py2/IPython/core/magics/script.py @@ -1,280 +1,280 @@ -"""Magic functions for running cells in various scripts.""" -from __future__ import print_function - +"""Magic functions for running cells in various scripts.""" +from __future__ import print_function + # 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 -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 + +import errno +import os +import sys +import signal +import time +from subprocess import Popen, PIPE +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. - """ - ), - 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. - """ - ), - 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. - """ - ), - ] - 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. - """ + +#----------------------------------------------------------------------------- +# 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. + """ + ), + 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. + """ + ), + 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. + """ + ), + ] + 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 - """, + 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 - + 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. - """ + 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() - if args.out: - self.shell.user_ns[args.out] = p.stdout - if args.err: - self.shell.user_ns[args.err] = p.stderr - self.job_manager.new(self._run_script, p, cell, 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.bytes_to_str(out) - err = py3compat.bytes_to_str(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() - - def _run_script(self, p, cell): - """callback for running the script in the background""" - p.stdin.write(cell) - p.stdin.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.""" + + 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() + if args.out: + self.shell.user_ns[args.out] = p.stdout + if args.err: + self.shell.user_ns[args.err] = p.stderr + self.job_manager.new(self._run_script, p, cell, 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.bytes_to_str(out) + err = py3compat.bytes_to_str(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() + + def _run_script(self, p, cell): + """callback for running the script in the background""" + p.stdin.write(cell) + p.stdin.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) + 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) + 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] + 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] |