Show More
@@ -282,9 +282,8 b' class DisplayHook(Configurable):' | |||||
282 | """Log the output.""" |
|
282 | """Log the output.""" | |
283 | if self.shell.logger.log_output: |
|
283 | if self.shell.logger.log_output: | |
284 | self.shell.logger.log_write(format_dict['text/plain'], 'output') |
|
284 | self.shell.logger.log_write(format_dict['text/plain'], 'output') | |
285 | # This is a defaultdict of lists, so we can always append |
|
285 | self.shell.history_manager.output_hist_reprs[self.prompt_count] = \ | |
286 | self.shell.history_manager.output_hist_reprs[self.prompt_count]\ |
|
286 | format_dict['text/plain'] | |
287 | .append(format_dict['text/plain']) |
|
|||
288 |
|
287 | |||
289 | def finish_displayhook(self): |
|
288 | def finish_displayhook(self): | |
290 | """Finish up all displayhook activities.""" |
|
289 | """Finish up all displayhook activities.""" |
@@ -15,14 +15,11 b' from __future__ import print_function' | |||||
15 | # Stdlib imports |
|
15 | # Stdlib imports | |
16 | import atexit |
|
16 | import atexit | |
17 | import datetime |
|
17 | import datetime | |
18 | import json |
|
|||
19 | import os |
|
18 | import os | |
20 | import re |
|
19 | import re | |
21 | import sqlite3 |
|
20 | import sqlite3 | |
22 | import threading |
|
21 | import threading | |
23 |
|
22 | |||
24 | from collections import defaultdict |
|
|||
25 |
|
||||
26 | # Our own packages |
|
23 | # Our own packages | |
27 | from IPython.config.configurable import Configurable |
|
24 | from IPython.config.configurable import Configurable | |
28 | import IPython.utils.io |
|
25 | import IPython.utils.io | |
@@ -56,11 +53,10 b' class HistoryManager(Configurable):' | |||||
56 | return [] |
|
53 | return [] | |
57 |
|
54 | |||
58 | # A dict of output history, keyed with ints from the shell's |
|
55 | # A dict of output history, keyed with ints from the shell's | |
59 | # execution count. If there are several outputs from one command, |
|
56 | # execution count. | |
60 | # only the last one is stored. |
|
|||
61 | output_hist = Dict() |
|
57 | output_hist = Dict() | |
62 | # Contains all outputs, in lists of reprs. |
|
58 | # The text/plain repr of outputs. | |
63 |
output_hist_reprs = |
|
59 | output_hist_reprs = Dict() | |
64 |
|
60 | |||
65 | # String holding the path to the history file |
|
61 | # String holding the path to the history file | |
66 | hist_file = Unicode(config=True) |
|
62 | hist_file = Unicode(config=True) | |
@@ -92,11 +88,10 b' class HistoryManager(Configurable):' | |||||
92 | _ii = Unicode(u'') |
|
88 | _ii = Unicode(u'') | |
93 | _iii = Unicode(u'') |
|
89 | _iii = Unicode(u'') | |
94 |
|
90 | |||
95 |
# A |
|
91 | # A regex matching all forms of the exit command, so that we don't store | |
96 |
# the history (it's annoying to rewind the first entry and land on |
|
92 | # them in the history (it's annoying to rewind the first entry and land on | |
97 | # call). |
|
93 | # an exit call). | |
98 | _exit_commands = Instance(set, args=(['Quit', 'quit', 'Exit', 'exit', |
|
94 | _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$") | |
99 | '%Quit', '%quit', '%Exit', '%exit'],)) |
|
|||
100 |
|
95 | |||
101 | def __init__(self, shell, config=None, **traits): |
|
96 | def __init__(self, shell, config=None, **traits): | |
102 | """Create a new history manager associated with a shell instance. |
|
97 | """Create a new history manager associated with a shell instance. | |
@@ -218,9 +213,7 b' class HistoryManager(Configurable):' | |||||
218 | cur = self.db.execute("SELECT session, line, %s FROM %s " %\ |
|
213 | cur = self.db.execute("SELECT session, line, %s FROM %s " %\ | |
219 | (toget, sqlfrom) + sql, params) |
|
214 | (toget, sqlfrom) + sql, params) | |
220 | if output: # Regroup into 3-tuples, and parse JSON |
|
215 | if output: # Regroup into 3-tuples, and parse JSON | |
221 | loads = lambda out: json.loads(out) if out else None |
|
216 | return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur) | |
222 | return ((ses, lin, (inp, loads(out))) \ |
|
|||
223 | for ses, lin, inp, out in cur) |
|
|||
224 | return cur |
|
217 | return cur | |
225 |
|
218 | |||
226 |
|
219 | |||
@@ -383,7 +376,7 b' class HistoryManager(Configurable):' | |||||
383 | source_raw = source_raw.rstrip('\n') |
|
376 | source_raw = source_raw.rstrip('\n') | |
384 |
|
377 | |||
385 | # do not store exit/quit commands |
|
378 | # do not store exit/quit commands | |
386 | if source_raw.strip() in self._exit_commands: |
|
379 | if self._exit_re.match(source_raw.strip()): | |
387 | return |
|
380 | return | |
388 |
|
381 | |||
389 | self.input_hist_parsed.append(source) |
|
382 | self.input_hist_parsed.append(source) | |
@@ -419,9 +412,9 b' class HistoryManager(Configurable):' | |||||
419 | line_num : int |
|
412 | line_num : int | |
420 | The line number from which to save outputs |
|
413 | The line number from which to save outputs | |
421 | """ |
|
414 | """ | |
422 |
if (not self.db_log_output) or not self.output_hist_reprs |
|
415 | if (not self.db_log_output) or (line_num not in self.output_hist_reprs): | |
423 | return |
|
416 | return | |
424 |
output = |
|
417 | output = self.output_hist_reprs[line_num] | |
425 |
|
418 | |||
426 | with self.db_output_cache_lock: |
|
419 | with self.db_output_cache_lock: | |
427 | self.db_output_cache.append((line_num, output)) |
|
420 | self.db_output_cache.append((line_num, output)) | |
@@ -696,7 +689,7 b" def magic_history(self, parameter_s = ''):" | |||||
696 | inline = "\n... ".join(inline.splitlines()) + "\n..." |
|
689 | inline = "\n... ".join(inline.splitlines()) + "\n..." | |
697 | print(inline, file=outfile) |
|
690 | print(inline, file=outfile) | |
698 | if get_output and output: |
|
691 | if get_output and output: | |
699 |
print( |
|
692 | print(output, file=outfile) | |
700 |
|
693 | |||
701 | if close_at_end: |
|
694 | if close_at_end: | |
702 | outfile.close() |
|
695 | outfile.close() |
@@ -2150,12 +2150,9 b' class InteractiveShell(Configurable, Magic):' | |||||
2150 | self.showsyntaxerror() |
|
2150 | self.showsyntaxerror() | |
2151 | self.execution_count += 1 |
|
2151 | self.execution_count += 1 | |
2152 | return None |
|
2152 | return None | |
2153 |
|
||||
2154 | interactivity = 'last' # Last node to be run interactive |
|
|||
2155 | if len(cell.splitlines()) == 1: |
|
|||
2156 | interactivity = 'all' # Single line; run fully interactive |
|
|||
2157 |
|
2153 | |||
2158 |
self.run_ast_nodes(code_ast.body, cell_name, |
|
2154 | self.run_ast_nodes(code_ast.body, cell_name, | |
|
2155 | interactivity="last_expr") | |||
2159 |
|
2156 | |||
2160 | # Execute any registered post-execution functions. |
|
2157 | # Execute any registered post-execution functions. | |
2161 | for func, status in self._post_execute.iteritems(): |
|
2158 | for func, status in self._post_execute.iteritems(): | |
@@ -2175,7 +2172,7 b' class InteractiveShell(Configurable, Magic):' | |||||
2175 | # Each cell is a *single* input, regardless of how many lines it has |
|
2172 | # Each cell is a *single* input, regardless of how many lines it has | |
2176 | self.execution_count += 1 |
|
2173 | self.execution_count += 1 | |
2177 |
|
2174 | |||
2178 | def run_ast_nodes(self, nodelist, cell_name, interactivity='last'): |
|
2175 | def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr'): | |
2179 | """Run a sequence of AST nodes. The execution mode depends on the |
|
2176 | """Run a sequence of AST nodes. The execution mode depends on the | |
2180 | interactivity parameter. |
|
2177 | interactivity parameter. | |
2181 |
|
2178 | |||
@@ -2187,13 +2184,21 b' class InteractiveShell(Configurable, Magic):' | |||||
2187 | Will be passed to the compiler as the filename of the cell. Typically |
|
2184 | Will be passed to the compiler as the filename of the cell. Typically | |
2188 | the value returned by ip.compile.cache(cell). |
|
2185 | the value returned by ip.compile.cache(cell). | |
2189 | interactivity : str |
|
2186 | interactivity : str | |
2190 |
'all', 'last' or 'none', specifying which nodes should be |
|
2187 | 'all', 'last', 'last_expr' or 'none', specifying which nodes should be | |
2191 |
interactively (displaying output from expressions). |
|
2188 | run interactively (displaying output from expressions). 'last_expr' | |
2192 | this parameter will raise a ValueError. |
|
2189 | will run the last node interactively only if it is an expression (i.e. | |
|
2190 | expressions in loops or other blocks are not displayed. Other values | |||
|
2191 | for this parameter will raise a ValueError. | |||
2193 | """ |
|
2192 | """ | |
2194 | if not nodelist: |
|
2193 | if not nodelist: | |
2195 | return |
|
2194 | return | |
2196 |
|
2195 | |||
|
2196 | if interactivity == 'last_expr': | |||
|
2197 | if isinstance(nodelist[-1], ast.Expr): | |||
|
2198 | interactivity = "last" | |||
|
2199 | else: | |||
|
2200 | interactivity = "none" | |||
|
2201 | ||||
2197 | if interactivity == 'none': |
|
2202 | if interactivity == 'none': | |
2198 | to_run_exec, to_run_interactive = nodelist, [] |
|
2203 | to_run_exec, to_run_interactive = nodelist, [] | |
2199 | elif interactivity == 'last': |
|
2204 | elif interactivity == 'last': |
@@ -33,7 +33,7 b' def test_history():' | |||||
33 |
|
33 | |||
34 | ip.history_manager.db_log_output = True |
|
34 | ip.history_manager.db_log_output = True | |
35 | # Doesn't match the input, but we'll just check it's stored. |
|
35 | # Doesn't match the input, but we'll just check it's stored. | |
36 |
ip.history_manager.output_hist_reprs[3] |
|
36 | ip.history_manager.output_hist_reprs[3] = "spam" | |
37 | ip.history_manager.store_output(3) |
|
37 | ip.history_manager.store_output(3) | |
38 |
|
38 | |||
39 | nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist) |
|
39 | nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist) | |
@@ -53,7 +53,7 b' def test_history():' | |||||
53 | # Check get_hist_tail |
|
53 | # Check get_hist_tail | |
54 | gothist = ip.history_manager.get_tail(4, output=True, |
|
54 | gothist = ip.history_manager.get_tail(4, output=True, | |
55 | include_latest=True) |
|
55 | include_latest=True) | |
56 |
expected = [(1, 3, (hist[-1], |
|
56 | expected = [(1, 3, (hist[-1], "spam")), | |
57 | (2, 1, (newcmds[0], None)), |
|
57 | (2, 1, (newcmds[0], None)), | |
58 | (2, 2, (newcmds[1], None)), |
|
58 | (2, 2, (newcmds[1], None)), | |
59 | (2, 3, (newcmds[2], None)),] |
|
59 | (2, 3, (newcmds[2], None)),] | |
@@ -68,7 +68,7 b' def test_history():' | |||||
68 | gothist = ip.history_manager.search("*test*") |
|
68 | gothist = ip.history_manager.search("*test*") | |
69 | nt.assert_equal(list(gothist), [(1,2,hist[1])] ) |
|
69 | nt.assert_equal(list(gothist), [(1,2,hist[1])] ) | |
70 | gothist = ip.history_manager.search("b*", output=True) |
|
70 | gothist = ip.history_manager.search("b*", output=True) | |
71 |
nt.assert_equal(list(gothist), [(1,3,(hist[2], |
|
71 | nt.assert_equal(list(gothist), [(1,3,(hist[2],"spam"))] ) | |
72 |
|
72 | |||
73 | # Cross testing: check that magic %save can get previous session. |
|
73 | # Cross testing: check that magic %save can get previous session. | |
74 | testfilename = os.path.realpath(os.path.join(tmpdir, "test.py")) |
|
74 | testfilename = os.path.realpath(os.path.join(tmpdir, "test.py")) |
General Comments 0
You need to be logged in to leave comments.
Login now