##// END OF EJS Templates
Allow history to store multiple outputs for a single input line.
Thomas Kluyver -
Show More
@@ -275,16 +275,13 b' class DisplayHook(Configurable):'
275 275 new_result = '_'+`self.prompt_count`
276 276 to_main[new_result] = result
277 277 self.shell.user_ns.update(to_main)
278 self.shell.user_ns['_oh'][self.prompt_count] = result
278 # This is a defaultdict of lists, so we can always append
279 self.shell.user_ns['_oh'][self.prompt_count].append(result)
279 280
280 281 def log_output(self, format_dict):
281 282 """Log the output."""
282 283 if self.shell.logger.log_output:
283 284 self.shell.logger.log_write(format_dict['text/plain'], 'output')
284 # Write output to the database. Does nothing unless history
285 # output logging is enabled.
286 self.shell.history_manager.store_output(self.prompt_count,
287 format_dict['text/plain'])
288 285
289 286 def finish_displayhook(self):
290 287 """Finish up all displayhook activities."""
@@ -14,10 +14,13 b' from __future__ import print_function'
14 14
15 15 # Stdlib imports
16 16 import datetime
17 import json
17 18 import os
18 19 import re
19 20 import sqlite3
20 21
22 from collections import defaultdict
23
21 24 # Our own packages
22 25 from IPython.config.configurable import Configurable
23 26 import IPython.utils.io
@@ -45,7 +48,7 b' class HistoryManager(Configurable):'
45 48 # A list of directories visited during session
46 49 dir_hist = List()
47 50 # A dict of output history, keyed with ints from the shell's execution count
48 output_hist = Dict()
51 output_hist = Instance(defaultdict)
49 52 # String holding the path to the history file
50 53 hist_file = Unicode()
51 54 # The SQLite database
@@ -94,6 +97,7 b' class HistoryManager(Configurable):'
94 97 self.new_session()
95 98
96 99 self._i00, self._i, self._ii, self._iii = '','','',''
100 self.output_hist = defaultdict(list)
97 101
98 102 self._exit_commands = set(['Quit', 'quit', 'Exit', 'exit', '%Quit',
99 103 '%quit', '%Exit', '%exit'])
@@ -179,8 +183,10 b' class HistoryManager(Configurable):'
179 183 toget = "history.%s, output_history.output" % toget
180 184 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
181 185 (toget, sqlfrom) + sql, params)
182 if output: # Regroup into 3-tuples
183 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
186 if output: # Regroup into 3-tuples, and parse JSON
187 loads = lambda out: json.loads(out) if out else None
188 return ((ses, lin, (inp, loads(out))) \
189 for ses, lin, inp, out in cur)
184 190 return cur
185 191
186 192
@@ -221,7 +227,8 b' class HistoryManager(Configurable):'
221 227
222 228 for i in range(start, stop):
223 229 if output:
224 line = (input_hist[i], repr(self.output_hist.get(i)))
230 output_item = [repr(x) for x in self.output_hist[i]]
231 line = (input_hist[i], output_item)
225 232 else:
226 233 line = input_hist[i]
227 234 yield (0, i, line)
@@ -324,9 +331,10 b' class HistoryManager(Configurable):'
324 331 new_i : self._i00 }
325 332 self.shell.user_ns.update(to_main)
326 333
327 def store_output(self, line_num, output):
328 if not self.db_log_output:
334 def store_output(self, line_num):
335 if (not self.db_log_output) or not self.output_hist[line_num]:
329 336 return
337 output = json.dumps([repr(x) for x in self.output_hist[line_num]])
330 338 db_row = (self.session_number, line_num, output)
331 339 if self.db_cache_size > 1:
332 340 self.db_output_cache.append(db_row)
@@ -524,7 +532,7 b" def magic_history(self, parameter_s = ''):"
524 532 inline = "\n... ".join(inline.splitlines()) + "\n..."
525 533 print(inline, file=outfile)
526 534 if get_output and output:
527 print(output, file=outfile)
535 print("\n".join(output), file=outfile)
528 536
529 537 if close_at_end:
530 538 outfile.close()
@@ -2119,8 +2119,11 b' class InteractiveShell(Configurable, Magic):'
2119 2119
2120 2120 # Single-block input should behave like an interactive prompt
2121 2121 if len(blocks) == 1:
2122 # since we return here, we need to update the execution count
2123 2122 out = self.run_source(blocks[0])
2123 # Write output to the database. Does nothing unless
2124 # history output logging is enabled.
2125 self.history_manager.store_output(self.execution_count)
2126 # since we return here, we need to update the execution count
2124 2127 self.execution_count += 1
2125 2128 return out
2126 2129
@@ -2148,6 +2151,9 b' class InteractiveShell(Configurable, Magic):'
2148 2151 # processed input in history
2149 2152 self.run_source(ipy_cell, symbol='exec')
2150 2153
2154 # Write output to the database. Does nothing unless
2155 # history output logging is enabled.
2156 self.history_manager.store_output(self.execution_count)
2151 2157 # Each cell is a *single* input, regardless of how many lines it has
2152 2158 self.execution_count += 1
2153 2159
@@ -38,7 +38,8 b' def test_history():'
38 38
39 39 ip.history_manager.db_log_output = True
40 40 # Doesn't match the input, but we'll just check it's stored.
41 ip.history_manager.store_output(3, "spam")
41 ip.history_manager.output_hist[3].append("spam")
42 ip.history_manager.store_output(3)
42 43
43 44 nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist)
44 45
@@ -59,7 +60,7 b' def test_history():'
59 60
60 61 # Check get_hist_tail
61 62 gothist = ip.history_manager.get_hist_tail(4, output=True)
62 expected = [(1, 3, (hist[-1], "spam")),
63 expected = [(1, 3, (hist[-1], [repr("spam")])),
63 64 (2, 1, (newcmds[0], None)),
64 65 (2, 2, (newcmds[1], None)),
65 66 (2, 3, (newcmds[2], None)),]
@@ -69,7 +70,7 b' def test_history():'
69 70 gothist = ip.history_manager.get_hist_search("*test*")
70 71 nt.assert_equal(list(gothist), [(1,2,hist[1])] )
71 72 gothist = ip.history_manager.get_hist_search("b*", output=True)
72 nt.assert_equal(list(gothist), [(1,3,(hist[2],"spam"))] )
73 nt.assert_equal(list(gothist), [(1,3,(hist[2],[repr("spam")]))] )
73 74
74 75 # Cross testing: check that magic %save can get previous session.
75 76 testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))
General Comments 0
You need to be logged in to leave comments. Login now