From 36a9e8f206a207ecb9997cacb9accf35c57ce64f 2011-03-27 20:25:19 From: Thomas Kluyver Date: 2011-03-27 20:25:19 Subject: [PATCH] Add context manager to reload readline history when leaving a block. --- diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index a0b55e5..9db7081 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -130,6 +130,23 @@ class SeparateStr(Str): 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): + self._nested_level += 1 + + def __exit__(self, type, value, traceback): + self._nested_level -= 1 + if self._nested_level == 0: + self.shell.refill_readline_hist() + # Returning False will cause exceptions to propagate + return False #----------------------------------------------------------------------------- @@ -737,7 +754,9 @@ class InteractiveShell(Configurable, Magic): else: # fallback to our internal debugger pm = lambda : self.InteractiveTB.debugger(force=True) - pm() + + with self.readline_no_record: + pm() #------------------------------------------------------------------------- # Things related to IPython's various namespaces @@ -1530,17 +1549,21 @@ class InteractiveShell(Configurable, Magic): # 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. diff --git a/IPython/core/magic.py b/IPython/core/magic.py index a571e49..8471c42 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -1600,88 +1600,89 @@ Currently the magic system has the following functions:\n""" # every single object ever created. sys.modules[main_mod_name] = main_mod - stats = None try: - 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