##// END OF EJS Templates
Merge branch 'cleanup-save-history' of https://github.com/takluyver/ipython into takluyver-cleanup-save-history
Fernando Perez -
r3498:d325df50 merge
parent child Browse files
Show More
@@ -131,6 +131,45 b' class SeparateStr(Str):'
131
131
132 class MultipleInstanceError(Exception):
132 class MultipleInstanceError(Exception):
133 pass
133 pass
134
135 class ReadlineNoRecord(object):
136 """Context manager to execute some code, then reload readline history
137 so that interactive input to the code doesn't appear when pressing up."""
138 def __init__(self, shell):
139 self.shell = shell
140 self._nested_level = 0
141
142 def __enter__(self):
143 if self._nested_level == 0:
144 self.orig_length = self.current_length()
145 self.readline_tail = self.get_readline_tail()
146 self._nested_level += 1
147
148 def __exit__(self, type, value, traceback):
149 self._nested_level -= 1
150 if self._nested_level == 0:
151 # Try clipping the end if it's got longer
152 e = self.current_length() - self.orig_length
153 if e > 0:
154 for _ in range(e):
155 self.shell.readline.remove_history_item(self.orig_length)
156
157 # If it still doesn't match, just reload readline history.
158 if self.current_length() != self.orig_length \
159 or self.get_readline_tail() != self.readline_tail:
160 self.shell.refill_readline_hist()
161 # Returning False will cause exceptions to propagate
162 return False
163
164 def current_length(self):
165 return self.shell.readline.get_current_history_length()
166
167 def get_readline_tail(self, n=10):
168 """Get the last n items in readline history."""
169 end = self.shell.readline.get_current_history_length() + 1
170 start = max(end-n, 1)
171 ghi = self.shell.readline.get_history_item
172 return [ghi(x) for x in range(start, end)]
134
173
135
174
136 #-----------------------------------------------------------------------------
175 #-----------------------------------------------------------------------------
@@ -738,7 +777,9 b' class InteractiveShell(Configurable, Magic):'
738 else:
777 else:
739 # fallback to our internal debugger
778 # fallback to our internal debugger
740 pm = lambda : self.InteractiveTB.debugger(force=True)
779 pm = lambda : self.InteractiveTB.debugger(force=True)
741 self.history_saving_wrapper(pm)()
780
781 with self.readline_no_record:
782 pm()
742
783
743 #-------------------------------------------------------------------------
784 #-------------------------------------------------------------------------
744 # Things related to IPython's various namespaces
785 # Things related to IPython's various namespaces
@@ -1251,26 +1292,6 b' class InteractiveShell(Configurable, Magic):'
1251 """Sets up the command history, and starts regular autosaves."""
1292 """Sets up the command history, and starts regular autosaves."""
1252 self.history_manager = HistoryManager(shell=self, config=self.config)
1293 self.history_manager = HistoryManager(shell=self, config=self.config)
1253
1294
1254 def history_saving_wrapper(self, func):
1255 """ Wrap func for readline history saving
1256
1257 Convert func into callable that saves & restores
1258 history around the call """
1259
1260 if self.has_readline:
1261 from IPython.utils import rlineimpl as readline
1262 else:
1263 return func
1264
1265 def wrapper():
1266 self.save_history()
1267 try:
1268 func()
1269 finally:
1270 self.reload_history()
1271 return wrapper
1272
1273
1274 #-------------------------------------------------------------------------
1295 #-------------------------------------------------------------------------
1275 # Things related to exception handling and tracebacks (not debugging)
1296 # Things related to exception handling and tracebacks (not debugging)
1276 #-------------------------------------------------------------------------
1297 #-------------------------------------------------------------------------
@@ -1551,17 +1572,21 b' class InteractiveShell(Configurable, Magic):'
1551 # otherwise we end up with a monster history after a while:
1572 # otherwise we end up with a monster history after a while:
1552 readline.set_history_length(self.history_length)
1573 readline.set_history_length(self.history_length)
1553
1574
1554 stdin_encoding = sys.stdin.encoding or "utf-8"
1575 self.refill_readline_hist()
1555
1576 self.readline_no_record = ReadlineNoRecord(self)
1556 # Load the last 1000 lines from history
1557 for _, _, cell in self.history_manager.get_tail(1000,
1558 include_latest=True):
1559 if cell.strip(): # Ignore blank lines
1560 for line in cell.splitlines():
1561 readline.add_history(line.encode(stdin_encoding))
1562
1577
1563 # Configure auto-indent for all platforms
1578 # Configure auto-indent for all platforms
1564 self.set_autoindent(self.autoindent)
1579 self.set_autoindent(self.autoindent)
1580
1581 def refill_readline_hist(self):
1582 # Load the last 1000 lines from history
1583 self.readline.clear_history()
1584 stdin_encoding = sys.stdin.encoding or "utf-8"
1585 for _, _, cell in self.history_manager.get_tail(1000,
1586 include_latest=True):
1587 if cell.strip(): # Ignore blank lines
1588 for line in cell.splitlines():
1589 self.readline.add_history(line.encode(stdin_encoding))
1565
1590
1566 def set_next_input(self, s):
1591 def set_next_input(self, s):
1567 """ Sets the 'default' input string for the next command line.
1592 """ Sets the 'default' input string for the next command line.
@@ -1605,90 +1605,89 b' Currently the magic system has the following functions:\\n"""'
1605 # every single object ever created.
1605 # every single object ever created.
1606 sys.modules[main_mod_name] = main_mod
1606 sys.modules[main_mod_name] = main_mod
1607
1607
1608 stats = None
1609 try:
1608 try:
1610 #self.shell.save_history()
1609 stats = None
1611
1610 with self.readline_no_record:
1612 if opts.has_key('p'):
1611 if opts.has_key('p'):
1613 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1612 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1614 else:
1615 if opts.has_key('d'):
1616 deb = debugger.Pdb(self.shell.colors)
1617 # reset Breakpoint state, which is moronically kept
1618 # in a class
1619 bdb.Breakpoint.next = 1
1620 bdb.Breakpoint.bplist = {}
1621 bdb.Breakpoint.bpbynumber = [None]
1622 # Set an initial breakpoint to stop execution
1623 maxtries = 10
1624 bp = int(opts.get('b',[1])[0])
1625 checkline = deb.checkline(filename,bp)
1626 if not checkline:
1627 for bp in range(bp+1,bp+maxtries+1):
1628 if deb.checkline(filename,bp):
1629 break
1630 else:
1631 msg = ("\nI failed to find a valid line to set "
1632 "a breakpoint\n"
1633 "after trying up to line: %s.\n"
1634 "Please set a valid breakpoint manually "
1635 "with the -b option." % bp)
1636 error(msg)
1637 return
1638 # if we find a good linenumber, set the breakpoint
1639 deb.do_break('%s:%s' % (filename,bp))
1640 # Start file run
1641 print "NOTE: Enter 'c' at the",
1642 print "%s prompt to start your script." % deb.prompt
1643 try:
1644 deb.run('execfile("%s")' % filename,prog_ns)
1645
1646 except:
1647 etype, value, tb = sys.exc_info()
1648 # Skip three frames in the traceback: the %run one,
1649 # one inside bdb.py, and the command-line typed by the
1650 # user (run by exec in pdb itself).
1651 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1652 else:
1613 else:
1653 if runner is None:
1614 if opts.has_key('d'):
1654 runner = self.shell.safe_execfile
1615 deb = debugger.Pdb(self.shell.colors)
1655 if opts.has_key('t'):
1616 # reset Breakpoint state, which is moronically kept
1656 # timed execution
1617 # in a class
1657 try:
1618 bdb.Breakpoint.next = 1
1658 nruns = int(opts['N'][0])
1619 bdb.Breakpoint.bplist = {}
1659 if nruns < 1:
1620 bdb.Breakpoint.bpbynumber = [None]
1660 error('Number of runs must be >=1')
1621 # Set an initial breakpoint to stop execution
1622 maxtries = 10
1623 bp = int(opts.get('b',[1])[0])
1624 checkline = deb.checkline(filename,bp)
1625 if not checkline:
1626 for bp in range(bp+1,bp+maxtries+1):
1627 if deb.checkline(filename,bp):
1628 break
1629 else:
1630 msg = ("\nI failed to find a valid line to set "
1631 "a breakpoint\n"
1632 "after trying up to line: %s.\n"
1633 "Please set a valid breakpoint manually "
1634 "with the -b option." % bp)
1635 error(msg)
1661 return
1636 return
1662 except (KeyError):
1637 # if we find a good linenumber, set the breakpoint
1663 nruns = 1
1638 deb.do_break('%s:%s' % (filename,bp))
1664 if nruns == 1:
1639 # Start file run
1665 t0 = clock2()
1640 print "NOTE: Enter 'c' at the",
1666 runner(filename,prog_ns,prog_ns,
1641 print "%s prompt to start your script." % deb.prompt
1667 exit_ignore=exit_ignore)
1642 try:
1668 t1 = clock2()
1643 deb.run('execfile("%s")' % filename,prog_ns)
1669 t_usr = t1[0]-t0[0]
1670 t_sys = t1[1]-t0[1]
1671 print "\nIPython CPU timings (estimated):"
1672 print " User : %10s s." % t_usr
1673 print " System: %10s s." % t_sys
1674 else:
1675 runs = range(nruns)
1676 t0 = clock2()
1677 for nr in runs:
1678 runner(filename,prog_ns,prog_ns,
1679 exit_ignore=exit_ignore)
1680 t1 = clock2()
1681 t_usr = t1[0]-t0[0]
1682 t_sys = t1[1]-t0[1]
1683 print "\nIPython CPU timings (estimated):"
1684 print "Total runs performed:",nruns
1685 print " Times : %10s %10s" % ('Total','Per run')
1686 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1687 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1688
1644
1645 except:
1646 etype, value, tb = sys.exc_info()
1647 # Skip three frames in the traceback: the %run one,
1648 # one inside bdb.py, and the command-line typed by the
1649 # user (run by exec in pdb itself).
1650 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1689 else:
1651 else:
1690 # regular execution
1652 if runner is None:
1691 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1653 runner = self.shell.safe_execfile
1654 if opts.has_key('t'):
1655 # timed execution
1656 try:
1657 nruns = int(opts['N'][0])
1658 if nruns < 1:
1659 error('Number of runs must be >=1')
1660 return
1661 except (KeyError):
1662 nruns = 1
1663 if nruns == 1:
1664 t0 = clock2()
1665 runner(filename,prog_ns,prog_ns,
1666 exit_ignore=exit_ignore)
1667 t1 = clock2()
1668 t_usr = t1[0]-t0[0]
1669 t_sys = t1[1]-t0[1]
1670 print "\nIPython CPU timings (estimated):"
1671 print " User : %10s s." % t_usr
1672 print " System: %10s s." % t_sys
1673 else:
1674 runs = range(nruns)
1675 t0 = clock2()
1676 for nr in runs:
1677 runner(filename,prog_ns,prog_ns,
1678 exit_ignore=exit_ignore)
1679 t1 = clock2()
1680 t_usr = t1[0]-t0[0]
1681 t_sys = t1[1]-t0[1]
1682 print "\nIPython CPU timings (estimated):"
1683 print "Total runs performed:",nruns
1684 print " Times : %10s %10s" % ('Total','Per run')
1685 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1686 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1687
1688 else:
1689 # regular execution
1690 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1692
1691
1693 if opts.has_key('i'):
1692 if opts.has_key('i'):
1694 self.shell.user_ns['__name__'] = __name__save
1693 self.shell.user_ns['__name__'] = __name__save
@@ -1725,8 +1724,6 b' Currently the magic system has the following functions:\\n"""'
1725 # added. Otherwise it will trap references to objects
1724 # added. Otherwise it will trap references to objects
1726 # contained therein.
1725 # contained therein.
1727 del sys.modules[main_mod_name]
1726 del sys.modules[main_mod_name]
1728
1729 #self.shell.reload_history()
1730
1727
1731 return stats
1728 return stats
1732
1729
General Comments 0
You need to be logged in to leave comments. Login now