##// END OF EJS Templates
Merge pull request #13215 from Carreau/reformat-x...
Merge pull request #13215 from Carreau/reformat-x reformat previous commit

File last commit:

r26641:65602328
r26944:ce18cc44 merge
Show More
history.py
333 lines | 12.2 KiB | text/x-python | PythonLexer
Fernando Perez
Create new core.magics package and start populating with history.
r6956 """Implementation of magic functions related to History.
"""
#-----------------------------------------------------------------------------
# Copyright (c) 2012, IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# Stdlib
import os
Thomas Kluyver
Deprecate io.{stdout,stderr} and shell.{write,write_err}...
r22192 import sys
Fernando Perez
Create new core.magics package and start populating with history.
r6956 from io import open as io_open
Daniel Goldfarb
implement range pattern with prints for testing
r26363 import fnmatch
Fernando Perez
Create new core.magics package and start populating with history.
r6956
# Our own packages
from IPython.core.error import StdinNotImplementedError
Fernando Perez
Renamed @register_magics to @magics_class to avoid confusion....
r6973 from IPython.core.magic import Magics, magics_class, line_magic
Takafumi Arakaki
Use an unique object instead of specified flag
r8539 from IPython.core.magic_arguments import (argument, magic_arguments,
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 parse_argstring)
Fernando Perez
Create new core.magics package and start populating with history.
r6956 from IPython.testing.skipdoctest import skip_doctest
from IPython.utils import io
#-----------------------------------------------------------------------------
# Magics class implementation
#-----------------------------------------------------------------------------
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424
Takafumi Arakaki
Use an unique object instead of specified flag
r8539 _unspecified = object()
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424
Fernando Perez
Renamed @register_magics to @magics_class to avoid confusion....
r6973 @magics_class
Fernando Perez
Create new core.magics package and start populating with history.
r6956 class HistoryMagics(Magics):
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 @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
adityausathe
fix for #10327 : get_ipython.magic() replaced with get_ipython.run_line_magic()
r23750 seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 """)
@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="""
Takafumi Arakaki
Fix help string of -g option for %history
r8452 treat the arg as a glob pattern to search for in (full) history.
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 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(
Takafumi Arakaki
Use an unique object instead of specified flag
r8539 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 help="""
get the last n lines from all sessions. Specify n as a single
arg, or the default is the last 10 lines.
""")
Takafumi Arakaki
Add -u argument to %history magic
r8784 @argument(
'-u', dest='unique', action='store_true',
help="""
when searching history using `-g`, show only unique history.
""")
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 @argument('range', nargs='*')
Fernando Perez
Create new core.magics package and start populating with history.
r6956 @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:
Thomas Kluyver
Miscellaneous docs fixes
r9244
``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.
Fernando Perez
Create new core.magics package and start populating with history.
r6956 Multiple ranges can be entered, separated by spaces
The same syntax is used by %macro, %save, %edit, %rerun
Examples
--------
::
Bradley M. Froehle
Use magic alias api to register magic aliases.
r7933 In [6]: %history -n 4-6
Fernando Perez
Create new core.magics package and start populating with history.
r6956 4:a = 12
5:print a**2
Bradley M. Froehle
Use magic alias api to register magic aliases.
r7933 6:%history -n 4-6
Fernando Perez
Create new core.magics package and start populating with history.
r6956
"""
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 args = parse_argstring(self.history, parameter_s)
Fernando Perez
Create new core.magics package and start populating with history.
r6956
# 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.
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 outfname = args.filename
if not outfname:
Thomas Kluyver
Deprecate io.{stdout,stderr} and shell.{write,write_err}...
r22192 outfile = sys.stdout # default
Fernando Perez
Create new core.magics package and start populating with history.
r6956 # 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
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 print_nums = args.print_nums
get_output = args.get_output
pyprompts = args.pyprompts
raw = args.raw
Fernando Perez
Create new core.magics package and start populating with history.
r6956
pattern = None
Takafumi Arakaki
Use an unique object instead of specified flag
r8539 limit = None if args.limit is _unspecified else args.limit
Fernando Perez
Create new core.magics package and start populating with history.
r6956
Daniel Goldfarb
implement range pattern with prints for testing
r26363 range_pattern = False
if args.pattern is not None and not args.range:
Takafumi Arakaki
Rewrite %history magic using magic_arguments
r8424 if args.pattern:
pattern = "*" + " ".join(args.pattern) + "*"
else:
pattern = "*"
Takafumi Arakaki
Limit option -l for %history can be used with -g now
r8425 hist = history_manager.search(pattern, raw=raw, output=get_output,
Takafumi Arakaki
Add -u argument to %history magic
r8784 n=limit, unique=args.unique)
Fernando Perez
Create new core.magics package and start populating with history.
r6956 print_nums = True
Takafumi Arakaki
Use an unique object instead of specified flag
r8539 elif args.limit is not _unspecified:
n = 10 if limit is None else limit
Fernando Perez
Create new core.magics package and start populating with history.
r6956 hist = history_manager.get_tail(n, raw=raw, output=get_output)
else:
Blazej Michalik
Remove unnecessary branch in %history...
r26632 if args.pattern:
range_pattern = "*" + " ".join(args.pattern) + "*"
print_nums = True
Blazej Michalik
Darker
r26641 hist = history_manager.get_range_by_str(
" ".join(args.range), raw, get_output
)
Fernando Perez
Create new core.magics package and start populating with history.
r6956
# 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
Daniel Goldfarb
implement range pattern with prints for testing
r26363 if range_pattern:
Daniel Goldfarb
darker -r 60625f241f298b5039cb2debc365db38aa7bb522
r26365 if not fnmatch.fnmatch(inline, range_pattern):
continue
Fernando Perez
Create new core.magics package and start populating with history.
r6956 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:
Srinivas Reddy Thatiparthy
remove python2 specific cast_unicode_py2 function
r23669 print(output, file=outfile)
Fernando Perez
Create new core.magics package and start populating with history.
r6956
if close_at_end:
outfile.close()
@line_magic
Bradley M. Froehle
Use magic alias api to register magic aliases.
r7933 def recall(self, arg):
Fernando Perez
Create new core.magics package and start populating with history.
r6956 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
Bradley M. Froehle
Use magic alias api to register magic aliases.
r7933 In[3]: %recall
Fernando Perez
Create new core.magics package and start populating with history.
r6956 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]):
Bradley M. Froehle
Use magic alias api to register magic aliases.
r7933 if 'recall' in h or 'rep' in h:
Fernando Perez
Create new core.magics package and start populating with history.
r6956 continue
self.shell.set_next_input(h.rstrip())
return
else:
self.shell.set_next_input(cmd.rstrip())
Blazej Michalik
Ensure %recall does not show error after argument eval
r26533 return
Fernando Perez
Create new core.magics package and start populating with history.
r6956 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'])
Blazej Michalik
Nicer output for erroneous args to %rerun -l
r26549
if n == 0:
print("Requested 0 last lines - nothing to run")
return
elif n < 0:
print("Number of lines to rerun cannot be negative")
return
Fernando Perez
Create new core.magics package and start populating with history.
r6956 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)