Show More
@@ -124,12 +124,19 b' class HistoryManager(Configurable):' | |||||
124 | name='session_number'""", (self.session_number+1,)) |
|
124 | name='session_number'""", (self.session_number+1,)) | |
125 | self.db.commit() |
|
125 | self.db.commit() | |
126 |
|
126 | |||
127 | def get_hist_tail(self, n=10, raw=True): |
|
127 | def get_hist_tail(self, n=10, raw=True, output=False): | |
128 | """Get the last n lines from the history database.""" |
|
128 | """Get the last n lines from the history database.""" | |
129 | toget = 'source_raw' if raw else 'source' |
|
129 | toget = 'source_raw' if raw else 'source' | |
|
130 | sqlfrom = "history" | |||
|
131 | if output: | |||
|
132 | sqlfrom = "history LEFT JOIN output_history USING (session, line)" | |||
|
133 | toget = "history.%s, output_history.output" % toget | |||
130 | cur = self.db.execute("SELECT session, line, " + toget +\ |
|
134 | cur = self.db.execute("SELECT session, line, " + toget +\ | |
131 |
" FROM |
|
135 | " FROM "+sqlfrom+" ORDER BY session DESC, line DESC LIMIT ?", (n,)) | |
132 |
|
|
136 | hist = reversed(cur.fetchall()) | |
|
137 | if output: | |||
|
138 | return ((ses, lin, (inp, out)) for ses, lin, inp, out in hist) | |||
|
139 | return hist | |||
133 |
|
140 | |||
134 | def get_hist_search(self, pattern="*", raw=True): |
|
141 | def get_hist_search(self, pattern="*", raw=True): | |
135 | """Search the database using unix glob-style matching (wildcards * and |
|
142 | """Search the database using unix glob-style matching (wildcards * and | |
@@ -158,7 +165,7 b' class HistoryManager(Configurable):' | |||||
158 |
|
165 | |||
159 | for i in range(start, stop): |
|
166 | for i in range(start, stop): | |
160 | if output: |
|
167 | if output: | |
161 | line = (input_hist[i], self.output_hist.get(i)) |
|
168 | line = (input_hist[i], repr(self.output_hist.get(i))) | |
162 | else: |
|
169 | else: | |
163 | line = input_hist[i] |
|
170 | line = input_hist[i] | |
164 | yield (0, i, line) |
|
171 | yield (0, i, line) | |
@@ -197,7 +204,7 b' class HistoryManager(Configurable):' | |||||
197 |
|
204 | |||
198 | # Assemble the SQL query: |
|
205 | # Assemble the SQL query: | |
199 | sqlfrom = "history" |
|
206 | sqlfrom = "history" | |
200 |
toget = |
|
207 | toget = 'source_raw' if raw else 'source' | |
201 | if output: |
|
208 | if output: | |
202 | sqlfrom = "history LEFT JOIN output_history USING (session, line)" |
|
209 | sqlfrom = "history LEFT JOIN output_history USING (session, line)" | |
203 | toget = "history.%s, output_history.output" % toget |
|
210 | toget = "history.%s, output_history.output" % toget | |
@@ -208,10 +215,10 b' class HistoryManager(Configurable):' | |||||
208 | lineclause = "line>=?" |
|
215 | lineclause = "line>=?" | |
209 | params = (session, start) |
|
216 | params = (session, start) | |
210 |
|
217 | |||
211 |
cur = self.db.execute("SELECT %s FROM %s WHERE |
|
218 | cur = self.db.execute("""SELECT session, line, %s FROM %s WHERE | |
212 |
|
|
219 | session==? AND %s""" %(toget, sqlfrom, lineclause), params) | |
213 | if output: # Regroup into 3-tuples |
|
220 | if output: # Regroup into 3-tuples | |
214 | return ((ses, lin (inp, out)) for ses, lin, inp, out in cur) |
|
221 | return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur) | |
215 | return cur |
|
222 | return cur | |
216 |
|
223 | |||
217 | def get_hist_from_rangestr(self, rangestr, raw=True, output=False): |
|
224 | def get_hist_from_rangestr(self, rangestr, raw=True, output=False): | |
@@ -278,6 +285,7 b' class HistoryManager(Configurable):' | |||||
278 | self.db.execute("INSERT INTO output_history VALUES (?,?,?)", db_row) |
|
285 | self.db.execute("INSERT INTO output_history VALUES (?,?,?)", db_row) | |
279 |
|
286 | |||
280 | def writeout_cache(self): |
|
287 | def writeout_cache(self): | |
|
288 | #print(self.db_input_cache) | |||
281 | with self.db: |
|
289 | with self.db: | |
282 | self.db.executemany("INSERT INTO history VALUES (?, ?, ?, ?)", |
|
290 | self.db.executemany("INSERT INTO history VALUES (?, ?, ?, ?)", | |
283 | self.db_input_cache) |
|
291 | self.db_input_cache) | |
@@ -295,8 +303,8 b' class HistoryManager(Configurable):' | |||||
295 | elif lr < lp: |
|
303 | elif lr < lp: | |
296 | self.input_hist_parsed[:lp-lr] = [] |
|
304 | self.input_hist_parsed[:lp-lr] = [] | |
297 |
|
305 | |||
298 | def reset(self): |
|
306 | def reset(self, new_session=True): | |
299 | """Clear all histories managed by this object, and start a new |
|
307 | """Clear the current session's history, and (optionally) start a new | |
300 | session.""" |
|
308 | session.""" | |
301 | self.input_hist_parsed[:] = [""] |
|
309 | self.input_hist_parsed[:] = [""] | |
302 | self.input_hist_raw[:] = [""] |
|
310 | self.input_hist_raw[:] = [""] | |
@@ -304,8 +312,9 b' class HistoryManager(Configurable):' | |||||
304 | # The directory history can't be completely empty |
|
312 | # The directory history can't be completely empty | |
305 | self.dir_hist[:] = [os.getcwd()] |
|
313 | self.dir_hist[:] = [os.getcwd()] | |
306 |
|
314 | |||
|
315 | if new_session: | |||
307 | self.writeout_cache() |
|
316 | self.writeout_cache() | |
308 |
self.init_db() # |
|
317 | self.init_db() # Get new session number | |
309 |
|
318 | |||
310 | # To match, e.g. ~5/8-~2/3 |
|
319 | # To match, e.g. ~5/8-~2/3 | |
311 | range_re = re.compile(r""" |
|
320 | range_re = re.compile(r""" | |
@@ -463,7 +472,7 b" def magic_history(self, parameter_s = ''):" | |||||
463 | n = int(args) |
|
472 | n = int(args) | |
464 | except ValueError, IndexError: |
|
473 | except ValueError, IndexError: | |
465 | n = 10 |
|
474 | n = 10 | |
466 | hist = history_manager.get_hist_tail(n, raw=raw) |
|
475 | hist = history_manager.get_hist_tail(n, raw=raw, output=get_output) | |
467 | else: |
|
476 | else: | |
468 | if args: # Get history by ranges |
|
477 | if args: # Get history by ranges | |
469 | hist = history_manager.get_hist_from_rangestr(args, raw, get_output) |
|
478 | hist = history_manager.get_hist_from_rangestr(args, raw, get_output) | |
@@ -471,6 +480,8 b" def magic_history(self, parameter_s = ''):" | |||||
471 | hist = history_manager.get_history(raw=raw, output=get_output) |
|
480 | hist = history_manager.get_history(raw=raw, output=get_output) | |
472 | # Pull hist into a list, so we can get the widest number in it. |
|
481 | # Pull hist into a list, so we can get the widest number in it. | |
473 | hist = list(hist) |
|
482 | hist = list(hist) | |
|
483 | if not hist: | |||
|
484 | return | |||
474 |
|
485 | |||
475 | width = max(len(_format_lineno(s, l)) for s, l, _ in hist) |
|
486 | width = max(len(_format_lineno(s, l)) for s, l, _ in hist) | |
476 |
|
487 | |||
@@ -496,7 +507,7 b" def magic_history(self, parameter_s = ''):" | |||||
496 | inline = "\n... ".join(inline.splitlines()) + "\n..." |
|
507 | inline = "\n... ".join(inline.splitlines()) + "\n..." | |
497 | print(inline, file=outfile) |
|
508 | print(inline, file=outfile) | |
498 | if get_output and output: |
|
509 | if get_output and output: | |
499 |
print( |
|
510 | print(output, file=outfile) | |
500 |
|
511 | |||
501 | if close_at_end: |
|
512 | if close_at_end: | |
502 | outfile.close() |
|
513 | outfile.close() |
@@ -990,14 +990,16 b' class InteractiveShell(Configurable, Magic):' | |||||
990 | # Finally, update the real user's namespace |
|
990 | # Finally, update the real user's namespace | |
991 | self.user_ns.update(ns) |
|
991 | self.user_ns.update(ns) | |
992 |
|
992 | |||
993 | def reset(self): |
|
993 | def reset(self, new_session=True): | |
994 | """Clear all internal namespaces. |
|
994 | """Clear all internal namespaces. | |
995 |
|
995 | |||
996 | Note that this is much more aggressive than %reset, since it clears |
|
996 | Note that this is much more aggressive than %reset, since it clears | |
997 | fully all namespaces, as well as all input/output lists. |
|
997 | fully all namespaces, as well as all input/output lists. | |
|
998 | ||||
|
999 | If new_session is True, a new history session will be opened. | |||
998 | """ |
|
1000 | """ | |
999 | # Clear histories |
|
1001 | # Clear histories | |
1000 | self.history_manager.reset() |
|
1002 | self.history_manager.reset(new_session) | |
1001 |
|
1003 | |||
1002 | # Reset counter used to index all histories |
|
1004 | # Reset counter used to index all histories | |
1003 | self.execution_count = 0 |
|
1005 | self.execution_count = 0 | |
@@ -1266,9 +1268,6 b' class InteractiveShell(Configurable, Magic):' | |||||
1266 | self.reload_history() |
|
1268 | self.reload_history() | |
1267 | return wrapper |
|
1269 | return wrapper | |
1268 |
|
1270 | |||
1269 | def get_history(self, start=1, stop=None, raw=False, output=True): |
|
|||
1270 | return self.history_manager.get_history(start, stop, raw, output) |
|
|||
1271 |
|
||||
1272 |
|
1271 | |||
1273 | #------------------------------------------------------------------------- |
|
1272 | #------------------------------------------------------------------------- | |
1274 | # Things related to exception handling and tracebacks (not debugging) |
|
1273 | # Things related to exception handling and tracebacks (not debugging) | |
@@ -2194,8 +2193,8 b' class InteractiveShell(Configurable, Magic):' | |||||
2194 | magic calls (%magic), special shell access (!cmd), etc. |
|
2193 | magic calls (%magic), special shell access (!cmd), etc. | |
2195 | """ |
|
2194 | """ | |
2196 |
|
2195 | |||
2197 | if isinstance(lines, (list, tuple)): |
|
2196 | if not isinstance(lines, (list, tuple)): | |
2198 |
lines = |
|
2197 | lines = lines.splitlines() | |
2199 |
|
2198 | |||
2200 | if clean: |
|
2199 | if clean: | |
2201 | lines = self._cleanup_ipy_script(lines) |
|
2200 | lines = self._cleanup_ipy_script(lines) | |
@@ -2203,7 +2202,6 b' class InteractiveShell(Configurable, Magic):' | |||||
2203 | # We must start with a clean buffer, in case this is run from an |
|
2202 | # We must start with a clean buffer, in case this is run from an | |
2204 | # interactive IPython session (via a magic, for example). |
|
2203 | # interactive IPython session (via a magic, for example). | |
2205 | self.reset_buffer() |
|
2204 | self.reset_buffer() | |
2206 | lines = lines.splitlines() |
|
|||
2207 |
|
2205 | |||
2208 | # Since we will prefilter all lines, store the user's raw input too |
|
2206 | # Since we will prefilter all lines, store the user's raw input too | |
2209 | # before we apply any transformations |
|
2207 | # before we apply any transformations | |
@@ -2533,7 +2531,7 b' class InteractiveShell(Configurable, Magic):' | |||||
2533 | self.history_manager.writeout_cache() |
|
2531 | self.history_manager.writeout_cache() | |
2534 |
|
2532 | |||
2535 | # Clear all user namespaces to release all references cleanly. |
|
2533 | # Clear all user namespaces to release all references cleanly. | |
2536 | self.reset() |
|
2534 | self.reset(new_session=False) | |
2537 |
|
2535 | |||
2538 | # Run user hooks |
|
2536 | # Run user hooks | |
2539 | self.hooks.shutdown_hook() |
|
2537 | self.hooks.shutdown_hook() |
@@ -157,7 +157,6 b' def test_macro():' | |||||
157 | cmds = ["a=1", "def b():\n return a**2", "print(a,b())"] |
|
157 | cmds = ["a=1", "def b():\n return a**2", "print(a,b())"] | |
158 | for i, cmd in enumerate(cmds, start=1): |
|
158 | for i, cmd in enumerate(cmds, start=1): | |
159 | ip.history_manager.store_inputs(i, cmd) |
|
159 | ip.history_manager.store_inputs(i, cmd) | |
160 | print i, cmd |
|
|||
161 | ip.magic("macro test 1-3") |
|
160 | ip.magic("macro test 1-3") | |
162 | nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n") |
|
161 | nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n") | |
163 |
|
162 |
@@ -158,15 +158,12 b' class IPythonWidget(FrontendWidget):' | |||||
158 | else: |
|
158 | else: | |
159 | super(IPythonWidget, self)._handle_execute_reply(msg) |
|
159 | super(IPythonWidget, self)._handle_execute_reply(msg) | |
160 |
|
160 | |||
161 | def _handle_history_reply(self, msg): |
|
161 | def _handle_history_tail_reply(self, msg): | |
162 |
""" Implemented to handle history replies, which are only supported |
|
162 | """ Implemented to handle history tail replies, which are only supported | |
163 | the IPython kernel. |
|
163 | by the IPython kernel. | |
164 | """ |
|
164 | """ | |
165 |
history_ |
|
165 | history_items = msg['content']['history'] | |
166 | input_history_dict = {} |
|
166 | items = [ line.rstrip() for _, _, line in history_items ] | |
167 | for key,val in history_dict.items(): |
|
|||
168 | input_history_dict[int(key)] = val |
|
|||
169 | items = [ val.rstrip() for _, val in sorted(input_history_dict.items()) ] |
|
|||
170 | self._set_history(items) |
|
167 | self._set_history(items) | |
171 |
|
168 | |||
172 | def _handle_pyout(self, msg): |
|
169 | def _handle_pyout(self, msg): | |
@@ -213,8 +210,7 b' class IPythonWidget(FrontendWidget):' | |||||
213 | """ Reimplemented to make a history request. |
|
210 | """ Reimplemented to make a history request. | |
214 | """ |
|
211 | """ | |
215 | super(IPythonWidget, self)._started_channels() |
|
212 | super(IPythonWidget, self)._started_channels() | |
216 |
self.kernel_manager.xreq_channel.history( |
|
213 | self.kernel_manager.xreq_channel.history_tail(1000) | |
217 | this_session=False) |
|
|||
218 |
|
214 | |||
219 | #--------------------------------------------------------------------------- |
|
215 | #--------------------------------------------------------------------------- | |
220 | # 'ConsoleWidget' public interface |
|
216 | # 'ConsoleWidget' public interface |
@@ -107,7 +107,7 b' class Kernel(Configurable):' | |||||
107 |
|
107 | |||
108 | # Build dict of handlers for message types |
|
108 | # Build dict of handlers for message types | |
109 | msg_types = [ 'execute_request', 'complete_request', |
|
109 | msg_types = [ 'execute_request', 'complete_request', | |
110 | 'object_info_request', 'history_request', |
|
110 | 'object_info_request', 'history_tail_request', | |
111 | 'connect_request', 'shutdown_request'] |
|
111 | 'connect_request', 'shutdown_request'] | |
112 | self.handlers = {} |
|
112 | self.handlers = {} | |
113 | for msg_type in msg_types: |
|
113 | for msg_type in msg_types: | |
@@ -308,12 +308,11 b' class Kernel(Configurable):' | |||||
308 | oinfo, parent, ident) |
|
308 | oinfo, parent, ident) | |
309 | logger.debug(msg) |
|
309 | logger.debug(msg) | |
310 |
|
310 | |||
311 | def history_request(self, ident, parent): |
|
311 | def history_tail_request(self, ident, parent): | |
312 |
# parent['content'] should contain keys " |
|
312 | # parent['content'] should contain keys "n", "raw" and "output" | |
313 | # "this_session". |
|
313 | hist = self.shell.history_manager.get_hist_tail(**parent['content']) | |
314 | hist = self.shell.get_history(**parent['content']) |
|
314 | content = {'history' : list(hist)} | |
315 | content = {'history' : hist} |
|
315 | msg = self.session.send(self.reply_socket, 'history_tail_reply', | |
316 | msg = self.session.send(self.reply_socket, 'history_reply', |
|
|||
317 | content, parent, ident) |
|
316 | content, parent, ident) | |
318 | logger.debug(str(msg)) |
|
317 | logger.debug(str(msg)) | |
319 |
|
318 |
@@ -282,30 +282,24 b' class XReqSocketChannel(ZmqSocketChannel):' | |||||
282 | self._queue_request(msg) |
|
282 | self._queue_request(msg) | |
283 | return msg['header']['msg_id'] |
|
283 | return msg['header']['msg_id'] | |
284 |
|
284 | |||
285 |
def history(self, |
|
285 | def history_tail(self, n=10, raw=True, output=False): | |
286 | """Get the history list. |
|
286 | """Get the history list. | |
287 |
|
287 | |||
288 | Parameters |
|
288 | Parameters | |
289 | ---------- |
|
289 | ---------- | |
290 | index : n or (n1, n2) or None |
|
290 | n : int | |
291 | If n, then the last entries. If a tuple, then all in |
|
291 | The number of lines of history to get. | |
292 | range(n1, n2). If None, then all entries. Raises IndexError if |
|
|||
293 | the format of index is incorrect. |
|
|||
294 | raw : bool |
|
292 | raw : bool | |
295 | If True, return the raw input. |
|
293 | If True, return the raw input. | |
296 | output : bool |
|
294 | output : bool | |
297 | If True, then return the output as well. |
|
295 | If True, then return the output as well. | |
298 | this_session : bool |
|
|||
299 | If True, returns only history from the current session. Otherwise, |
|
|||
300 | includes reloaded history from previous sessions. |
|
|||
301 |
|
296 | |||
302 | Returns |
|
297 | Returns | |
303 | ------- |
|
298 | ------- | |
304 | The msg_id of the message sent. |
|
299 | The msg_id of the message sent. | |
305 | """ |
|
300 | """ | |
306 |
content = dict( |
|
301 | content = dict(n=n, raw=raw, output=output) | |
307 | this_session=this_session) |
|
302 | msg = self.session.msg('history_tail_request', content) | |
308 | msg = self.session.msg('history_request', content) |
|
|||
309 | self._queue_request(msg) |
|
303 | self._queue_request(msg) | |
310 | return msg['header']['msg_id'] |
|
304 | return msg['header']['msg_id'] | |
311 |
|
305 |
General Comments 0
You need to be logged in to leave comments.
Login now