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