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