Show More
@@ -162,7 +162,7 b' class HistoryManager(Configurable):' | |||
|
162 | 162 | ## ------------------------------- |
|
163 | 163 | ## Methods for retrieving history: |
|
164 | 164 | ## ------------------------------- |
|
165 |
def _ |
|
|
165 | def _run_sql(self, sql, params, raw=True, output=False): | |
|
166 | 166 | """Prepares and runs an SQL query for the history database. |
|
167 | 167 | |
|
168 | 168 | Parameters |
@@ -171,15 +171,12 b' class HistoryManager(Configurable):' | |||
|
171 | 171 | Any filtering expressions to go after SELECT ... FROM ... |
|
172 | 172 | params : tuple |
|
173 | 173 | Parameters passed to the SQL query (to replace "?") |
|
174 | raw : bool | |
|
175 | If True, get raw input. | |
|
176 | output : bool | |
|
177 | If True, include output where available. | |
|
174 | raw, output : bool | |
|
175 | See :meth:`get_range` | |
|
178 | 176 | |
|
179 | 177 | Returns |
|
180 | 178 | ------- |
|
181 | An iterator over 3-tuples: (session, line_number, command), or if output | |
|
182 | is True, (session, line_number, (command, output)). | |
|
179 | Tuples as :meth:`get_range` | |
|
183 | 180 | """ |
|
184 | 181 | toget = 'source_raw' if raw else 'source' |
|
185 | 182 | sqlfrom = "history" |
@@ -195,41 +192,61 b' class HistoryManager(Configurable):' | |||
|
195 | 192 | return cur |
|
196 | 193 | |
|
197 | 194 | |
|
198 |
def get_ |
|
|
195 | def get_tail(self, n=10, raw=True, output=False, include_latest=False): | |
|
199 | 196 | """Get the last n lines from the history database. |
|
200 | 197 | |
|
201 | If include_latest is False (default), n+1 lines are fetched, and | |
|
202 | the latest one is discarded. This is intended to be used where | |
|
203 | the function is called by a user command, which it should not | |
|
204 | return.""" | |
|
198 | Parameters | |
|
199 | ---------- | |
|
200 | n : int | |
|
201 | The number of lines to get | |
|
202 | raw, output : bool | |
|
203 | See :meth:`get_range` | |
|
204 | include_latest : bool | |
|
205 | If False (default), n+1 lines are fetched, and the latest one | |
|
206 | is discarded. This is intended to be used where the function | |
|
207 | is called by a user command, which it should not return. | |
|
208 | ||
|
209 | Returns | |
|
210 | ------- | |
|
211 | Tuples as :meth:`get_range` | |
|
212 | """ | |
|
205 | 213 | self.writeout_cache() |
|
206 | 214 | if not include_latest: |
|
207 | 215 | n += 1 |
|
208 |
cur = self._ |
|
|
216 | cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?", | |
|
209 | 217 | (n,), raw=raw, output=output) |
|
210 | 218 | if not include_latest: |
|
211 | 219 | return reversed(list(cur)[1:]) |
|
212 | 220 | return reversed(list(cur)) |
|
213 | 221 | |
|
214 |
def |
|
|
222 | def search(self, pattern="*", raw=True, search_raw=True, | |
|
215 | 223 | output=False): |
|
216 | 224 | """Search the database using unix glob-style matching (wildcards |
|
217 | 225 | * and ?). |
|
218 | 226 | |
|
227 | Parameters | |
|
228 | ---------- | |
|
229 | pattern : str | |
|
230 | The wildcarded pattern to match when searching | |
|
231 | search_raw : bool | |
|
232 | If True, search the raw input, otherwise, the parsed input | |
|
233 | raw, output : bool | |
|
234 | See :meth:`get_range` | |
|
235 | ||
|
219 | 236 | Returns |
|
220 | 237 | ------- |
|
221 | An iterator over tuples: (session, line_number, command) | |
|
238 | Tuples as :meth:`get_range` | |
|
222 | 239 | """ |
|
223 | 240 | tosearch = "source_raw" if search_raw else "source" |
|
224 | 241 | if output: |
|
225 | 242 | tosearch = "history." + tosearch |
|
226 | 243 | self.writeout_cache() |
|
227 |
return self._ |
|
|
244 | return self._run_sql("WHERE %s GLOB ?" % tosearch, (pattern,), | |
|
228 | 245 | raw=raw, output=output) |
|
229 | 246 | |
|
230 |
def _get_ |
|
|
247 | def _get_range_session(self, start=1, stop=None, raw=True, output=False): | |
|
231 | 248 | """Get input and output history from the current session. Called by |
|
232 |
get_ |
|
|
249 | get_range, and takes similar parameters.""" | |
|
233 | 250 | input_hist = self.input_hist_raw if raw else self.input_hist_parsed |
|
234 | 251 | |
|
235 | 252 | n = len(input_hist) |
@@ -247,7 +264,7 b' class HistoryManager(Configurable):' | |||
|
247 | 264 | line = input_hist[i] |
|
248 | 265 | yield (0, i, line) |
|
249 | 266 | |
|
250 |
def get_ |
|
|
267 | def get_range(self, session=0, start=1, stop=None, raw=True,output=False): | |
|
251 | 268 | """Retrieve input by session. |
|
252 | 269 | |
|
253 | 270 | Parameters |
@@ -275,7 +292,7 b' class HistoryManager(Configurable):' | |||
|
275 | 292 | (session, line, (input, output)) if output is True. |
|
276 | 293 | """ |
|
277 | 294 | if session == 0 or session==self.session_number: # Current session |
|
278 |
return self._get_ |
|
|
295 | return self._get_range_session(start, stop, raw, output) | |
|
279 | 296 | if session < 0: |
|
280 | 297 | session += self.session_number |
|
281 | 298 | |
@@ -286,14 +303,27 b' class HistoryManager(Configurable):' | |||
|
286 | 303 | lineclause = "line>=?" |
|
287 | 304 | params = (session, start) |
|
288 | 305 | |
|
289 |
return self._ |
|
|
306 | return self._run_sql("WHERE session==? AND %s""" % lineclause, | |
|
290 | 307 | params, raw=raw, output=output) |
|
291 | 308 | |
|
292 |
def get_ |
|
|
309 | def get_range_by_str(self, rangestr, raw=True, output=False): | |
|
293 | 310 | """Get lines of history from a string of ranges, as used by magic |
|
294 |
commands %hist, %save, %macro, etc. |
|
|
311 | commands %hist, %save, %macro, etc. | |
|
312 | ||
|
313 | Parameters | |
|
314 | ---------- | |
|
315 | rangestr : str | |
|
316 | A string specifying ranges, e.g. "5 ~2/1-4". See | |
|
317 | :func:`magic_history` for full details. | |
|
318 | raw, output : bool | |
|
319 | As :meth:`get_range` | |
|
320 | ||
|
321 | Returns | |
|
322 | ------- | |
|
323 | Tuples as :meth:`get_range` | |
|
324 | """ | |
|
295 | 325 | for sess, s, e in extract_hist_ranges(rangestr): |
|
296 |
for line in self.get_ |
|
|
326 | for line in self.get_range(sess, s, e, raw=raw, output=output): | |
|
297 | 327 | yield line |
|
298 | 328 | |
|
299 | 329 | ## ---------------------------- |
@@ -350,7 +380,13 b' class HistoryManager(Configurable):' | |||
|
350 | 380 | def store_output(self, line_num): |
|
351 | 381 | """If database output logging is enabled, this saves all the |
|
352 | 382 | outputs from the indicated prompt number to the database. It's |
|
353 |
called by run_cell after code has been executed. |
|
|
383 | called by run_cell after code has been executed. | |
|
384 | ||
|
385 | Parameters | |
|
386 | ---------- | |
|
387 | line_num : int | |
|
388 | The line number from which to save outputs | |
|
389 | """ | |
|
354 | 390 | if (not self.db_log_output) or not self.output_hist_reprs[line_num]: |
|
355 | 391 | return |
|
356 | 392 | output = json.dumps(self.output_hist_reprs[line_num]) |
@@ -428,11 +464,18 b" def magic_history(self, parameter_s = ''):" | |||
|
428 | 464 | %history n1 n2 -> print inputs between n1 and n2 (n2 not included)\\ |
|
429 | 465 | |
|
430 | 466 | By default, input history is printed without line numbers so it can be |
|
431 | directly pasted into an editor. | |
|
467 | directly pasted into an editor. Use -n to show them. | |
|
468 | ||
|
469 | Ranges of history can be indicated using the syntax: | |
|
470 | 4 : Line 4, current session | |
|
471 | 4-6 : Lines 4-6, current session | |
|
472 | 243/1-5: Lines 1-5, session 243 | |
|
473 | ~2/7 : Line 7, session 2 before current | |
|
474 | ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line | |
|
475 | of 6 sessions ago. | |
|
476 | Multiple ranges can be entered, separated by spaces | |
|
432 | 477 | |
|
433 | With -n, each input's number <n> is shown, and is accessible as the | |
|
434 | automatically generated variable _i<n> as well as In[<n>]. Multi-line | |
|
435 | statements are printed starting at a new line for easy copy/paste. | |
|
478 | The same syntax is used by %macro, %save, %edit, %rerun | |
|
436 | 479 | |
|
437 | 480 | Options: |
|
438 | 481 | |
@@ -516,19 +559,18 b" def magic_history(self, parameter_s = ''):" | |||
|
516 | 559 | |
|
517 | 560 | if 'g' in opts: # Glob search |
|
518 | 561 | pattern = "*" + args + "*" if args else "*" |
|
519 |
hist = history_manager. |
|
|
520 | output=get_output) | |
|
562 | hist = history_manager.search(pattern, raw=raw, output=get_output) | |
|
521 | 563 | elif 'l' in opts: # Get 'tail' |
|
522 | 564 | try: |
|
523 | 565 | n = int(args) |
|
524 | 566 | except ValueError, IndexError: |
|
525 | 567 | n = 10 |
|
526 |
hist = history_manager.get_ |
|
|
568 | hist = history_manager.get_tail(n, raw=raw, output=get_output) | |
|
527 | 569 | else: |
|
528 | 570 | if args: # Get history by ranges |
|
529 |
hist = history_manager.get_ |
|
|
571 | hist = history_manager.get_range_by_str(args, raw, get_output) | |
|
530 | 572 | else: # Just get history for the current session |
|
531 |
hist = history_manager.get_ |
|
|
573 | hist = history_manager.get_range(raw=raw, output=get_output) | |
|
532 | 574 | |
|
533 | 575 | # We could be displaying the entire history, so let's not try to pull it |
|
534 | 576 | # into a list in memory. Anything that needs more space will just misalign. |
@@ -579,10 +621,10 b' def magic_rep(self, arg):' | |||
|
579 | 621 | Place history line 45 on the next input prompt. Use %hist to find |
|
580 | 622 | out the number. |
|
581 | 623 | |
|
582 |
%rep 1-4 |
|
|
624 | %rep 1-4 | |
|
583 | 625 | |
|
584 | 626 | Combine the specified lines into one cell, and place it on the next |
|
585 |
input prompt. |
|
|
627 | input prompt. See %history for the slice syntax. | |
|
586 | 628 | |
|
587 | 629 | %rep foo+bar |
|
588 | 630 | |
@@ -595,7 +637,7 b' def magic_rep(self, arg):' | |||
|
595 | 637 | self.set_next_input(str(self.shell.user_ns["_"])) |
|
596 | 638 | return |
|
597 | 639 | # Get history range |
|
598 |
histlines = self.history_manager.get_ |
|
|
640 | histlines = self.history_manager.get_range_by_str(arg) | |
|
599 | 641 | cmd = "\n".join(x[2] for x in histlines) |
|
600 | 642 | if cmd: |
|
601 | 643 | self.set_next_input(cmd.rstrip()) |
@@ -604,7 +646,7 b' def magic_rep(self, arg):' | |||
|
604 | 646 | try: # Variable in user namespace |
|
605 | 647 | cmd = str(eval(arg, self.shell.user_ns)) |
|
606 | 648 | except Exception: # Search for term in history |
|
607 |
histlines = self.history_manager. |
|
|
649 | histlines = self.history_manager.search("*"+arg+"*") | |
|
608 | 650 | for h in reversed([x[2] for x in histlines]): |
|
609 | 651 | if 'rep' in h: |
|
610 | 652 | continue |
@@ -618,7 +660,7 b" def magic_rerun(self, parameter_s=''):" | |||
|
618 | 660 | """Re-run previous input |
|
619 | 661 | |
|
620 | 662 | By default, you can specify ranges of input history to be repeated |
|
621 | (as with %hist). With no arguments, it will repeat the last line. | |
|
663 | (as with %history). With no arguments, it will repeat the last line. | |
|
622 | 664 | |
|
623 | 665 | Options: |
|
624 | 666 | |
@@ -630,10 +672,10 b" def magic_rerun(self, parameter_s=''):" | |||
|
630 | 672 | opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') |
|
631 | 673 | if "l" in opts: # Last n lines |
|
632 | 674 | n = int(opts['l']) |
|
633 |
hist = self.history_manager.get_ |
|
|
675 | hist = self.history_manager.get_tail(n) | |
|
634 | 676 | elif "g" in opts: # Search |
|
635 | 677 | p = "*"+opts['g']+"*" |
|
636 |
hist = list(self.history_manager. |
|
|
678 | hist = list(self.history_manager.search(p)) | |
|
637 | 679 | for l in reversed(hist): |
|
638 | 680 | if "rerun" not in l[2]: |
|
639 | 681 | hist = [l] # The last match which isn't a %rerun |
@@ -641,9 +683,9 b" def magic_rerun(self, parameter_s=''):" | |||
|
641 | 683 | else: |
|
642 | 684 | hist = [] # No matches except %rerun |
|
643 | 685 | elif args: # Specify history ranges |
|
644 |
hist = self.history_manager.get_ |
|
|
686 | hist = self.history_manager.get_range_by_str(args) | |
|
645 | 687 | else: # Last line |
|
646 |
hist = self.history_manager.get_ |
|
|
688 | hist = self.history_manager.get_tail(1) | |
|
647 | 689 | hist = [x[2] for x in hist] |
|
648 | 690 | if not hist: |
|
649 | 691 | print("No lines in history match specification") |
@@ -1550,7 +1550,7 b' class InteractiveShell(Configurable, Magic):' | |||
|
1550 | 1550 | readline.set_history_length(self.history_length) |
|
1551 | 1551 | |
|
1552 | 1552 | # Load the last 1000 lines from history |
|
1553 |
for _, _, cell in self.history_manager.get_ |
|
|
1553 | for _, _, cell in self.history_manager.get_tail(1000, | |
|
1554 | 1554 | include_latest=True): |
|
1555 | 1555 | if cell.strip(): # Ignore blank lines |
|
1556 | 1556 | for line in cell.splitlines(): |
@@ -186,7 +186,7 b' python-profiler package from non-free.""")' | |||
|
186 | 186 | |
|
187 | 187 | N-M -> include items N..M (closed endpoint).""" |
|
188 | 188 | lines = self.shell.history_manager.\ |
|
189 |
get_ |
|
|
189 | get_range_by_str(range_str, raw=raw) | |
|
190 | 190 | return "\n".join(x for _, _, x in lines) |
|
191 | 191 | |
|
192 | 192 | def arg_err(self,func): |
@@ -1976,9 +1976,7 b' Currently the magic system has the following functions:\\n"""' | |||
|
1976 | 1976 | you had typed them. You just type 'name' at the prompt and the code |
|
1977 | 1977 | executes. |
|
1978 | 1978 | |
|
1979 |
The |
|
|
1980 | numbers n1,...n2' (the endpoint is included). That is, '5-7' means | |
|
1981 | using the lines numbered 5,6 and 7. | |
|
1979 | The syntax for indicating input ranges is described in %history. | |
|
1982 | 1980 | |
|
1983 | 1981 | Note: as a 'hidden' feature, you can also use traditional python slice |
|
1984 | 1982 | notation, where N:M means numbers N through M-1. |
@@ -2048,9 +2046,8 b' Currently the magic system has the following functions:\\n"""' | |||
|
2048 | 2046 | Python. If this option is given, the raw input as typed as the |
|
2049 | 2047 | command line is used instead. |
|
2050 | 2048 | |
|
2051 |
This function uses the same syntax as % |
|
|
2052 | instead of creating a macro it saves the resulting string to the | |
|
2053 | filename you specify. | |
|
2049 | This function uses the same syntax as %history for input ranges, | |
|
2050 | then saves the lines to the filename you specify. | |
|
2054 | 2051 | |
|
2055 | 2052 | It adds a '.py' extension to the file if you don't do so yourself, and |
|
2056 | 2053 | it asks for confirmation before overwriting existing files.""" |
@@ -2139,14 +2136,16 b' Currently the magic system has the following functions:\\n"""' | |||
|
2139 | 2136 | |
|
2140 | 2137 | If arguments are given, the following possibilites exist: |
|
2141 | 2138 | |
|
2142 | - The arguments are numbers or pairs of colon-separated numbers (like | |
|
2143 | 1 4:8 9). These are interpreted as lines of previous input to be | |
|
2144 | loaded into the editor. The syntax is the same of the %macro command. | |
|
2139 | - If the argument is a filename, IPython will load that into the | |
|
2140 | editor. It will execute its contents with execfile() when you exit, | |
|
2141 | loading any code in the file into your interactive namespace. | |
|
2142 | ||
|
2143 | - The arguments are ranges of input history, e.g. "7 ~1/4-6". | |
|
2144 | The syntax is the same as in the %history magic. | |
|
2145 | 2145 | |
|
2146 |
- If the argument |
|
|
2147 | variable and its contents loaded into the editor. You can thus edit | |
|
2148 |
|
|
|
2149 | previous edits). | |
|
2146 | - If the argument is a string variable, its contents are loaded | |
|
2147 | into the editor. You can thus edit any string which contains | |
|
2148 | python code (including the result of previous edits). | |
|
2150 | 2149 | |
|
2151 | 2150 | - If the argument is the name of an object (other than a string), |
|
2152 | 2151 | IPython will try to locate the file where it was defined and open the |
@@ -2163,11 +2162,6 b' Currently the magic system has the following functions:\\n"""' | |||
|
2163 | 2162 | '+NUMBER' parameter necessary for this feature. Good editors like |
|
2164 | 2163 | (X)Emacs, vi, jed, pico and joe all do. |
|
2165 | 2164 | |
|
2166 | - If the argument is not found as a variable, IPython will look for a | |
|
2167 | file with that name (adding .py if necessary) and load it into the | |
|
2168 | editor. It will execute its contents with execfile() when you exit, | |
|
2169 | loading any code in the file into your interactive namespace. | |
|
2170 | ||
|
2171 | 2165 | After executing your code, %edit will return as output the code you |
|
2172 | 2166 | typed in the editor (except when it was an existing file). This way |
|
2173 | 2167 | you can reload the code in further invocations of %edit as a variable, |
@@ -52,14 +52,14 b' def test_history():' | |||
|
52 | 52 | newcmds = ["z=5","class X(object):\n pass", "k='p'"] |
|
53 | 53 | for i, cmd in enumerate(newcmds, start=1): |
|
54 | 54 | ip.history_manager.store_inputs(i, cmd) |
|
55 |
gothist = ip.history_manager.get_ |
|
|
55 | gothist = ip.history_manager.get_range(start=1, stop=4) | |
|
56 | 56 | nt.assert_equal(list(gothist), zip([0,0,0],[1,2,3], newcmds)) |
|
57 | 57 | # Previous session: |
|
58 |
gothist = ip.history_manager.get_ |
|
|
58 | gothist = ip.history_manager.get_range(-1, 1, 4) | |
|
59 | 59 | nt.assert_equal(list(gothist), zip([1,1,1],[1,2,3], hist)) |
|
60 | 60 | |
|
61 | 61 | # Check get_hist_tail |
|
62 |
gothist = ip.history_manager.get_ |
|
|
62 | gothist = ip.history_manager.get_tail(4, output=True, | |
|
63 | 63 | include_latest=True) |
|
64 | 64 | expected = [(1, 3, (hist[-1], ["spam"])), |
|
65 | 65 | (2, 1, (newcmds[0], None)), |
@@ -67,15 +67,15 b' def test_history():' | |||
|
67 | 67 | (2, 3, (newcmds[2], None)),] |
|
68 | 68 | nt.assert_equal(list(gothist), expected) |
|
69 | 69 | |
|
70 |
gothist = ip.history_manager.get_ |
|
|
70 | gothist = ip.history_manager.get_tail(2) | |
|
71 | 71 | expected = [(2, 1, newcmds[0]), |
|
72 | 72 | (2, 2, newcmds[1])] |
|
73 | 73 | nt.assert_equal(list(gothist), expected) |
|
74 | 74 | |
|
75 | 75 | # Check get_hist_search |
|
76 |
gothist = ip.history_manager. |
|
|
76 | gothist = ip.history_manager.search("*test*") | |
|
77 | 77 | nt.assert_equal(list(gothist), [(1,2,hist[1])] ) |
|
78 |
gothist = ip.history_manager. |
|
|
78 | gothist = ip.history_manager.search("b*", output=True) | |
|
79 | 79 | nt.assert_equal(list(gothist), [(1,3,(hist[2],["spam"]))] ) |
|
80 | 80 | |
|
81 | 81 | # Cross testing: check that magic %save can get previous session. |
@@ -314,7 +314,7 b' class Kernel(Configurable):' | |||
|
314 | 314 | n = parent['content']['n'] |
|
315 | 315 | raw = parent['content']['raw'] |
|
316 | 316 | output = parent['content']['output'] |
|
317 |
hist = self.shell.history_manager.get_ |
|
|
317 | hist = self.shell.history_manager.get_tail(n, raw=raw, output=output) | |
|
318 | 318 | content = {'history' : list(hist)} |
|
319 | 319 | msg = self.session.send(self.reply_socket, 'history_tail_reply', |
|
320 | 320 | content, parent, ident) |
General Comments 0
You need to be logged in to leave comments.
Login now