Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/IPython/core/magics/history.py: 20%
146 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1"""Implementation of magic functions related to History.
2"""
3#-----------------------------------------------------------------------------
4# Copyright (c) 2012, IPython Development Team.
5#
6# Distributed under the terms of the Modified BSD License.
7#
8# The full license is in the file COPYING.txt, distributed with this software.
9#-----------------------------------------------------------------------------
11#-----------------------------------------------------------------------------
12# Imports
13#-----------------------------------------------------------------------------
15# Stdlib
16import os
17import sys
18from io import open as io_open
19import fnmatch
21# Our own packages
22from IPython.core.error import StdinNotImplementedError
23from IPython.core.magic import Magics, magics_class, line_magic
24from IPython.core.magic_arguments import (argument, magic_arguments,
25 parse_argstring)
26from IPython.testing.skipdoctest import skip_doctest
27from IPython.utils import io
29#-----------------------------------------------------------------------------
30# Magics class implementation
31#-----------------------------------------------------------------------------
34_unspecified = object()
37@magics_class
38class HistoryMagics(Magics):
40 @magic_arguments()
41 @argument(
42 '-n', dest='print_nums', action='store_true', default=False,
43 help="""
44 print line numbers for each input.
45 This feature is only available if numbered prompts are in use.
46 """)
47 @argument(
48 '-o', dest='get_output', action='store_true', default=False,
49 help="also print outputs for each input.")
50 @argument(
51 '-p', dest='pyprompts', action='store_true', default=False,
52 help="""
53 print classic '>>>' python prompts before each input.
54 This is useful for making documentation, and in conjunction
55 with -o, for producing doctest-ready output.
56 """)
57 @argument(
58 '-t', dest='raw', action='store_false', default=True,
59 help="""
60 print the 'translated' history, as IPython understands it.
61 IPython filters your input and converts it all into valid Python
62 source before executing it (things like magics or aliases are turned
63 into function calls, for example). With this option, you'll see the
64 native history instead of the user-entered version: '%%cd /' will be
65 seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
66 """)
67 @argument(
68 '-f', dest='filename',
69 help="""
70 FILENAME: instead of printing the output to the screen, redirect
71 it to the given file. The file is always overwritten, though *when
72 it can*, IPython asks for confirmation first. In particular, running
73 the command 'history -f FILENAME' from the IPython Notebook
74 interface will replace FILENAME even if it already exists *without*
75 confirmation.
76 """)
77 @argument(
78 '-g', dest='pattern', nargs='*', default=None,
79 help="""
80 treat the arg as a glob pattern to search for in (full) history.
81 This includes the saved history (almost all commands ever written).
82 The pattern may contain '?' to match one unknown character and '*'
83 to match any number of unknown characters. Use '%%hist -g' to show
84 full saved history (may be very long).
85 """)
86 @argument(
87 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
88 help="""
89 get the last n lines from all sessions. Specify n as a single
90 arg, or the default is the last 10 lines.
91 """)
92 @argument(
93 '-u', dest='unique', action='store_true',
94 help="""
95 when searching history using `-g`, show only unique history.
96 """)
97 @argument('range', nargs='*')
98 @skip_doctest
99 @line_magic
100 def history(self, parameter_s = ''):
101 """Print input history (_i<n> variables), with most recent last.
103 By default, input history is printed without line numbers so it can be
104 directly pasted into an editor. Use -n to show them.
106 By default, all input history from the current session is displayed.
107 Ranges of history can be indicated using the syntax:
109 ``4``
110 Line 4, current session
111 ``4-6``
112 Lines 4-6, current session
113 ``243/1-5``
114 Lines 1-5, session 243
115 ``~2/7``
116 Line 7, session 2 before current
117 ``~8/1-~6/5``
118 From the first line of 8 sessions ago, to the fifth line of 6
119 sessions ago.
121 Multiple ranges can be entered, separated by spaces
123 The same syntax is used by %macro, %save, %edit, %rerun
125 Examples
126 --------
127 ::
129 In [6]: %history -n 4-6
130 4:a = 12
131 5:print a**2
132 6:%history -n 4-6
134 """
136 args = parse_argstring(self.history, parameter_s)
138 # For brevity
139 history_manager = self.shell.history_manager
141 def _format_lineno(session, line):
142 """Helper function to format line numbers properly."""
143 if session in (0, history_manager.session_number):
144 return str(line)
145 return "%s/%s" % (session, line)
147 # Check if output to specific file was requested.
148 outfname = args.filename
149 if not outfname:
150 outfile = sys.stdout # default
151 # We don't want to close stdout at the end!
152 close_at_end = False
153 else:
154 outfname = os.path.expanduser(outfname)
155 if os.path.exists(outfname):
156 try:
157 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
158 except StdinNotImplementedError:
159 ans = True
160 if not ans:
161 print('Aborting.')
162 return
163 print("Overwriting file.")
164 outfile = io_open(outfname, 'w', encoding='utf-8')
165 close_at_end = True
167 print_nums = args.print_nums
168 get_output = args.get_output
169 pyprompts = args.pyprompts
170 raw = args.raw
172 pattern = None
173 limit = None if args.limit is _unspecified else args.limit
175 range_pattern = False
176 if args.pattern is not None and not args.range:
177 if args.pattern:
178 pattern = "*" + " ".join(args.pattern) + "*"
179 else:
180 pattern = "*"
181 hist = history_manager.search(pattern, raw=raw, output=get_output,
182 n=limit, unique=args.unique)
183 print_nums = True
184 elif args.limit is not _unspecified:
185 n = 10 if limit is None else limit
186 hist = history_manager.get_tail(n, raw=raw, output=get_output)
187 else:
188 if args.pattern:
189 range_pattern = "*" + " ".join(args.pattern) + "*"
190 print_nums = True
191 hist = history_manager.get_range_by_str(
192 " ".join(args.range), raw, get_output
193 )
195 # We could be displaying the entire history, so let's not try to pull
196 # it into a list in memory. Anything that needs more space will just
197 # misalign.
198 width = 4
200 for session, lineno, inline in hist:
201 # Print user history with tabs expanded to 4 spaces. The GUI
202 # clients use hard tabs for easier usability in auto-indented code,
203 # but we want to produce PEP-8 compliant history for safe pasting
204 # into an editor.
205 if get_output:
206 inline, output = inline
207 if range_pattern:
208 if not fnmatch.fnmatch(inline, range_pattern):
209 continue
210 inline = inline.expandtabs(4).rstrip()
212 multiline = "\n" in inline
213 line_sep = '\n' if multiline else ' '
214 if print_nums:
215 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
216 line_sep), file=outfile, end=u'')
217 if pyprompts:
218 print(u">>> ", end=u"", file=outfile)
219 if multiline:
220 inline = "\n... ".join(inline.splitlines()) + "\n..."
221 print(inline, file=outfile)
222 if get_output and output:
223 print(output, file=outfile)
225 if close_at_end:
226 outfile.close()
228 @line_magic
229 def recall(self, arg):
230 r"""Repeat a command, or get command to input line for editing.
232 %recall and %rep are equivalent.
234 - %recall (no arguments):
236 Place a string version of last computation result (stored in the
237 special '_' variable) to the next input prompt. Allows you to create
238 elaborate command lines without using copy-paste::
240 In[1]: l = ["hei", "vaan"]
241 In[2]: "".join(l)
242 Out[2]: heivaan
243 In[3]: %recall
244 In[4]: heivaan_ <== cursor blinking
246 %recall 45
248 Place history line 45 on the next input prompt. Use %hist to find
249 out the number.
251 %recall 1-4
253 Combine the specified lines into one cell, and place it on the next
254 input prompt. See %history for the slice syntax.
256 %recall foo+bar
258 If foo+bar can be evaluated in the user namespace, the result is
259 placed at the next input prompt. Otherwise, the history is searched
260 for lines which contain that substring, and the most recent one is
261 placed at the next input prompt.
262 """
263 if not arg: # Last output
264 self.shell.set_next_input(str(self.shell.user_ns["_"]))
265 return
266 # Get history range
267 histlines = self.shell.history_manager.get_range_by_str(arg)
268 cmd = "\n".join(x[2] for x in histlines)
269 if cmd:
270 self.shell.set_next_input(cmd.rstrip())
271 return
273 try: # Variable in user namespace
274 cmd = str(eval(arg, self.shell.user_ns))
275 except Exception: # Search for term in history
276 histlines = self.shell.history_manager.search("*"+arg+"*")
277 for h in reversed([x[2] for x in histlines]):
278 if 'recall' in h or 'rep' in h:
279 continue
280 self.shell.set_next_input(h.rstrip())
281 return
282 else:
283 self.shell.set_next_input(cmd.rstrip())
284 return
285 print("Couldn't evaluate or find in history:", arg)
287 @line_magic
288 def rerun(self, parameter_s=''):
289 """Re-run previous input
291 By default, you can specify ranges of input history to be repeated
292 (as with %history). With no arguments, it will repeat the last line.
294 Options:
296 -l <n> : Repeat the last n lines of input, not including the
297 current command.
299 -g foo : Repeat the most recent line which contains foo
300 """
301 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
302 if "l" in opts: # Last n lines
303 try:
304 n = int(opts["l"])
305 except ValueError:
306 print("Number of lines must be an integer")
307 return
309 if n == 0:
310 print("Requested 0 last lines - nothing to run")
311 return
312 elif n < 0:
313 print("Number of lines to rerun cannot be negative")
314 return
316 hist = self.shell.history_manager.get_tail(n)
317 elif "g" in opts: # Search
318 p = "*"+opts['g']+"*"
319 hist = list(self.shell.history_manager.search(p))
320 for l in reversed(hist):
321 if "rerun" not in l[2]:
322 hist = [l] # The last match which isn't a %rerun
323 break
324 else:
325 hist = [] # No matches except %rerun
326 elif args: # Specify history ranges
327 hist = self.shell.history_manager.get_range_by_str(args)
328 else: # Last line
329 hist = self.shell.history_manager.get_tail(1)
330 hist = [x[2] for x in hist]
331 if not hist:
332 print("No lines in history match specification")
333 return
334 histlines = "\n".join(hist)
335 print("=== Executing: ===")
336 print(histlines)
337 print("=== Output: ===")
338 self.shell.run_cell("\n".join(hist), store_history=False)