Skip to content

Commit

Permalink
Merge branch 'cleanup-save-history' of https://github.com/takluyver/i…
Browse files Browse the repository at this point in the history
…python into takluyver-cleanup-save-history
  • Loading branch information
fperez committed Apr 3, 2011
2 parents 7d1bdfa + 4851de4 commit d325df5
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 110 deletions.
83 changes: 54 additions & 29 deletions IPython/core/interactiveshell.py
Expand Up @@ -131,6 +131,45 @@ def validate(self, obj, value):

class MultipleInstanceError(Exception):
pass

class ReadlineNoRecord(object):
"""Context manager to execute some code, then reload readline history
so that interactive input to the code doesn't appear when pressing up."""
def __init__(self, shell):
self.shell = shell
self._nested_level = 0

def __enter__(self):
if self._nested_level == 0:
self.orig_length = self.current_length()
self.readline_tail = self.get_readline_tail()
self._nested_level += 1

def __exit__(self, type, value, traceback):
self._nested_level -= 1
if self._nested_level == 0:
# Try clipping the end if it's got longer
e = self.current_length() - self.orig_length
if e > 0:
for _ in range(e):
self.shell.readline.remove_history_item(self.orig_length)

# If it still doesn't match, just reload readline history.
if self.current_length() != self.orig_length \
or self.get_readline_tail() != self.readline_tail:
self.shell.refill_readline_hist()
# Returning False will cause exceptions to propagate
return False

def current_length(self):
return self.shell.readline.get_current_history_length()

def get_readline_tail(self, n=10):
"""Get the last n items in readline history."""
end = self.shell.readline.get_current_history_length() + 1
start = max(end-n, 1)
ghi = self.shell.readline.get_history_item
return [ghi(x) for x in range(start, end)]


#-----------------------------------------------------------------------------
Expand Down Expand Up @@ -738,7 +777,9 @@ def debugger(self,force=False):
else:
# fallback to our internal debugger
pm = lambda : self.InteractiveTB.debugger(force=True)
self.history_saving_wrapper(pm)()

with self.readline_no_record:
pm()

#-------------------------------------------------------------------------
# Things related to IPython's various namespaces
Expand Down Expand Up @@ -1251,26 +1292,6 @@ def init_history(self):
"""Sets up the command history, and starts regular autosaves."""
self.history_manager = HistoryManager(shell=self, config=self.config)

def history_saving_wrapper(self, func):
""" Wrap func for readline history saving
Convert func into callable that saves & restores
history around the call """

if self.has_readline:
from IPython.utils import rlineimpl as readline
else:
return func

def wrapper():
self.save_history()
try:
func()
finally:
self.reload_history()
return wrapper


#-------------------------------------------------------------------------
# Things related to exception handling and tracebacks (not debugging)
#-------------------------------------------------------------------------
Expand Down Expand Up @@ -1551,17 +1572,21 @@ def init_readline(self):
# otherwise we end up with a monster history after a while:
readline.set_history_length(self.history_length)

stdin_encoding = sys.stdin.encoding or "utf-8"

# Load the last 1000 lines from history
for _, _, cell in self.history_manager.get_tail(1000,
include_latest=True):
if cell.strip(): # Ignore blank lines
for line in cell.splitlines():
readline.add_history(line.encode(stdin_encoding))
self.refill_readline_hist()
self.readline_no_record = ReadlineNoRecord(self)

# Configure auto-indent for all platforms
self.set_autoindent(self.autoindent)

def refill_readline_hist(self):
# Load the last 1000 lines from history
self.readline.clear_history()
stdin_encoding = sys.stdin.encoding or "utf-8"
for _, _, cell in self.history_manager.get_tail(1000,
include_latest=True):
if cell.strip(): # Ignore blank lines
for line in cell.splitlines():
self.readline.add_history(line.encode(stdin_encoding))

def set_next_input(self, s):
""" Sets the 'default' input string for the next command line.
Expand Down
159 changes: 78 additions & 81 deletions IPython/core/magic.py
Expand Up @@ -1605,90 +1605,89 @@ def magic_run(self, parameter_s ='',runner=None,
# every single object ever created.
sys.modules[main_mod_name] = main_mod

stats = None
try:
#self.shell.save_history()

if opts.has_key('p'):
stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
else:
if opts.has_key('d'):
deb = debugger.Pdb(self.shell.colors)
# reset Breakpoint state, which is moronically kept
# in a class
bdb.Breakpoint.next = 1
bdb.Breakpoint.bplist = {}
bdb.Breakpoint.bpbynumber = [None]
# Set an initial breakpoint to stop execution
maxtries = 10
bp = int(opts.get('b',[1])[0])
checkline = deb.checkline(filename,bp)
if not checkline:
for bp in range(bp+1,bp+maxtries+1):
if deb.checkline(filename,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)
error(msg)
return
# if we find a good linenumber, set the breakpoint
deb.do_break('%s:%s' % (filename,bp))
# Start file run
print "NOTE: Enter 'c' at the",
print "%s prompt to start your script." % deb.prompt
try:
deb.run('execfile("%s")' % filename,prog_ns)

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)
stats = None
with self.readline_no_record:
if opts.has_key('p'):
stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
else:
if runner is None:
runner = self.shell.safe_execfile
if opts.has_key('t'):
# timed execution
try:
nruns = int(opts['N'][0])
if nruns < 1:
error('Number of runs must be >=1')
if opts.has_key('d'):
deb = debugger.Pdb(self.shell.colors)
# reset Breakpoint state, which is moronically kept
# in a class
bdb.Breakpoint.next = 1
bdb.Breakpoint.bplist = {}
bdb.Breakpoint.bpbynumber = [None]
# Set an initial breakpoint to stop execution
maxtries = 10
bp = int(opts.get('b',[1])[0])
checkline = deb.checkline(filename,bp)
if not checkline:
for bp in range(bp+1,bp+maxtries+1):
if deb.checkline(filename,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)
error(msg)
return
except (KeyError):
nruns = 1
if nruns == 1:
t0 = clock2()
runner(filename,prog_ns,prog_ns,
exit_ignore=exit_ignore)
t1 = clock2()
t_usr = t1[0]-t0[0]
t_sys = t1[1]-t0[1]
print "\nIPython CPU timings (estimated):"
print " User : %10s s." % t_usr
print " System: %10s s." % t_sys
else:
runs = range(nruns)
t0 = clock2()
for nr in runs:
runner(filename,prog_ns,prog_ns,
exit_ignore=exit_ignore)
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 : %10s s, %10s s." % (t_usr,t_usr/nruns)
print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
# if we find a good linenumber, set the breakpoint
deb.do_break('%s:%s' % (filename,bp))
# Start file run
print "NOTE: Enter 'c' at the",
print "%s prompt to start your script." % deb.prompt
try:
deb.run('execfile("%s")' % filename,prog_ns)

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)
else:
# regular execution
runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
if runner is None:
runner = self.shell.safe_execfile
if opts.has_key('t'):
# timed execution
try:
nruns = int(opts['N'][0])
if nruns < 1:
error('Number of runs must be >=1')
return
except (KeyError):
nruns = 1
if nruns == 1:
t0 = clock2()
runner(filename,prog_ns,prog_ns,
exit_ignore=exit_ignore)
t1 = clock2()
t_usr = t1[0]-t0[0]
t_sys = t1[1]-t0[1]
print "\nIPython CPU timings (estimated):"
print " User : %10s s." % t_usr
print " System: %10s s." % t_sys
else:
runs = range(nruns)
t0 = clock2()
for nr in runs:
runner(filename,prog_ns,prog_ns,
exit_ignore=exit_ignore)
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 : %10s s, %10s s." % (t_usr,t_usr/nruns)
print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)

else:
# regular execution
runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)

if opts.has_key('i'):
self.shell.user_ns['__name__'] = __name__save
Expand Down Expand Up @@ -1725,8 +1724,6 @@ def magic_run(self, parameter_s ='',runner=None,
# added. Otherwise it will trap references to objects
# contained therein.
del sys.modules[main_mod_name]

#self.shell.reload_history()

return stats

Expand Down

0 comments on commit d325df5

Please sign in to comment.