##// END OF EJS Templates
Merge pull request #13385 from nicolaslazo/master...
Matthias Bussonnier -
r27284:08ffcbce merge
parent child Browse files
Show More
@@ -1,658 +1,660
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3
3
4 import argparse
4 import argparse
5 from logging import error
5 from logging import error
6 import io
6 import io
7 import os
7 from pprint import pformat
8 from pprint import pformat
8 import sys
9 import sys
9 from warnings import warn
10 from warnings import warn
10
11
11 from traitlets.utils.importstring import import_item
12 from traitlets.utils.importstring import import_item
12 from IPython.core import magic_arguments, page
13 from IPython.core import magic_arguments, page
13 from IPython.core.error import UsageError
14 from IPython.core.error import UsageError
14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 from IPython.utils.text import format_screen, dedent, indent
16 from IPython.utils.text import format_screen, dedent, indent
16 from IPython.testing.skipdoctest import skip_doctest
17 from IPython.testing.skipdoctest import skip_doctest
17 from IPython.utils.ipstruct import Struct
18 from IPython.utils.ipstruct import Struct
18
19
19
20
20 class MagicsDisplay(object):
21 class MagicsDisplay(object):
21 def __init__(self, magics_manager, ignore=None):
22 def __init__(self, magics_manager, ignore=None):
22 self.ignore = ignore if ignore else []
23 self.ignore = ignore if ignore else []
23 self.magics_manager = magics_manager
24 self.magics_manager = magics_manager
24
25
25 def _lsmagic(self):
26 def _lsmagic(self):
26 """The main implementation of the %lsmagic"""
27 """The main implementation of the %lsmagic"""
27 mesc = magic_escapes['line']
28 mesc = magic_escapes['line']
28 cesc = magic_escapes['cell']
29 cesc = magic_escapes['cell']
29 mman = self.magics_manager
30 mman = self.magics_manager
30 magics = mman.lsmagic()
31 magics = mman.lsmagic()
31 out = ['Available line magics:',
32 out = ['Available line magics:',
32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 '',
34 '',
34 'Available cell magics:',
35 'Available cell magics:',
35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 '',
37 '',
37 mman.auto_status()]
38 mman.auto_status()]
38 return '\n'.join(out)
39 return '\n'.join(out)
39
40
40 def _repr_pretty_(self, p, cycle):
41 def _repr_pretty_(self, p, cycle):
41 p.text(self._lsmagic())
42 p.text(self._lsmagic())
42
43
43 def __str__(self):
44 def __str__(self):
44 return self._lsmagic()
45 return self._lsmagic()
45
46
46 def _jsonable(self):
47 def _jsonable(self):
47 """turn magics dict into jsonable dict of the same structure
48 """turn magics dict into jsonable dict of the same structure
48
49
49 replaces object instances with their class names as strings
50 replaces object instances with their class names as strings
50 """
51 """
51 magic_dict = {}
52 magic_dict = {}
52 mman = self.magics_manager
53 mman = self.magics_manager
53 magics = mman.lsmagic()
54 magics = mman.lsmagic()
54 for key, subdict in magics.items():
55 for key, subdict in magics.items():
55 d = {}
56 d = {}
56 magic_dict[key] = d
57 magic_dict[key] = d
57 for name, obj in subdict.items():
58 for name, obj in subdict.items():
58 try:
59 try:
59 classname = obj.__self__.__class__.__name__
60 classname = obj.__self__.__class__.__name__
60 except AttributeError:
61 except AttributeError:
61 classname = 'Other'
62 classname = 'Other'
62
63
63 d[name] = classname
64 d[name] = classname
64 return magic_dict
65 return magic_dict
65
66
66 def _repr_json_(self):
67 def _repr_json_(self):
67 return self._jsonable()
68 return self._jsonable()
68
69
69
70
70 @magics_class
71 @magics_class
71 class BasicMagics(Magics):
72 class BasicMagics(Magics):
72 """Magics that provide central IPython functionality.
73 """Magics that provide central IPython functionality.
73
74
74 These are various magics that don't fit into specific categories but that
75 These are various magics that don't fit into specific categories but that
75 are all part of the base 'IPython experience'."""
76 are all part of the base 'IPython experience'."""
76
77
77 @skip_doctest
78 @skip_doctest
78 @magic_arguments.magic_arguments()
79 @magic_arguments.magic_arguments()
79 @magic_arguments.argument(
80 @magic_arguments.argument(
80 '-l', '--line', action='store_true',
81 '-l', '--line', action='store_true',
81 help="""Create a line magic alias."""
82 help="""Create a line magic alias."""
82 )
83 )
83 @magic_arguments.argument(
84 @magic_arguments.argument(
84 '-c', '--cell', action='store_true',
85 '-c', '--cell', action='store_true',
85 help="""Create a cell magic alias."""
86 help="""Create a cell magic alias."""
86 )
87 )
87 @magic_arguments.argument(
88 @magic_arguments.argument(
88 'name',
89 'name',
89 help="""Name of the magic to be created."""
90 help="""Name of the magic to be created."""
90 )
91 )
91 @magic_arguments.argument(
92 @magic_arguments.argument(
92 'target',
93 'target',
93 help="""Name of the existing line or cell magic."""
94 help="""Name of the existing line or cell magic."""
94 )
95 )
95 @magic_arguments.argument(
96 @magic_arguments.argument(
96 '-p', '--params', default=None,
97 '-p', '--params', default=None,
97 help="""Parameters passed to the magic function."""
98 help="""Parameters passed to the magic function."""
98 )
99 )
99 @line_magic
100 @line_magic
100 def alias_magic(self, line=''):
101 def alias_magic(self, line=''):
101 """Create an alias for an existing line or cell magic.
102 """Create an alias for an existing line or cell magic.
102
103
103 Examples
104 Examples
104 --------
105 --------
105 ::
106 ::
106
107
107 In [1]: %alias_magic t timeit
108 In [1]: %alias_magic t timeit
108 Created `%t` as an alias for `%timeit`.
109 Created `%t` as an alias for `%timeit`.
109 Created `%%t` as an alias for `%%timeit`.
110 Created `%%t` as an alias for `%%timeit`.
110
111
111 In [2]: %t -n1 pass
112 In [2]: %t -n1 pass
112 1 loops, best of 3: 954 ns per loop
113 1 loops, best of 3: 954 ns per loop
113
114
114 In [3]: %%t -n1
115 In [3]: %%t -n1
115 ...: pass
116 ...: pass
116 ...:
117 ...:
117 1 loops, best of 3: 954 ns per loop
118 1 loops, best of 3: 954 ns per loop
118
119
119 In [4]: %alias_magic --cell whereami pwd
120 In [4]: %alias_magic --cell whereami pwd
120 UsageError: Cell magic function `%%pwd` not found.
121 UsageError: Cell magic function `%%pwd` not found.
121 In [5]: %alias_magic --line whereami pwd
122 In [5]: %alias_magic --line whereami pwd
122 Created `%whereami` as an alias for `%pwd`.
123 Created `%whereami` as an alias for `%pwd`.
123
124
124 In [6]: %whereami
125 In [6]: %whereami
125 Out[6]: u'/home/testuser'
126 Out[6]: u'/home/testuser'
126
127
127 In [7]: %alias_magic h history "-p -l 30" --line
128 In [7]: %alias_magic h history "-p -l 30" --line
128 Created `%h` as an alias for `%history -l 30`.
129 Created `%h` as an alias for `%history -l 30`.
129 """
130 """
130
131
131 args = magic_arguments.parse_argstring(self.alias_magic, line)
132 args = magic_arguments.parse_argstring(self.alias_magic, line)
132 shell = self.shell
133 shell = self.shell
133 mman = self.shell.magics_manager
134 mman = self.shell.magics_manager
134 escs = ''.join(magic_escapes.values())
135 escs = ''.join(magic_escapes.values())
135
136
136 target = args.target.lstrip(escs)
137 target = args.target.lstrip(escs)
137 name = args.name.lstrip(escs)
138 name = args.name.lstrip(escs)
138
139
139 params = args.params
140 params = args.params
140 if (params and
141 if (params and
141 ((params.startswith('"') and params.endswith('"'))
142 ((params.startswith('"') and params.endswith('"'))
142 or (params.startswith("'") and params.endswith("'")))):
143 or (params.startswith("'") and params.endswith("'")))):
143 params = params[1:-1]
144 params = params[1:-1]
144
145
145 # Find the requested magics.
146 # Find the requested magics.
146 m_line = shell.find_magic(target, 'line')
147 m_line = shell.find_magic(target, 'line')
147 m_cell = shell.find_magic(target, 'cell')
148 m_cell = shell.find_magic(target, 'cell')
148 if args.line and m_line is None:
149 if args.line and m_line is None:
149 raise UsageError('Line magic function `%s%s` not found.' %
150 raise UsageError('Line magic function `%s%s` not found.' %
150 (magic_escapes['line'], target))
151 (magic_escapes['line'], target))
151 if args.cell and m_cell is None:
152 if args.cell and m_cell is None:
152 raise UsageError('Cell magic function `%s%s` not found.' %
153 raise UsageError('Cell magic function `%s%s` not found.' %
153 (magic_escapes['cell'], target))
154 (magic_escapes['cell'], target))
154
155
155 # If --line and --cell are not specified, default to the ones
156 # If --line and --cell are not specified, default to the ones
156 # that are available.
157 # that are available.
157 if not args.line and not args.cell:
158 if not args.line and not args.cell:
158 if not m_line and not m_cell:
159 if not m_line and not m_cell:
159 raise UsageError(
160 raise UsageError(
160 'No line or cell magic with name `%s` found.' % target
161 'No line or cell magic with name `%s` found.' % target
161 )
162 )
162 args.line = bool(m_line)
163 args.line = bool(m_line)
163 args.cell = bool(m_cell)
164 args.cell = bool(m_cell)
164
165
165 params_str = "" if params is None else " " + params
166 params_str = "" if params is None else " " + params
166
167
167 if args.line:
168 if args.line:
168 mman.register_alias(name, target, 'line', params)
169 mman.register_alias(name, target, 'line', params)
169 print('Created `%s%s` as an alias for `%s%s%s`.' % (
170 print('Created `%s%s` as an alias for `%s%s%s`.' % (
170 magic_escapes['line'], name,
171 magic_escapes['line'], name,
171 magic_escapes['line'], target, params_str))
172 magic_escapes['line'], target, params_str))
172
173
173 if args.cell:
174 if args.cell:
174 mman.register_alias(name, target, 'cell', params)
175 mman.register_alias(name, target, 'cell', params)
175 print('Created `%s%s` as an alias for `%s%s%s`.' % (
176 print('Created `%s%s` as an alias for `%s%s%s`.' % (
176 magic_escapes['cell'], name,
177 magic_escapes['cell'], name,
177 magic_escapes['cell'], target, params_str))
178 magic_escapes['cell'], target, params_str))
178
179
179 @line_magic
180 @line_magic
180 def lsmagic(self, parameter_s=''):
181 def lsmagic(self, parameter_s=''):
181 """List currently available magic functions."""
182 """List currently available magic functions."""
182 return MagicsDisplay(self.shell.magics_manager, ignore=[])
183 return MagicsDisplay(self.shell.magics_manager, ignore=[])
183
184
184 def _magic_docs(self, brief=False, rest=False):
185 def _magic_docs(self, brief=False, rest=False):
185 """Return docstrings from magic functions."""
186 """Return docstrings from magic functions."""
186 mman = self.shell.magics_manager
187 mman = self.shell.magics_manager
187 docs = mman.lsmagic_docs(brief, missing='No documentation')
188 docs = mman.lsmagic_docs(brief, missing='No documentation')
188
189
189 if rest:
190 if rest:
190 format_string = '**%s%s**::\n\n%s\n\n'
191 format_string = '**%s%s**::\n\n%s\n\n'
191 else:
192 else:
192 format_string = '%s%s:\n%s\n'
193 format_string = '%s%s:\n%s\n'
193
194
194 return ''.join(
195 return ''.join(
195 [format_string % (magic_escapes['line'], fname,
196 [format_string % (magic_escapes['line'], fname,
196 indent(dedent(fndoc)))
197 indent(dedent(fndoc)))
197 for fname, fndoc in sorted(docs['line'].items())]
198 for fname, fndoc in sorted(docs['line'].items())]
198 +
199 +
199 [format_string % (magic_escapes['cell'], fname,
200 [format_string % (magic_escapes['cell'], fname,
200 indent(dedent(fndoc)))
201 indent(dedent(fndoc)))
201 for fname, fndoc in sorted(docs['cell'].items())]
202 for fname, fndoc in sorted(docs['cell'].items())]
202 )
203 )
203
204
204 @line_magic
205 @line_magic
205 def magic(self, parameter_s=''):
206 def magic(self, parameter_s=''):
206 """Print information about the magic function system.
207 """Print information about the magic function system.
207
208
208 Supported formats: -latex, -brief, -rest
209 Supported formats: -latex, -brief, -rest
209 """
210 """
210
211
211 mode = ''
212 mode = ''
212 try:
213 try:
213 mode = parameter_s.split()[0][1:]
214 mode = parameter_s.split()[0][1:]
214 except IndexError:
215 except IndexError:
215 pass
216 pass
216
217
217 brief = (mode == 'brief')
218 brief = (mode == 'brief')
218 rest = (mode == 'rest')
219 rest = (mode == 'rest')
219 magic_docs = self._magic_docs(brief, rest)
220 magic_docs = self._magic_docs(brief, rest)
220
221
221 if mode == 'latex':
222 if mode == 'latex':
222 print(self.format_latex(magic_docs))
223 print(self.format_latex(magic_docs))
223 return
224 return
224 else:
225 else:
225 magic_docs = format_screen(magic_docs)
226 magic_docs = format_screen(magic_docs)
226
227
227 out = ["""
228 out = ["""
228 IPython's 'magic' functions
229 IPython's 'magic' functions
229 ===========================
230 ===========================
230
231
231 The magic function system provides a series of functions which allow you to
232 The magic function system provides a series of functions which allow you to
232 control the behavior of IPython itself, plus a lot of system-type
233 control the behavior of IPython itself, plus a lot of system-type
233 features. There are two kinds of magics, line-oriented and cell-oriented.
234 features. There are two kinds of magics, line-oriented and cell-oriented.
234
235
235 Line magics are prefixed with the % character and work much like OS
236 Line magics are prefixed with the % character and work much like OS
236 command-line calls: they get as an argument the rest of the line, where
237 command-line calls: they get as an argument the rest of the line, where
237 arguments are passed without parentheses or quotes. For example, this will
238 arguments are passed without parentheses or quotes. For example, this will
238 time the given statement::
239 time the given statement::
239
240
240 %timeit range(1000)
241 %timeit range(1000)
241
242
242 Cell magics are prefixed with a double %%, and they are functions that get as
243 Cell magics are prefixed with a double %%, and they are functions that get as
243 an argument not only the rest of the line, but also the lines below it in a
244 an argument not only the rest of the line, but also the lines below it in a
244 separate argument. These magics are called with two arguments: the rest of the
245 separate argument. These magics are called with two arguments: the rest of the
245 call line and the body of the cell, consisting of the lines below the first.
246 call line and the body of the cell, consisting of the lines below the first.
246 For example::
247 For example::
247
248
248 %%timeit x = numpy.random.randn((100, 100))
249 %%timeit x = numpy.random.randn((100, 100))
249 numpy.linalg.svd(x)
250 numpy.linalg.svd(x)
250
251
251 will time the execution of the numpy svd routine, running the assignment of x
252 will time the execution of the numpy svd routine, running the assignment of x
252 as part of the setup phase, which is not timed.
253 as part of the setup phase, which is not timed.
253
254
254 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 input with %% will automatically enter cell mode, and IPython will continue
256 input with %% will automatically enter cell mode, and IPython will continue
256 reading input until a blank line is given. In the notebook, simply type the
257 reading input until a blank line is given. In the notebook, simply type the
257 whole cell as one entity, but keep in mind that the %% escape can only be at
258 whole cell as one entity, but keep in mind that the %% escape can only be at
258 the very start of the cell.
259 the very start of the cell.
259
260
260 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 %automagic function), you don't need to type in the % explicitly for line
262 %automagic function), you don't need to type in the % explicitly for line
262 magics; cell magics always require an explicit '%%' escape. By default,
263 magics; cell magics always require an explicit '%%' escape. By default,
263 IPython ships with automagic on, so you should only rarely need the % escape.
264 IPython ships with automagic on, so you should only rarely need the % escape.
264
265
265 Example: typing '%cd mydir' (without the quotes) changes your working directory
266 Example: typing '%cd mydir' (without the quotes) changes your working directory
266 to 'mydir', if it exists.
267 to 'mydir', if it exists.
267
268
268 For a list of the available magic functions, use %lsmagic. For a description
269 For a list of the available magic functions, use %lsmagic. For a description
269 of any of them, type %magic_name?, e.g. '%cd?'.
270 of any of them, type %magic_name?, e.g. '%cd?'.
270
271
271 Currently the magic system has the following functions:""",
272 Currently the magic system has the following functions:""",
272 magic_docs,
273 magic_docs,
273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 str(self.lsmagic()),
275 str(self.lsmagic()),
275 ]
276 ]
276 page.page('\n'.join(out))
277 page.page('\n'.join(out))
277
278
278
279
279 @line_magic
280 @line_magic
280 def page(self, parameter_s=''):
281 def page(self, parameter_s=''):
281 """Pretty print the object and display it through a pager.
282 """Pretty print the object and display it through a pager.
282
283
283 %page [options] OBJECT
284 %page [options] OBJECT
284
285
285 If no object is given, use _ (last output).
286 If no object is given, use _ (last output).
286
287
287 Options:
288 Options:
288
289
289 -r: page str(object), don't pretty-print it."""
290 -r: page str(object), don't pretty-print it."""
290
291
291 # After a function contributed by Olivier Aubert, slightly modified.
292 # After a function contributed by Olivier Aubert, slightly modified.
292
293
293 # Process options/args
294 # Process options/args
294 opts, args = self.parse_options(parameter_s, 'r')
295 opts, args = self.parse_options(parameter_s, 'r')
295 raw = 'r' in opts
296 raw = 'r' in opts
296
297
297 oname = args and args or '_'
298 oname = args and args or '_'
298 info = self.shell._ofind(oname)
299 info = self.shell._ofind(oname)
299 if info['found']:
300 if info['found']:
300 txt = (raw and str or pformat)( info['obj'] )
301 txt = (raw and str or pformat)( info['obj'] )
301 page.page(txt)
302 page.page(txt)
302 else:
303 else:
303 print('Object `%s` not found' % oname)
304 print('Object `%s` not found' % oname)
304
305
305 @line_magic
306 @line_magic
306 def pprint(self, parameter_s=''):
307 def pprint(self, parameter_s=''):
307 """Toggle pretty printing on/off."""
308 """Toggle pretty printing on/off."""
308 ptformatter = self.shell.display_formatter.formatters['text/plain']
309 ptformatter = self.shell.display_formatter.formatters['text/plain']
309 ptformatter.pprint = bool(1 - ptformatter.pprint)
310 ptformatter.pprint = bool(1 - ptformatter.pprint)
310 print('Pretty printing has been turned',
311 print('Pretty printing has been turned',
311 ['OFF','ON'][ptformatter.pprint])
312 ['OFF','ON'][ptformatter.pprint])
312
313
313 @line_magic
314 @line_magic
314 def colors(self, parameter_s=''):
315 def colors(self, parameter_s=''):
315 """Switch color scheme for prompts, info system and exception handlers.
316 """Switch color scheme for prompts, info system and exception handlers.
316
317
317 Currently implemented schemes: NoColor, Linux, LightBG.
318 Currently implemented schemes: NoColor, Linux, LightBG.
318
319
319 Color scheme names are not case-sensitive.
320 Color scheme names are not case-sensitive.
320
321
321 Examples
322 Examples
322 --------
323 --------
323 To get a plain black and white terminal::
324 To get a plain black and white terminal::
324
325
325 %colors nocolor
326 %colors nocolor
326 """
327 """
327 def color_switch_err(name):
328 def color_switch_err(name):
328 warn('Error changing %s color schemes.\n%s' %
329 warn('Error changing %s color schemes.\n%s' %
329 (name, sys.exc_info()[1]), stacklevel=2)
330 (name, sys.exc_info()[1]), stacklevel=2)
330
331
331
332
332 new_scheme = parameter_s.strip()
333 new_scheme = parameter_s.strip()
333 if not new_scheme:
334 if not new_scheme:
334 raise UsageError(
335 raise UsageError(
335 "%colors: you must specify a color scheme. See '%colors?'")
336 "%colors: you must specify a color scheme. See '%colors?'")
336 # local shortcut
337 # local shortcut
337 shell = self.shell
338 shell = self.shell
338
339
339 # Set shell colour scheme
340 # Set shell colour scheme
340 try:
341 try:
341 shell.colors = new_scheme
342 shell.colors = new_scheme
342 shell.refresh_style()
343 shell.refresh_style()
343 except:
344 except:
344 color_switch_err('shell')
345 color_switch_err('shell')
345
346
346 # Set exception colors
347 # Set exception colors
347 try:
348 try:
348 shell.InteractiveTB.set_colors(scheme = new_scheme)
349 shell.InteractiveTB.set_colors(scheme = new_scheme)
349 shell.SyntaxTB.set_colors(scheme = new_scheme)
350 shell.SyntaxTB.set_colors(scheme = new_scheme)
350 except:
351 except:
351 color_switch_err('exception')
352 color_switch_err('exception')
352
353
353 # Set info (for 'object?') colors
354 # Set info (for 'object?') colors
354 if shell.color_info:
355 if shell.color_info:
355 try:
356 try:
356 shell.inspector.set_active_scheme(new_scheme)
357 shell.inspector.set_active_scheme(new_scheme)
357 except:
358 except:
358 color_switch_err('object inspector')
359 color_switch_err('object inspector')
359 else:
360 else:
360 shell.inspector.set_active_scheme('NoColor')
361 shell.inspector.set_active_scheme('NoColor')
361
362
362 @line_magic
363 @line_magic
363 def xmode(self, parameter_s=''):
364 def xmode(self, parameter_s=''):
364 """Switch modes for the exception handlers.
365 """Switch modes for the exception handlers.
365
366
366 Valid modes: Plain, Context, Verbose, and Minimal.
367 Valid modes: Plain, Context, Verbose, and Minimal.
367
368
368 If called without arguments, acts as a toggle.
369 If called without arguments, acts as a toggle.
369
370
370 When in verbose mode the value --show (and --hide)
371 When in verbose mode the value --show (and --hide)
371 will respectively show (or hide) frames with ``__tracebackhide__ =
372 will respectively show (or hide) frames with ``__tracebackhide__ =
372 True`` value set.
373 True`` value set.
373 """
374 """
374
375
375 def xmode_switch_err(name):
376 def xmode_switch_err(name):
376 warn('Error changing %s exception modes.\n%s' %
377 warn('Error changing %s exception modes.\n%s' %
377 (name,sys.exc_info()[1]))
378 (name,sys.exc_info()[1]))
378
379
379 shell = self.shell
380 shell = self.shell
380 if parameter_s.strip() == "--show":
381 if parameter_s.strip() == "--show":
381 shell.InteractiveTB.skip_hidden = False
382 shell.InteractiveTB.skip_hidden = False
382 return
383 return
383 if parameter_s.strip() == "--hide":
384 if parameter_s.strip() == "--hide":
384 shell.InteractiveTB.skip_hidden = True
385 shell.InteractiveTB.skip_hidden = True
385 return
386 return
386
387
387 new_mode = parameter_s.strip().capitalize()
388 new_mode = parameter_s.strip().capitalize()
388 try:
389 try:
389 shell.InteractiveTB.set_mode(mode=new_mode)
390 shell.InteractiveTB.set_mode(mode=new_mode)
390 print('Exception reporting mode:',shell.InteractiveTB.mode)
391 print('Exception reporting mode:',shell.InteractiveTB.mode)
391 except:
392 except:
392 xmode_switch_err('user')
393 xmode_switch_err('user')
393
394
394 @line_magic
395 @line_magic
395 def quickref(self, arg):
396 def quickref(self, arg):
396 """ Show a quick reference sheet """
397 """ Show a quick reference sheet """
397 from IPython.core.usage import quick_reference
398 from IPython.core.usage import quick_reference
398 qr = quick_reference + self._magic_docs(brief=True)
399 qr = quick_reference + self._magic_docs(brief=True)
399 page.page(qr)
400 page.page(qr)
400
401
401 @line_magic
402 @line_magic
402 def doctest_mode(self, parameter_s=''):
403 def doctest_mode(self, parameter_s=''):
403 """Toggle doctest mode on and off.
404 """Toggle doctest mode on and off.
404
405
405 This mode is intended to make IPython behave as much as possible like a
406 This mode is intended to make IPython behave as much as possible like a
406 plain Python shell, from the perspective of how its prompts, exceptions
407 plain Python shell, from the perspective of how its prompts, exceptions
407 and output look. This makes it easy to copy and paste parts of a
408 and output look. This makes it easy to copy and paste parts of a
408 session into doctests. It does so by:
409 session into doctests. It does so by:
409
410
410 - Changing the prompts to the classic ``>>>`` ones.
411 - Changing the prompts to the classic ``>>>`` ones.
411 - Changing the exception reporting mode to 'Plain'.
412 - Changing the exception reporting mode to 'Plain'.
412 - Disabling pretty-printing of output.
413 - Disabling pretty-printing of output.
413
414
414 Note that IPython also supports the pasting of code snippets that have
415 Note that IPython also supports the pasting of code snippets that have
415 leading '>>>' and '...' prompts in them. This means that you can paste
416 leading '>>>' and '...' prompts in them. This means that you can paste
416 doctests from files or docstrings (even if they have leading
417 doctests from files or docstrings (even if they have leading
417 whitespace), and the code will execute correctly. You can then use
418 whitespace), and the code will execute correctly. You can then use
418 '%history -t' to see the translated history; this will give you the
419 '%history -t' to see the translated history; this will give you the
419 input after removal of all the leading prompts and whitespace, which
420 input after removal of all the leading prompts and whitespace, which
420 can be pasted back into an editor.
421 can be pasted back into an editor.
421
422
422 With these features, you can switch into this mode easily whenever you
423 With these features, you can switch into this mode easily whenever you
423 need to do testing and changes to doctests, without having to leave
424 need to do testing and changes to doctests, without having to leave
424 your existing IPython session.
425 your existing IPython session.
425 """
426 """
426
427
427 # Shorthands
428 # Shorthands
428 shell = self.shell
429 shell = self.shell
429 meta = shell.meta
430 meta = shell.meta
430 disp_formatter = self.shell.display_formatter
431 disp_formatter = self.shell.display_formatter
431 ptformatter = disp_formatter.formatters['text/plain']
432 ptformatter = disp_formatter.formatters['text/plain']
432 # dstore is a data store kept in the instance metadata bag to track any
433 # dstore is a data store kept in the instance metadata bag to track any
433 # changes we make, so we can undo them later.
434 # changes we make, so we can undo them later.
434 dstore = meta.setdefault('doctest_mode',Struct())
435 dstore = meta.setdefault('doctest_mode',Struct())
435 save_dstore = dstore.setdefault
436 save_dstore = dstore.setdefault
436
437
437 # save a few values we'll need to recover later
438 # save a few values we'll need to recover later
438 mode = save_dstore('mode',False)
439 mode = save_dstore('mode',False)
439 save_dstore('rc_pprint',ptformatter.pprint)
440 save_dstore('rc_pprint',ptformatter.pprint)
440 save_dstore('xmode',shell.InteractiveTB.mode)
441 save_dstore('xmode',shell.InteractiveTB.mode)
441 save_dstore('rc_separate_out',shell.separate_out)
442 save_dstore('rc_separate_out',shell.separate_out)
442 save_dstore('rc_separate_out2',shell.separate_out2)
443 save_dstore('rc_separate_out2',shell.separate_out2)
443 save_dstore('rc_separate_in',shell.separate_in)
444 save_dstore('rc_separate_in',shell.separate_in)
444 save_dstore('rc_active_types',disp_formatter.active_types)
445 save_dstore('rc_active_types',disp_formatter.active_types)
445
446
446 if not mode:
447 if not mode:
447 # turn on
448 # turn on
448
449
449 # Prompt separators like plain python
450 # Prompt separators like plain python
450 shell.separate_in = ''
451 shell.separate_in = ''
451 shell.separate_out = ''
452 shell.separate_out = ''
452 shell.separate_out2 = ''
453 shell.separate_out2 = ''
453
454
454
455
455 ptformatter.pprint = False
456 ptformatter.pprint = False
456 disp_formatter.active_types = ['text/plain']
457 disp_formatter.active_types = ['text/plain']
457
458
458 shell.magic('xmode Plain')
459 shell.magic('xmode Plain')
459 else:
460 else:
460 # turn off
461 # turn off
461 shell.separate_in = dstore.rc_separate_in
462 shell.separate_in = dstore.rc_separate_in
462
463
463 shell.separate_out = dstore.rc_separate_out
464 shell.separate_out = dstore.rc_separate_out
464 shell.separate_out2 = dstore.rc_separate_out2
465 shell.separate_out2 = dstore.rc_separate_out2
465
466
466 ptformatter.pprint = dstore.rc_pprint
467 ptformatter.pprint = dstore.rc_pprint
467 disp_formatter.active_types = dstore.rc_active_types
468 disp_formatter.active_types = dstore.rc_active_types
468
469
469 shell.magic('xmode ' + dstore.xmode)
470 shell.magic('xmode ' + dstore.xmode)
470
471
471 # mode here is the state before we switch; switch_doctest_mode takes
472 # mode here is the state before we switch; switch_doctest_mode takes
472 # the mode we're switching to.
473 # the mode we're switching to.
473 shell.switch_doctest_mode(not mode)
474 shell.switch_doctest_mode(not mode)
474
475
475 # Store new mode and inform
476 # Store new mode and inform
476 dstore.mode = bool(not mode)
477 dstore.mode = bool(not mode)
477 mode_label = ['OFF','ON'][dstore.mode]
478 mode_label = ['OFF','ON'][dstore.mode]
478 print('Doctest mode is:', mode_label)
479 print('Doctest mode is:', mode_label)
479
480
480 @line_magic
481 @line_magic
481 def gui(self, parameter_s=''):
482 def gui(self, parameter_s=''):
482 """Enable or disable IPython GUI event loop integration.
483 """Enable or disable IPython GUI event loop integration.
483
484
484 %gui [GUINAME]
485 %gui [GUINAME]
485
486
486 This magic replaces IPython's threaded shells that were activated
487 This magic replaces IPython's threaded shells that were activated
487 using the (pylab/wthread/etc.) command line flags. GUI toolkits
488 using the (pylab/wthread/etc.) command line flags. GUI toolkits
488 can now be enabled at runtime and keyboard
489 can now be enabled at runtime and keyboard
489 interrupts should work without any problems. The following toolkits
490 interrupts should work without any problems. The following toolkits
490 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
491 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
491
492
492 %gui wx # enable wxPython event loop integration
493 %gui wx # enable wxPython event loop integration
493 %gui qt4|qt # enable PyQt4 event loop integration
494 %gui qt4|qt # enable PyQt4 event loop integration
494 %gui qt5 # enable PyQt5 event loop integration
495 %gui qt5 # enable PyQt5 event loop integration
495 %gui gtk # enable PyGTK event loop integration
496 %gui gtk # enable PyGTK event loop integration
496 %gui gtk3 # enable Gtk3 event loop integration
497 %gui gtk3 # enable Gtk3 event loop integration
497 %gui gtk4 # enable Gtk4 event loop integration
498 %gui gtk4 # enable Gtk4 event loop integration
498 %gui tk # enable Tk event loop integration
499 %gui tk # enable Tk event loop integration
499 %gui osx # enable Cocoa event loop integration
500 %gui osx # enable Cocoa event loop integration
500 # (requires %matplotlib 1.1)
501 # (requires %matplotlib 1.1)
501 %gui # disable all event loop integration
502 %gui # disable all event loop integration
502
503
503 WARNING: after any of these has been called you can simply create
504 WARNING: after any of these has been called you can simply create
504 an application object, but DO NOT start the event loop yourself, as
505 an application object, but DO NOT start the event loop yourself, as
505 we have already handled that.
506 we have already handled that.
506 """
507 """
507 opts, arg = self.parse_options(parameter_s, '')
508 opts, arg = self.parse_options(parameter_s, '')
508 if arg=='': arg = None
509 if arg=='': arg = None
509 try:
510 try:
510 return self.shell.enable_gui(arg)
511 return self.shell.enable_gui(arg)
511 except Exception as e:
512 except Exception as e:
512 # print simple error message, rather than traceback if we can't
513 # print simple error message, rather than traceback if we can't
513 # hook up the GUI
514 # hook up the GUI
514 error(str(e))
515 error(str(e))
515
516
516 @skip_doctest
517 @skip_doctest
517 @line_magic
518 @line_magic
518 def precision(self, s=''):
519 def precision(self, s=''):
519 """Set floating point precision for pretty printing.
520 """Set floating point precision for pretty printing.
520
521
521 Can set either integer precision or a format string.
522 Can set either integer precision or a format string.
522
523
523 If numpy has been imported and precision is an int,
524 If numpy has been imported and precision is an int,
524 numpy display precision will also be set, via ``numpy.set_printoptions``.
525 numpy display precision will also be set, via ``numpy.set_printoptions``.
525
526
526 If no argument is given, defaults will be restored.
527 If no argument is given, defaults will be restored.
527
528
528 Examples
529 Examples
529 --------
530 --------
530 ::
531 ::
531
532
532 In [1]: from math import pi
533 In [1]: from math import pi
533
534
534 In [2]: %precision 3
535 In [2]: %precision 3
535 Out[2]: u'%.3f'
536 Out[2]: u'%.3f'
536
537
537 In [3]: pi
538 In [3]: pi
538 Out[3]: 3.142
539 Out[3]: 3.142
539
540
540 In [4]: %precision %i
541 In [4]: %precision %i
541 Out[4]: u'%i'
542 Out[4]: u'%i'
542
543
543 In [5]: pi
544 In [5]: pi
544 Out[5]: 3
545 Out[5]: 3
545
546
546 In [6]: %precision %e
547 In [6]: %precision %e
547 Out[6]: u'%e'
548 Out[6]: u'%e'
548
549
549 In [7]: pi**10
550 In [7]: pi**10
550 Out[7]: 9.364805e+04
551 Out[7]: 9.364805e+04
551
552
552 In [8]: %precision
553 In [8]: %precision
553 Out[8]: u'%r'
554 Out[8]: u'%r'
554
555
555 In [9]: pi**10
556 In [9]: pi**10
556 Out[9]: 93648.047476082982
557 Out[9]: 93648.047476082982
557 """
558 """
558 ptformatter = self.shell.display_formatter.formatters['text/plain']
559 ptformatter = self.shell.display_formatter.formatters['text/plain']
559 ptformatter.float_precision = s
560 ptformatter.float_precision = s
560 return ptformatter.float_format
561 return ptformatter.float_format
561
562
562 @magic_arguments.magic_arguments()
563 @magic_arguments.magic_arguments()
563 @magic_arguments.argument(
564 @magic_arguments.argument(
564 'filename', type=str,
565 'filename', type=str,
565 help='Notebook name or filename'
566 help='Notebook name or filename'
566 )
567 )
567 @line_magic
568 @line_magic
568 def notebook(self, s):
569 def notebook(self, s):
569 """Export and convert IPython notebooks.
570 """Export and convert IPython notebooks.
570
571
571 This function can export the current IPython history to a notebook file.
572 This function can export the current IPython history to a notebook file.
572 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
573 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
573 """
574 """
574 args = magic_arguments.parse_argstring(self.notebook, s)
575 args = magic_arguments.parse_argstring(self.notebook, s)
576 outfname = os.path.expanduser(args.filename)
575
577
576 from nbformat import write, v4
578 from nbformat import write, v4
577
579
578 cells = []
580 cells = []
579 hist = list(self.shell.history_manager.get_range())
581 hist = list(self.shell.history_manager.get_range())
580 if(len(hist)<=1):
582 if(len(hist)<=1):
581 raise ValueError('History is empty, cannot export')
583 raise ValueError('History is empty, cannot export')
582 for session, execution_count, source in hist[:-1]:
584 for session, execution_count, source in hist[:-1]:
583 cells.append(v4.new_code_cell(
585 cells.append(v4.new_code_cell(
584 execution_count=execution_count,
586 execution_count=execution_count,
585 source=source
587 source=source
586 ))
588 ))
587 nb = v4.new_notebook(cells=cells)
589 nb = v4.new_notebook(cells=cells)
588 with io.open(args.filename, 'w', encoding='utf-8') as f:
590 with io.open(outfname, "w", encoding="utf-8") as f:
589 write(nb, f, version=4)
591 write(nb, f, version=4)
590
592
591 @magics_class
593 @magics_class
592 class AsyncMagics(BasicMagics):
594 class AsyncMagics(BasicMagics):
593
595
594 @line_magic
596 @line_magic
595 def autoawait(self, parameter_s):
597 def autoawait(self, parameter_s):
596 """
598 """
597 Allow to change the status of the autoawait option.
599 Allow to change the status of the autoawait option.
598
600
599 This allow you to set a specific asynchronous code runner.
601 This allow you to set a specific asynchronous code runner.
600
602
601 If no value is passed, print the currently used asynchronous integration
603 If no value is passed, print the currently used asynchronous integration
602 and whether it is activated.
604 and whether it is activated.
603
605
604 It can take a number of value evaluated in the following order:
606 It can take a number of value evaluated in the following order:
605
607
606 - False/false/off deactivate autoawait integration
608 - False/false/off deactivate autoawait integration
607 - True/true/on activate autoawait integration using configured default
609 - True/true/on activate autoawait integration using configured default
608 loop
610 loop
609 - asyncio/curio/trio activate autoawait integration and use integration
611 - asyncio/curio/trio activate autoawait integration and use integration
610 with said library.
612 with said library.
611
613
612 - `sync` turn on the pseudo-sync integration (mostly used for
614 - `sync` turn on the pseudo-sync integration (mostly used for
613 `IPython.embed()` which does not run IPython with a real eventloop and
615 `IPython.embed()` which does not run IPython with a real eventloop and
614 deactivate running asynchronous code. Turning on Asynchronous code with
616 deactivate running asynchronous code. Turning on Asynchronous code with
615 the pseudo sync loop is undefined behavior and may lead IPython to crash.
617 the pseudo sync loop is undefined behavior and may lead IPython to crash.
616
618
617 If the passed parameter does not match any of the above and is a python
619 If the passed parameter does not match any of the above and is a python
618 identifier, get said object from user namespace and set it as the
620 identifier, get said object from user namespace and set it as the
619 runner, and activate autoawait.
621 runner, and activate autoawait.
620
622
621 If the object is a fully qualified object name, attempt to import it and
623 If the object is a fully qualified object name, attempt to import it and
622 set it as the runner, and activate autoawait.
624 set it as the runner, and activate autoawait.
623
625
624
626
625 The exact behavior of autoawait is experimental and subject to change
627 The exact behavior of autoawait is experimental and subject to change
626 across version of IPython and Python.
628 across version of IPython and Python.
627 """
629 """
628
630
629 param = parameter_s.strip()
631 param = parameter_s.strip()
630 d = {True: "on", False: "off"}
632 d = {True: "on", False: "off"}
631
633
632 if not param:
634 if not param:
633 print("IPython autoawait is `{}`, and set to use `{}`".format(
635 print("IPython autoawait is `{}`, and set to use `{}`".format(
634 d[self.shell.autoawait],
636 d[self.shell.autoawait],
635 self.shell.loop_runner
637 self.shell.loop_runner
636 ))
638 ))
637 return None
639 return None
638
640
639 if param.lower() in ('false', 'off'):
641 if param.lower() in ('false', 'off'):
640 self.shell.autoawait = False
642 self.shell.autoawait = False
641 return None
643 return None
642 if param.lower() in ('true', 'on'):
644 if param.lower() in ('true', 'on'):
643 self.shell.autoawait = True
645 self.shell.autoawait = True
644 return None
646 return None
645
647
646 if param in self.shell.loop_runner_map:
648 if param in self.shell.loop_runner_map:
647 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
649 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
648 return None
650 return None
649
651
650 if param in self.shell.user_ns :
652 if param in self.shell.user_ns :
651 self.shell.loop_runner = self.shell.user_ns[param]
653 self.shell.loop_runner = self.shell.user_ns[param]
652 self.shell.autoawait = True
654 self.shell.autoawait = True
653 return None
655 return None
654
656
655 runner = import_item(param)
657 runner = import_item(param)
656
658
657 self.shell.loop_runner = runner
659 self.shell.loop_runner = runner
658 self.shell.autoawait = True
660 self.shell.autoawait = True
@@ -1,754 +1,755
1 """Implementation of code management magic functions.
1 """Implementation of code management magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import inspect
16 import inspect
17 import io
17 import io
18 import os
18 import os
19 import re
19 import re
20 import sys
20 import sys
21 import ast
21 import ast
22 from itertools import chain
22 from itertools import chain
23 from urllib.request import Request, urlopen
23 from urllib.request import Request, urlopen
24 from urllib.parse import urlencode
24 from urllib.parse import urlencode
25 from pathlib import Path
25 from pathlib import Path
26
26
27 # Our own packages
27 # Our own packages
28 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
28 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
29 from IPython.core.macro import Macro
29 from IPython.core.macro import Macro
30 from IPython.core.magic import Magics, magics_class, line_magic
30 from IPython.core.magic import Magics, magics_class, line_magic
31 from IPython.core.oinspect import find_file, find_source_lines
31 from IPython.core.oinspect import find_file, find_source_lines
32 from IPython.core.release import version
32 from IPython.core.release import version
33 from IPython.testing.skipdoctest import skip_doctest
33 from IPython.testing.skipdoctest import skip_doctest
34 from IPython.utils.contexts import preserve_keys
34 from IPython.utils.contexts import preserve_keys
35 from IPython.utils.path import get_py_filename
35 from IPython.utils.path import get_py_filename
36 from warnings import warn
36 from warnings import warn
37 from logging import error
37 from logging import error
38 from IPython.utils.text import get_text_list
38 from IPython.utils.text import get_text_list
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Magic implementation classes
41 # Magic implementation classes
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # Used for exception handling in magic_edit
44 # Used for exception handling in magic_edit
45 class MacroToEdit(ValueError): pass
45 class MacroToEdit(ValueError): pass
46
46
47 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
47 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
48
48
49 # To match, e.g. 8-10 1:5 :10 3-
49 # To match, e.g. 8-10 1:5 :10 3-
50 range_re = re.compile(r"""
50 range_re = re.compile(r"""
51 (?P<start>\d+)?
51 (?P<start>\d+)?
52 ((?P<sep>[\-:])
52 ((?P<sep>[\-:])
53 (?P<end>\d+)?)?
53 (?P<end>\d+)?)?
54 $""", re.VERBOSE)
54 $""", re.VERBOSE)
55
55
56
56
57 def extract_code_ranges(ranges_str):
57 def extract_code_ranges(ranges_str):
58 """Turn a string of range for %%load into 2-tuples of (start, stop)
58 """Turn a string of range for %%load into 2-tuples of (start, stop)
59 ready to use as a slice of the content split by lines.
59 ready to use as a slice of the content split by lines.
60
60
61 Examples
61 Examples
62 --------
62 --------
63 list(extract_input_ranges("5-10 2"))
63 list(extract_input_ranges("5-10 2"))
64 [(4, 10), (1, 2)]
64 [(4, 10), (1, 2)]
65 """
65 """
66 for range_str in ranges_str.split():
66 for range_str in ranges_str.split():
67 rmatch = range_re.match(range_str)
67 rmatch = range_re.match(range_str)
68 if not rmatch:
68 if not rmatch:
69 continue
69 continue
70 sep = rmatch.group("sep")
70 sep = rmatch.group("sep")
71 start = rmatch.group("start")
71 start = rmatch.group("start")
72 end = rmatch.group("end")
72 end = rmatch.group("end")
73
73
74 if sep == '-':
74 if sep == '-':
75 start = int(start) - 1 if start else None
75 start = int(start) - 1 if start else None
76 end = int(end) if end else None
76 end = int(end) if end else None
77 elif sep == ':':
77 elif sep == ':':
78 start = int(start) - 1 if start else None
78 start = int(start) - 1 if start else None
79 end = int(end) - 1 if end else None
79 end = int(end) - 1 if end else None
80 else:
80 else:
81 end = int(start)
81 end = int(start)
82 start = int(start) - 1
82 start = int(start) - 1
83 yield (start, end)
83 yield (start, end)
84
84
85
85
86 def extract_symbols(code, symbols):
86 def extract_symbols(code, symbols):
87 """
87 """
88 Return a tuple (blocks, not_found)
88 Return a tuple (blocks, not_found)
89 where ``blocks`` is a list of code fragments
89 where ``blocks`` is a list of code fragments
90 for each symbol parsed from code, and ``not_found`` are
90 for each symbol parsed from code, and ``not_found`` are
91 symbols not found in the code.
91 symbols not found in the code.
92
92
93 For example::
93 For example::
94
94
95 In [1]: code = '''a = 10
95 In [1]: code = '''a = 10
96 ...: def b(): return 42
96 ...: def b(): return 42
97 ...: class A: pass'''
97 ...: class A: pass'''
98
98
99 In [2]: extract_symbols(code, 'A,b,z')
99 In [2]: extract_symbols(code, 'A,b,z')
100 Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z'])
100 Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z'])
101 """
101 """
102 symbols = symbols.split(',')
102 symbols = symbols.split(',')
103
103
104 # this will raise SyntaxError if code isn't valid Python
104 # this will raise SyntaxError if code isn't valid Python
105 py_code = ast.parse(code)
105 py_code = ast.parse(code)
106
106
107 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
107 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
108 code = code.split('\n')
108 code = code.split('\n')
109
109
110 symbols_lines = {}
110 symbols_lines = {}
111
111
112 # we already know the start_lineno of each symbol (marks).
112 # we already know the start_lineno of each symbol (marks).
113 # To find each end_lineno, we traverse in reverse order until each
113 # To find each end_lineno, we traverse in reverse order until each
114 # non-blank line
114 # non-blank line
115 end = len(code)
115 end = len(code)
116 for name, start in reversed(marks):
116 for name, start in reversed(marks):
117 while not code[end - 1].strip():
117 while not code[end - 1].strip():
118 end -= 1
118 end -= 1
119 if name:
119 if name:
120 symbols_lines[name] = (start - 1, end)
120 symbols_lines[name] = (start - 1, end)
121 end = start - 1
121 end = start - 1
122
122
123 # Now symbols_lines is a map
123 # Now symbols_lines is a map
124 # {'symbol_name': (start_lineno, end_lineno), ...}
124 # {'symbol_name': (start_lineno, end_lineno), ...}
125
125
126 # fill a list with chunks of codes for each requested symbol
126 # fill a list with chunks of codes for each requested symbol
127 blocks = []
127 blocks = []
128 not_found = []
128 not_found = []
129 for symbol in symbols:
129 for symbol in symbols:
130 if symbol in symbols_lines:
130 if symbol in symbols_lines:
131 start, end = symbols_lines[symbol]
131 start, end = symbols_lines[symbol]
132 blocks.append('\n'.join(code[start:end]) + '\n')
132 blocks.append('\n'.join(code[start:end]) + '\n')
133 else:
133 else:
134 not_found.append(symbol)
134 not_found.append(symbol)
135
135
136 return blocks, not_found
136 return blocks, not_found
137
137
138 def strip_initial_indent(lines):
138 def strip_initial_indent(lines):
139 """For %load, strip indent from lines until finding an unindented line.
139 """For %load, strip indent from lines until finding an unindented line.
140
140
141 https://github.com/ipython/ipython/issues/9775
141 https://github.com/ipython/ipython/issues/9775
142 """
142 """
143 indent_re = re.compile(r'\s+')
143 indent_re = re.compile(r'\s+')
144
144
145 it = iter(lines)
145 it = iter(lines)
146 first_line = next(it)
146 first_line = next(it)
147 indent_match = indent_re.match(first_line)
147 indent_match = indent_re.match(first_line)
148
148
149 if indent_match:
149 if indent_match:
150 # First line was indented
150 # First line was indented
151 indent = indent_match.group()
151 indent = indent_match.group()
152 yield first_line[len(indent):]
152 yield first_line[len(indent):]
153
153
154 for line in it:
154 for line in it:
155 if line.startswith(indent):
155 if line.startswith(indent):
156 yield line[len(indent):]
156 yield line[len(indent):]
157 else:
157 else:
158 # Less indented than the first line - stop dedenting
158 # Less indented than the first line - stop dedenting
159 yield line
159 yield line
160 break
160 break
161 else:
161 else:
162 yield first_line
162 yield first_line
163
163
164 # Pass the remaining lines through without dedenting
164 # Pass the remaining lines through without dedenting
165 for line in it:
165 for line in it:
166 yield line
166 yield line
167
167
168
168
169 class InteractivelyDefined(Exception):
169 class InteractivelyDefined(Exception):
170 """Exception for interactively defined variable in magic_edit"""
170 """Exception for interactively defined variable in magic_edit"""
171 def __init__(self, index):
171 def __init__(self, index):
172 self.index = index
172 self.index = index
173
173
174
174
175 @magics_class
175 @magics_class
176 class CodeMagics(Magics):
176 class CodeMagics(Magics):
177 """Magics related to code management (loading, saving, editing, ...)."""
177 """Magics related to code management (loading, saving, editing, ...)."""
178
178
179 def __init__(self, *args, **kwargs):
179 def __init__(self, *args, **kwargs):
180 self._knowntemps = set()
180 self._knowntemps = set()
181 super(CodeMagics, self).__init__(*args, **kwargs)
181 super(CodeMagics, self).__init__(*args, **kwargs)
182
182
183 @line_magic
183 @line_magic
184 def save(self, parameter_s=''):
184 def save(self, parameter_s=''):
185 """Save a set of lines or a macro to a given filename.
185 """Save a set of lines or a macro to a given filename.
186
186
187 Usage:\\
187 Usage:\\
188 %save [options] filename [history]
188 %save [options] filename [history]
189
189
190 Options:
190 Options:
191
191
192 -r: use 'raw' input. By default, the 'processed' history is used,
192 -r: use 'raw' input. By default, the 'processed' history is used,
193 so that magics are loaded in their transformed version to valid
193 so that magics are loaded in their transformed version to valid
194 Python. If this option is given, the raw input as typed as the
194 Python. If this option is given, the raw input as typed as the
195 command line is used instead.
195 command line is used instead.
196
196
197 -f: force overwrite. If file exists, %save will prompt for overwrite
197 -f: force overwrite. If file exists, %save will prompt for overwrite
198 unless -f is given.
198 unless -f is given.
199
199
200 -a: append to the file instead of overwriting it.
200 -a: append to the file instead of overwriting it.
201
201
202 The history argument uses the same syntax as %history for input ranges,
202 The history argument uses the same syntax as %history for input ranges,
203 then saves the lines to the filename you specify.
203 then saves the lines to the filename you specify.
204
204
205 If no ranges are specified, saves history of the current session up to
205 If no ranges are specified, saves history of the current session up to
206 this point.
206 this point.
207
207
208 It adds a '.py' extension to the file if you don't do so yourself, and
208 It adds a '.py' extension to the file if you don't do so yourself, and
209 it asks for confirmation before overwriting existing files.
209 it asks for confirmation before overwriting existing files.
210
210
211 If `-r` option is used, the default extension is `.ipy`.
211 If `-r` option is used, the default extension is `.ipy`.
212 """
212 """
213
213
214 opts,args = self.parse_options(parameter_s,'fra',mode='list')
214 opts,args = self.parse_options(parameter_s,'fra',mode='list')
215 if not args:
215 if not args:
216 raise UsageError('Missing filename.')
216 raise UsageError('Missing filename.')
217 raw = 'r' in opts
217 raw = 'r' in opts
218 force = 'f' in opts
218 force = 'f' in opts
219 append = 'a' in opts
219 append = 'a' in opts
220 mode = 'a' if append else 'w'
220 mode = 'a' if append else 'w'
221 ext = '.ipy' if raw else '.py'
221 ext = '.ipy' if raw else '.py'
222 fname, codefrom = args[0], " ".join(args[1:])
222 fname, codefrom = args[0], " ".join(args[1:])
223 if not fname.endswith(('.py','.ipy')):
223 if not fname.endswith(('.py','.ipy')):
224 fname += ext
224 fname += ext
225 fname = os.path.expanduser(fname)
225 file_exists = os.path.isfile(fname)
226 file_exists = os.path.isfile(fname)
226 if file_exists and not force and not append:
227 if file_exists and not force and not append:
227 try:
228 try:
228 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
229 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
229 except StdinNotImplementedError:
230 except StdinNotImplementedError:
230 print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
231 print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
231 return
232 return
232 if not overwrite :
233 if not overwrite :
233 print('Operation cancelled.')
234 print('Operation cancelled.')
234 return
235 return
235 try:
236 try:
236 cmds = self.shell.find_user_code(codefrom,raw)
237 cmds = self.shell.find_user_code(codefrom,raw)
237 except (TypeError, ValueError) as e:
238 except (TypeError, ValueError) as e:
238 print(e.args[0])
239 print(e.args[0])
239 return
240 return
240 with io.open(fname, mode, encoding="utf-8") as f:
241 with io.open(fname, mode, encoding="utf-8") as f:
241 if not file_exists or not append:
242 if not file_exists or not append:
242 f.write("# coding: utf-8\n")
243 f.write("# coding: utf-8\n")
243 f.write(cmds)
244 f.write(cmds)
244 # make sure we end on a newline
245 # make sure we end on a newline
245 if not cmds.endswith('\n'):
246 if not cmds.endswith('\n'):
246 f.write('\n')
247 f.write('\n')
247 print('The following commands were written to file `%s`:' % fname)
248 print('The following commands were written to file `%s`:' % fname)
248 print(cmds)
249 print(cmds)
249
250
250 @line_magic
251 @line_magic
251 def pastebin(self, parameter_s=''):
252 def pastebin(self, parameter_s=''):
252 """Upload code to dpaste.com, returning the URL.
253 """Upload code to dpaste.com, returning the URL.
253
254
254 Usage:\\
255 Usage:\\
255 %pastebin [-d "Custom description"][-e 24] 1-7
256 %pastebin [-d "Custom description"][-e 24] 1-7
256
257
257 The argument can be an input history range, a filename, or the name of a
258 The argument can be an input history range, a filename, or the name of a
258 string or macro.
259 string or macro.
259
260
260 If no arguments are given, uploads the history of this session up to
261 If no arguments are given, uploads the history of this session up to
261 this point.
262 this point.
262
263
263 Options:
264 Options:
264
265
265 -d: Pass a custom description. The default will say
266 -d: Pass a custom description. The default will say
266 "Pasted from IPython".
267 "Pasted from IPython".
267 -e: Pass number of days for the link to be expired.
268 -e: Pass number of days for the link to be expired.
268 The default will be 7 days.
269 The default will be 7 days.
269 """
270 """
270 opts, args = self.parse_options(parameter_s, "d:e:")
271 opts, args = self.parse_options(parameter_s, "d:e:")
271
272
272 try:
273 try:
273 code = self.shell.find_user_code(args)
274 code = self.shell.find_user_code(args)
274 except (ValueError, TypeError) as e:
275 except (ValueError, TypeError) as e:
275 print(e.args[0])
276 print(e.args[0])
276 return
277 return
277
278
278 expiry_days = 7
279 expiry_days = 7
279 try:
280 try:
280 expiry_days = int(opts.get("e", 7))
281 expiry_days = int(opts.get("e", 7))
281 except ValueError as e:
282 except ValueError as e:
282 print(e.args[0].capitalize())
283 print(e.args[0].capitalize())
283 return
284 return
284 if expiry_days < 1 or expiry_days > 365:
285 if expiry_days < 1 or expiry_days > 365:
285 print("Expiry days should be in range of 1 to 365")
286 print("Expiry days should be in range of 1 to 365")
286 return
287 return
287
288
288 post_data = urlencode(
289 post_data = urlencode(
289 {
290 {
290 "title": opts.get("d", "Pasted from IPython"),
291 "title": opts.get("d", "Pasted from IPython"),
291 "syntax": "python",
292 "syntax": "python",
292 "content": code,
293 "content": code,
293 "expiry_days": expiry_days,
294 "expiry_days": expiry_days,
294 }
295 }
295 ).encode("utf-8")
296 ).encode("utf-8")
296
297
297 request = Request(
298 request = Request(
298 "https://dpaste.com/api/v2/",
299 "https://dpaste.com/api/v2/",
299 headers={"User-Agent": "IPython v{}".format(version)},
300 headers={"User-Agent": "IPython v{}".format(version)},
300 )
301 )
301 response = urlopen(request, post_data)
302 response = urlopen(request, post_data)
302 return response.headers.get('Location')
303 return response.headers.get('Location')
303
304
304 @line_magic
305 @line_magic
305 def loadpy(self, arg_s):
306 def loadpy(self, arg_s):
306 """Alias of `%load`
307 """Alias of `%load`
307
308
308 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
309 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
309 extension. So it has been renamed simply into %load. You can look at
310 extension. So it has been renamed simply into %load. You can look at
310 `%load`'s docstring for more info.
311 `%load`'s docstring for more info.
311 """
312 """
312 self.load(arg_s)
313 self.load(arg_s)
313
314
314 @line_magic
315 @line_magic
315 def load(self, arg_s):
316 def load(self, arg_s):
316 """Load code into the current frontend.
317 """Load code into the current frontend.
317
318
318 Usage:\\
319 Usage:\\
319 %load [options] source
320 %load [options] source
320
321
321 where source can be a filename, URL, input history range, macro, or
322 where source can be a filename, URL, input history range, macro, or
322 element in the user namespace
323 element in the user namespace
323
324
324 If no arguments are given, loads the history of this session up to this
325 If no arguments are given, loads the history of this session up to this
325 point.
326 point.
326
327
327 Options:
328 Options:
328
329
329 -r <lines>: Specify lines or ranges of lines to load from the source.
330 -r <lines>: Specify lines or ranges of lines to load from the source.
330 Ranges could be specified as x-y (x..y) or in python-style x:y
331 Ranges could be specified as x-y (x..y) or in python-style x:y
331 (x..(y-1)). Both limits x and y can be left blank (meaning the
332 (x..(y-1)). Both limits x and y can be left blank (meaning the
332 beginning and end of the file, respectively).
333 beginning and end of the file, respectively).
333
334
334 -s <symbols>: Specify function or classes to load from python source.
335 -s <symbols>: Specify function or classes to load from python source.
335
336
336 -y : Don't ask confirmation for loading source above 200 000 characters.
337 -y : Don't ask confirmation for loading source above 200 000 characters.
337
338
338 -n : Include the user's namespace when searching for source code.
339 -n : Include the user's namespace when searching for source code.
339
340
340 This magic command can either take a local filename, a URL, an history
341 This magic command can either take a local filename, a URL, an history
341 range (see %history) or a macro as argument, it will prompt for
342 range (see %history) or a macro as argument, it will prompt for
342 confirmation before loading source with more than 200 000 characters, unless
343 confirmation before loading source with more than 200 000 characters, unless
343 -y flag is passed or if the frontend does not support raw_input::
344 -y flag is passed or if the frontend does not support raw_input::
344
345
345 %load
346 %load
346 %load myscript.py
347 %load myscript.py
347 %load 7-27
348 %load 7-27
348 %load myMacro
349 %load myMacro
349 %load http://www.example.com/myscript.py
350 %load http://www.example.com/myscript.py
350 %load -r 5-10 myscript.py
351 %load -r 5-10 myscript.py
351 %load -r 10-20,30,40: foo.py
352 %load -r 10-20,30,40: foo.py
352 %load -s MyClass,wonder_function myscript.py
353 %load -s MyClass,wonder_function myscript.py
353 %load -n MyClass
354 %load -n MyClass
354 %load -n my_module.wonder_function
355 %load -n my_module.wonder_function
355 """
356 """
356 opts,args = self.parse_options(arg_s,'yns:r:')
357 opts,args = self.parse_options(arg_s,'yns:r:')
357 search_ns = 'n' in opts
358 search_ns = 'n' in opts
358 contents = self.shell.find_user_code(args, search_ns=search_ns)
359 contents = self.shell.find_user_code(args, search_ns=search_ns)
359
360
360 if 's' in opts:
361 if 's' in opts:
361 try:
362 try:
362 blocks, not_found = extract_symbols(contents, opts['s'])
363 blocks, not_found = extract_symbols(contents, opts['s'])
363 except SyntaxError:
364 except SyntaxError:
364 # non python code
365 # non python code
365 error("Unable to parse the input as valid Python code")
366 error("Unable to parse the input as valid Python code")
366 return
367 return
367
368
368 if len(not_found) == 1:
369 if len(not_found) == 1:
369 warn('The symbol `%s` was not found' % not_found[0])
370 warn('The symbol `%s` was not found' % not_found[0])
370 elif len(not_found) > 1:
371 elif len(not_found) > 1:
371 warn('The symbols %s were not found' % get_text_list(not_found,
372 warn('The symbols %s were not found' % get_text_list(not_found,
372 wrap_item_with='`')
373 wrap_item_with='`')
373 )
374 )
374
375
375 contents = '\n'.join(blocks)
376 contents = '\n'.join(blocks)
376
377
377 if 'r' in opts:
378 if 'r' in opts:
378 ranges = opts['r'].replace(',', ' ')
379 ranges = opts['r'].replace(',', ' ')
379 lines = contents.split('\n')
380 lines = contents.split('\n')
380 slices = extract_code_ranges(ranges)
381 slices = extract_code_ranges(ranges)
381 contents = [lines[slice(*slc)] for slc in slices]
382 contents = [lines[slice(*slc)] for slc in slices]
382 contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
383 contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
383
384
384 l = len(contents)
385 l = len(contents)
385
386
386 # 200 000 is ~ 2500 full 80 character lines
387 # 200 000 is ~ 2500 full 80 character lines
387 # so in average, more than 5000 lines
388 # so in average, more than 5000 lines
388 if l > 200000 and 'y' not in opts:
389 if l > 200000 and 'y' not in opts:
389 try:
390 try:
390 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
391 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
391 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
392 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
392 except StdinNotImplementedError:
393 except StdinNotImplementedError:
393 #assume yes if raw input not implemented
394 #assume yes if raw input not implemented
394 ans = True
395 ans = True
395
396
396 if ans is False :
397 if ans is False :
397 print('Operation cancelled.')
398 print('Operation cancelled.')
398 return
399 return
399
400
400 contents = "# %load {}\n".format(arg_s) + contents
401 contents = "# %load {}\n".format(arg_s) + contents
401
402
402 self.shell.set_next_input(contents, replace=True)
403 self.shell.set_next_input(contents, replace=True)
403
404
404 @staticmethod
405 @staticmethod
405 def _find_edit_target(shell, args, opts, last_call):
406 def _find_edit_target(shell, args, opts, last_call):
406 """Utility method used by magic_edit to find what to edit."""
407 """Utility method used by magic_edit to find what to edit."""
407
408
408 def make_filename(arg):
409 def make_filename(arg):
409 "Make a filename from the given args"
410 "Make a filename from the given args"
410 try:
411 try:
411 filename = get_py_filename(arg)
412 filename = get_py_filename(arg)
412 except IOError:
413 except IOError:
413 # If it ends with .py but doesn't already exist, assume we want
414 # If it ends with .py but doesn't already exist, assume we want
414 # a new file.
415 # a new file.
415 if arg.endswith('.py'):
416 if arg.endswith('.py'):
416 filename = arg
417 filename = arg
417 else:
418 else:
418 filename = None
419 filename = None
419 return filename
420 return filename
420
421
421 # Set a few locals from the options for convenience:
422 # Set a few locals from the options for convenience:
422 opts_prev = 'p' in opts
423 opts_prev = 'p' in opts
423 opts_raw = 'r' in opts
424 opts_raw = 'r' in opts
424
425
425 # custom exceptions
426 # custom exceptions
426 class DataIsObject(Exception): pass
427 class DataIsObject(Exception): pass
427
428
428 # Default line number value
429 # Default line number value
429 lineno = opts.get('n',None)
430 lineno = opts.get('n',None)
430
431
431 if opts_prev:
432 if opts_prev:
432 args = '_%s' % last_call[0]
433 args = '_%s' % last_call[0]
433 if args not in shell.user_ns:
434 if args not in shell.user_ns:
434 args = last_call[1]
435 args = last_call[1]
435
436
436 # by default this is done with temp files, except when the given
437 # by default this is done with temp files, except when the given
437 # arg is a filename
438 # arg is a filename
438 use_temp = True
439 use_temp = True
439
440
440 data = ''
441 data = ''
441
442
442 # First, see if the arguments should be a filename.
443 # First, see if the arguments should be a filename.
443 filename = make_filename(args)
444 filename = make_filename(args)
444 if filename:
445 if filename:
445 use_temp = False
446 use_temp = False
446 elif args:
447 elif args:
447 # Mode where user specifies ranges of lines, like in %macro.
448 # Mode where user specifies ranges of lines, like in %macro.
448 data = shell.extract_input_lines(args, opts_raw)
449 data = shell.extract_input_lines(args, opts_raw)
449 if not data:
450 if not data:
450 try:
451 try:
451 # Load the parameter given as a variable. If not a string,
452 # Load the parameter given as a variable. If not a string,
452 # process it as an object instead (below)
453 # process it as an object instead (below)
453
454
454 #print '*** args',args,'type',type(args) # dbg
455 #print '*** args',args,'type',type(args) # dbg
455 data = eval(args, shell.user_ns)
456 data = eval(args, shell.user_ns)
456 if not isinstance(data, str):
457 if not isinstance(data, str):
457 raise DataIsObject
458 raise DataIsObject
458
459
459 except (NameError,SyntaxError):
460 except (NameError,SyntaxError):
460 # given argument is not a variable, try as a filename
461 # given argument is not a variable, try as a filename
461 filename = make_filename(args)
462 filename = make_filename(args)
462 if filename is None:
463 if filename is None:
463 warn("Argument given (%s) can't be found as a variable "
464 warn("Argument given (%s) can't be found as a variable "
464 "or as a filename." % args)
465 "or as a filename." % args)
465 return (None, None, None)
466 return (None, None, None)
466 use_temp = False
467 use_temp = False
467
468
468 except DataIsObject as e:
469 except DataIsObject as e:
469 # macros have a special edit function
470 # macros have a special edit function
470 if isinstance(data, Macro):
471 if isinstance(data, Macro):
471 raise MacroToEdit(data) from e
472 raise MacroToEdit(data) from e
472
473
473 # For objects, try to edit the file where they are defined
474 # For objects, try to edit the file where they are defined
474 filename = find_file(data)
475 filename = find_file(data)
475 if filename:
476 if filename:
476 if 'fakemodule' in filename.lower() and \
477 if 'fakemodule' in filename.lower() and \
477 inspect.isclass(data):
478 inspect.isclass(data):
478 # class created by %edit? Try to find source
479 # class created by %edit? Try to find source
479 # by looking for method definitions instead, the
480 # by looking for method definitions instead, the
480 # __module__ in those classes is FakeModule.
481 # __module__ in those classes is FakeModule.
481 attrs = [getattr(data, aname) for aname in dir(data)]
482 attrs = [getattr(data, aname) for aname in dir(data)]
482 for attr in attrs:
483 for attr in attrs:
483 if not inspect.ismethod(attr):
484 if not inspect.ismethod(attr):
484 continue
485 continue
485 filename = find_file(attr)
486 filename = find_file(attr)
486 if filename and \
487 if filename and \
487 'fakemodule' not in filename.lower():
488 'fakemodule' not in filename.lower():
488 # change the attribute to be the edit
489 # change the attribute to be the edit
489 # target instead
490 # target instead
490 data = attr
491 data = attr
491 break
492 break
492
493
493 m = ipython_input_pat.match(os.path.basename(filename))
494 m = ipython_input_pat.match(os.path.basename(filename))
494 if m:
495 if m:
495 raise InteractivelyDefined(int(m.groups()[0])) from e
496 raise InteractivelyDefined(int(m.groups()[0])) from e
496
497
497 datafile = 1
498 datafile = 1
498 if filename is None:
499 if filename is None:
499 filename = make_filename(args)
500 filename = make_filename(args)
500 datafile = 1
501 datafile = 1
501 if filename is not None:
502 if filename is not None:
502 # only warn about this if we get a real name
503 # only warn about this if we get a real name
503 warn('Could not find file where `%s` is defined.\n'
504 warn('Could not find file where `%s` is defined.\n'
504 'Opening a file named `%s`' % (args, filename))
505 'Opening a file named `%s`' % (args, filename))
505 # Now, make sure we can actually read the source (if it was
506 # Now, make sure we can actually read the source (if it was
506 # in a temp file it's gone by now).
507 # in a temp file it's gone by now).
507 if datafile:
508 if datafile:
508 if lineno is None:
509 if lineno is None:
509 lineno = find_source_lines(data)
510 lineno = find_source_lines(data)
510 if lineno is None:
511 if lineno is None:
511 filename = make_filename(args)
512 filename = make_filename(args)
512 if filename is None:
513 if filename is None:
513 warn('The file where `%s` was defined '
514 warn('The file where `%s` was defined '
514 'cannot be read or found.' % data)
515 'cannot be read or found.' % data)
515 return (None, None, None)
516 return (None, None, None)
516 use_temp = False
517 use_temp = False
517
518
518 if use_temp:
519 if use_temp:
519 filename = shell.mktempfile(data)
520 filename = shell.mktempfile(data)
520 print('IPython will make a temporary file named:',filename)
521 print('IPython will make a temporary file named:',filename)
521
522
522 # use last_call to remember the state of the previous call, but don't
523 # use last_call to remember the state of the previous call, but don't
523 # let it be clobbered by successive '-p' calls.
524 # let it be clobbered by successive '-p' calls.
524 try:
525 try:
525 last_call[0] = shell.displayhook.prompt_count
526 last_call[0] = shell.displayhook.prompt_count
526 if not opts_prev:
527 if not opts_prev:
527 last_call[1] = args
528 last_call[1] = args
528 except:
529 except:
529 pass
530 pass
530
531
531
532
532 return filename, lineno, use_temp
533 return filename, lineno, use_temp
533
534
534 def _edit_macro(self,mname,macro):
535 def _edit_macro(self,mname,macro):
535 """open an editor with the macro data in a file"""
536 """open an editor with the macro data in a file"""
536 filename = self.shell.mktempfile(macro.value)
537 filename = self.shell.mktempfile(macro.value)
537 self.shell.hooks.editor(filename)
538 self.shell.hooks.editor(filename)
538
539
539 # and make a new macro object, to replace the old one
540 # and make a new macro object, to replace the old one
540 mvalue = Path(filename).read_text()
541 mvalue = Path(filename).read_text()
541 self.shell.user_ns[mname] = Macro(mvalue)
542 self.shell.user_ns[mname] = Macro(mvalue)
542
543
543 @skip_doctest
544 @skip_doctest
544 @line_magic
545 @line_magic
545 def edit(self, parameter_s='',last_call=['','']):
546 def edit(self, parameter_s='',last_call=['','']):
546 """Bring up an editor and execute the resulting code.
547 """Bring up an editor and execute the resulting code.
547
548
548 Usage:
549 Usage:
549 %edit [options] [args]
550 %edit [options] [args]
550
551
551 %edit runs IPython's editor hook. The default version of this hook is
552 %edit runs IPython's editor hook. The default version of this hook is
552 set to call the editor specified by your $EDITOR environment variable.
553 set to call the editor specified by your $EDITOR environment variable.
553 If this isn't found, it will default to vi under Linux/Unix and to
554 If this isn't found, it will default to vi under Linux/Unix and to
554 notepad under Windows. See the end of this docstring for how to change
555 notepad under Windows. See the end of this docstring for how to change
555 the editor hook.
556 the editor hook.
556
557
557 You can also set the value of this editor via the
558 You can also set the value of this editor via the
558 ``TerminalInteractiveShell.editor`` option in your configuration file.
559 ``TerminalInteractiveShell.editor`` option in your configuration file.
559 This is useful if you wish to use a different editor from your typical
560 This is useful if you wish to use a different editor from your typical
560 default with IPython (and for Windows users who typically don't set
561 default with IPython (and for Windows users who typically don't set
561 environment variables).
562 environment variables).
562
563
563 This command allows you to conveniently edit multi-line code right in
564 This command allows you to conveniently edit multi-line code right in
564 your IPython session.
565 your IPython session.
565
566
566 If called without arguments, %edit opens up an empty editor with a
567 If called without arguments, %edit opens up an empty editor with a
567 temporary file and will execute the contents of this file when you
568 temporary file and will execute the contents of this file when you
568 close it (don't forget to save it!).
569 close it (don't forget to save it!).
569
570
570
571
571 Options:
572 Options:
572
573
573 -n <number>: open the editor at a specified line number. By default,
574 -n <number>: open the editor at a specified line number. By default,
574 the IPython editor hook uses the unix syntax 'editor +N filename', but
575 the IPython editor hook uses the unix syntax 'editor +N filename', but
575 you can configure this by providing your own modified hook if your
576 you can configure this by providing your own modified hook if your
576 favorite editor supports line-number specifications with a different
577 favorite editor supports line-number specifications with a different
577 syntax.
578 syntax.
578
579
579 -p: this will call the editor with the same data as the previous time
580 -p: this will call the editor with the same data as the previous time
580 it was used, regardless of how long ago (in your current session) it
581 it was used, regardless of how long ago (in your current session) it
581 was.
582 was.
582
583
583 -r: use 'raw' input. This option only applies to input taken from the
584 -r: use 'raw' input. This option only applies to input taken from the
584 user's history. By default, the 'processed' history is used, so that
585 user's history. By default, the 'processed' history is used, so that
585 magics are loaded in their transformed version to valid Python. If
586 magics are loaded in their transformed version to valid Python. If
586 this option is given, the raw input as typed as the command line is
587 this option is given, the raw input as typed as the command line is
587 used instead. When you exit the editor, it will be executed by
588 used instead. When you exit the editor, it will be executed by
588 IPython's own processor.
589 IPython's own processor.
589
590
590 -x: do not execute the edited code immediately upon exit. This is
591 -x: do not execute the edited code immediately upon exit. This is
591 mainly useful if you are editing programs which need to be called with
592 mainly useful if you are editing programs which need to be called with
592 command line arguments, which you can then do using %run.
593 command line arguments, which you can then do using %run.
593
594
594
595
595 Arguments:
596 Arguments:
596
597
597 If arguments are given, the following possibilities exist:
598 If arguments are given, the following possibilities exist:
598
599
599 - If the argument is a filename, IPython will load that into the
600 - If the argument is a filename, IPython will load that into the
600 editor. It will execute its contents with execfile() when you exit,
601 editor. It will execute its contents with execfile() when you exit,
601 loading any code in the file into your interactive namespace.
602 loading any code in the file into your interactive namespace.
602
603
603 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
604 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
604 The syntax is the same as in the %history magic.
605 The syntax is the same as in the %history magic.
605
606
606 - If the argument is a string variable, its contents are loaded
607 - If the argument is a string variable, its contents are loaded
607 into the editor. You can thus edit any string which contains
608 into the editor. You can thus edit any string which contains
608 python code (including the result of previous edits).
609 python code (including the result of previous edits).
609
610
610 - If the argument is the name of an object (other than a string),
611 - If the argument is the name of an object (other than a string),
611 IPython will try to locate the file where it was defined and open the
612 IPython will try to locate the file where it was defined and open the
612 editor at the point where it is defined. You can use `%edit function`
613 editor at the point where it is defined. You can use `%edit function`
613 to load an editor exactly at the point where 'function' is defined,
614 to load an editor exactly at the point where 'function' is defined,
614 edit it and have the file be executed automatically.
615 edit it and have the file be executed automatically.
615
616
616 - If the object is a macro (see %macro for details), this opens up your
617 - If the object is a macro (see %macro for details), this opens up your
617 specified editor with a temporary file containing the macro's data.
618 specified editor with a temporary file containing the macro's data.
618 Upon exit, the macro is reloaded with the contents of the file.
619 Upon exit, the macro is reloaded with the contents of the file.
619
620
620 Note: opening at an exact line is only supported under Unix, and some
621 Note: opening at an exact line is only supported under Unix, and some
621 editors (like kedit and gedit up to Gnome 2.8) do not understand the
622 editors (like kedit and gedit up to Gnome 2.8) do not understand the
622 '+NUMBER' parameter necessary for this feature. Good editors like
623 '+NUMBER' parameter necessary for this feature. Good editors like
623 (X)Emacs, vi, jed, pico and joe all do.
624 (X)Emacs, vi, jed, pico and joe all do.
624
625
625 After executing your code, %edit will return as output the code you
626 After executing your code, %edit will return as output the code you
626 typed in the editor (except when it was an existing file). This way
627 typed in the editor (except when it was an existing file). This way
627 you can reload the code in further invocations of %edit as a variable,
628 you can reload the code in further invocations of %edit as a variable,
628 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
629 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
629 the output.
630 the output.
630
631
631 Note that %edit is also available through the alias %ed.
632 Note that %edit is also available through the alias %ed.
632
633
633 This is an example of creating a simple function inside the editor and
634 This is an example of creating a simple function inside the editor and
634 then modifying it. First, start up the editor::
635 then modifying it. First, start up the editor::
635
636
636 In [1]: edit
637 In [1]: edit
637 Editing... done. Executing edited code...
638 Editing... done. Executing edited code...
638 Out[1]: 'def foo():\\n print "foo() was defined in an editing
639 Out[1]: 'def foo():\\n print "foo() was defined in an editing
639 session"\\n'
640 session"\\n'
640
641
641 We can then call the function foo()::
642 We can then call the function foo()::
642
643
643 In [2]: foo()
644 In [2]: foo()
644 foo() was defined in an editing session
645 foo() was defined in an editing session
645
646
646 Now we edit foo. IPython automatically loads the editor with the
647 Now we edit foo. IPython automatically loads the editor with the
647 (temporary) file where foo() was previously defined::
648 (temporary) file where foo() was previously defined::
648
649
649 In [3]: edit foo
650 In [3]: edit foo
650 Editing... done. Executing edited code...
651 Editing... done. Executing edited code...
651
652
652 And if we call foo() again we get the modified version::
653 And if we call foo() again we get the modified version::
653
654
654 In [4]: foo()
655 In [4]: foo()
655 foo() has now been changed!
656 foo() has now been changed!
656
657
657 Here is an example of how to edit a code snippet successive
658 Here is an example of how to edit a code snippet successive
658 times. First we call the editor::
659 times. First we call the editor::
659
660
660 In [5]: edit
661 In [5]: edit
661 Editing... done. Executing edited code...
662 Editing... done. Executing edited code...
662 hello
663 hello
663 Out[5]: "print 'hello'\\n"
664 Out[5]: "print 'hello'\\n"
664
665
665 Now we call it again with the previous output (stored in _)::
666 Now we call it again with the previous output (stored in _)::
666
667
667 In [6]: edit _
668 In [6]: edit _
668 Editing... done. Executing edited code...
669 Editing... done. Executing edited code...
669 hello world
670 hello world
670 Out[6]: "print 'hello world'\\n"
671 Out[6]: "print 'hello world'\\n"
671
672
672 Now we call it with the output #8 (stored in _8, also as Out[8])::
673 Now we call it with the output #8 (stored in _8, also as Out[8])::
673
674
674 In [7]: edit _8
675 In [7]: edit _8
675 Editing... done. Executing edited code...
676 Editing... done. Executing edited code...
676 hello again
677 hello again
677 Out[7]: "print 'hello again'\\n"
678 Out[7]: "print 'hello again'\\n"
678
679
679
680
680 Changing the default editor hook:
681 Changing the default editor hook:
681
682
682 If you wish to write your own editor hook, you can put it in a
683 If you wish to write your own editor hook, you can put it in a
683 configuration file which you load at startup time. The default hook
684 configuration file which you load at startup time. The default hook
684 is defined in the IPython.core.hooks module, and you can use that as a
685 is defined in the IPython.core.hooks module, and you can use that as a
685 starting example for further modifications. That file also has
686 starting example for further modifications. That file also has
686 general instructions on how to set a new hook for use once you've
687 general instructions on how to set a new hook for use once you've
687 defined it."""
688 defined it."""
688 opts,args = self.parse_options(parameter_s,'prxn:')
689 opts,args = self.parse_options(parameter_s,'prxn:')
689
690
690 try:
691 try:
691 filename, lineno, is_temp = self._find_edit_target(self.shell,
692 filename, lineno, is_temp = self._find_edit_target(self.shell,
692 args, opts, last_call)
693 args, opts, last_call)
693 except MacroToEdit as e:
694 except MacroToEdit as e:
694 self._edit_macro(args, e.args[0])
695 self._edit_macro(args, e.args[0])
695 return
696 return
696 except InteractivelyDefined as e:
697 except InteractivelyDefined as e:
697 print("Editing In[%i]" % e.index)
698 print("Editing In[%i]" % e.index)
698 args = str(e.index)
699 args = str(e.index)
699 filename, lineno, is_temp = self._find_edit_target(self.shell,
700 filename, lineno, is_temp = self._find_edit_target(self.shell,
700 args, opts, last_call)
701 args, opts, last_call)
701 if filename is None:
702 if filename is None:
702 # nothing was found, warnings have already been issued,
703 # nothing was found, warnings have already been issued,
703 # just give up.
704 # just give up.
704 return
705 return
705
706
706 if is_temp:
707 if is_temp:
707 self._knowntemps.add(filename)
708 self._knowntemps.add(filename)
708 elif (filename in self._knowntemps):
709 elif (filename in self._knowntemps):
709 is_temp = True
710 is_temp = True
710
711
711
712
712 # do actual editing here
713 # do actual editing here
713 print('Editing...', end=' ')
714 print('Editing...', end=' ')
714 sys.stdout.flush()
715 sys.stdout.flush()
715 filepath = Path(filename)
716 filepath = Path(filename)
716 try:
717 try:
717 # Quote filenames that may have spaces in them when opening
718 # Quote filenames that may have spaces in them when opening
718 # the editor
719 # the editor
719 quoted = filename = str(filepath.absolute())
720 quoted = filename = str(filepath.absolute())
720 if " " in quoted:
721 if " " in quoted:
721 quoted = "'%s'" % quoted
722 quoted = "'%s'" % quoted
722 self.shell.hooks.editor(quoted, lineno)
723 self.shell.hooks.editor(quoted, lineno)
723 except TryNext:
724 except TryNext:
724 warn('Could not open editor')
725 warn('Could not open editor')
725 return
726 return
726
727
727 # XXX TODO: should this be generalized for all string vars?
728 # XXX TODO: should this be generalized for all string vars?
728 # For now, this is special-cased to blocks created by cpaste
729 # For now, this is special-cased to blocks created by cpaste
729 if args.strip() == "pasted_block":
730 if args.strip() == "pasted_block":
730 self.shell.user_ns["pasted_block"] = filepath.read_text()
731 self.shell.user_ns["pasted_block"] = filepath.read_text()
731
732
732 if 'x' in opts: # -x prevents actual execution
733 if 'x' in opts: # -x prevents actual execution
733 print()
734 print()
734 else:
735 else:
735 print('done. Executing edited code...')
736 print('done. Executing edited code...')
736 with preserve_keys(self.shell.user_ns, '__file__'):
737 with preserve_keys(self.shell.user_ns, '__file__'):
737 if not is_temp:
738 if not is_temp:
738 self.shell.user_ns['__file__'] = filename
739 self.shell.user_ns['__file__'] = filename
739 if 'r' in opts: # Untranslated IPython code
740 if 'r' in opts: # Untranslated IPython code
740 source = filepath.read_text()
741 source = filepath.read_text()
741 self.shell.run_cell(source, store_history=False)
742 self.shell.run_cell(source, store_history=False)
742 else:
743 else:
743 self.shell.safe_execfile(filename, self.shell.user_ns,
744 self.shell.safe_execfile(filename, self.shell.user_ns,
744 self.shell.user_ns)
745 self.shell.user_ns)
745
746
746 if is_temp:
747 if is_temp:
747 try:
748 try:
748 return filepath.read_text()
749 return filepath.read_text()
749 except IOError as msg:
750 except IOError as msg:
750 if Path(msg.filename) == filepath:
751 if Path(msg.filename) == filepath:
751 warn('File not found. Did you forget to save?')
752 warn('File not found. Did you forget to save?')
752 return
753 return
753 else:
754 else:
754 self.shell.showtraceback()
755 self.shell.showtraceback()
@@ -1,337 +1,338
1 """Implementation of magic functions related to History.
1 """Implementation of magic functions related to History.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012, IPython Development Team.
4 # Copyright (c) 2012, IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import os
16 import os
17 import sys
17 import sys
18 from io import open as io_open
18 from io import open as io_open
19 import fnmatch
19 import fnmatch
20
20
21 # Our own packages
21 # Our own packages
22 from IPython.core.error import StdinNotImplementedError
22 from IPython.core.error import StdinNotImplementedError
23 from IPython.core.magic import Magics, magics_class, line_magic
23 from IPython.core.magic import Magics, magics_class, line_magic
24 from IPython.core.magic_arguments import (argument, magic_arguments,
24 from IPython.core.magic_arguments import (argument, magic_arguments,
25 parse_argstring)
25 parse_argstring)
26 from IPython.testing.skipdoctest import skip_doctest
26 from IPython.testing.skipdoctest import skip_doctest
27 from IPython.utils import io
27 from IPython.utils import io
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Magics class implementation
30 # Magics class implementation
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33
33
34 _unspecified = object()
34 _unspecified = object()
35
35
36
36
37 @magics_class
37 @magics_class
38 class HistoryMagics(Magics):
38 class HistoryMagics(Magics):
39
39
40 @magic_arguments()
40 @magic_arguments()
41 @argument(
41 @argument(
42 '-n', dest='print_nums', action='store_true', default=False,
42 '-n', dest='print_nums', action='store_true', default=False,
43 help="""
43 help="""
44 print line numbers for each input.
44 print line numbers for each input.
45 This feature is only available if numbered prompts are in use.
45 This feature is only available if numbered prompts are in use.
46 """)
46 """)
47 @argument(
47 @argument(
48 '-o', dest='get_output', action='store_true', default=False,
48 '-o', dest='get_output', action='store_true', default=False,
49 help="also print outputs for each input.")
49 help="also print outputs for each input.")
50 @argument(
50 @argument(
51 '-p', dest='pyprompts', action='store_true', default=False,
51 '-p', dest='pyprompts', action='store_true', default=False,
52 help="""
52 help="""
53 print classic '>>>' python prompts before each input.
53 print classic '>>>' python prompts before each input.
54 This is useful for making documentation, and in conjunction
54 This is useful for making documentation, and in conjunction
55 with -o, for producing doctest-ready output.
55 with -o, for producing doctest-ready output.
56 """)
56 """)
57 @argument(
57 @argument(
58 '-t', dest='raw', action='store_false', default=True,
58 '-t', dest='raw', action='store_false', default=True,
59 help="""
59 help="""
60 print the 'translated' history, as IPython understands it.
60 print the 'translated' history, as IPython understands it.
61 IPython filters your input and converts it all into valid Python
61 IPython filters your input and converts it all into valid Python
62 source before executing it (things like magics or aliases are turned
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
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
64 native history instead of the user-entered version: '%%cd /' will be
65 seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
65 seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
66 """)
66 """)
67 @argument(
67 @argument(
68 '-f', dest='filename',
68 '-f', dest='filename',
69 help="""
69 help="""
70 FILENAME: instead of printing the output to the screen, redirect
70 FILENAME: instead of printing the output to the screen, redirect
71 it to the given file. The file is always overwritten, though *when
71 it to the given file. The file is always overwritten, though *when
72 it can*, IPython asks for confirmation first. In particular, running
72 it can*, IPython asks for confirmation first. In particular, running
73 the command 'history -f FILENAME' from the IPython Notebook
73 the command 'history -f FILENAME' from the IPython Notebook
74 interface will replace FILENAME even if it already exists *without*
74 interface will replace FILENAME even if it already exists *without*
75 confirmation.
75 confirmation.
76 """)
76 """)
77 @argument(
77 @argument(
78 '-g', dest='pattern', nargs='*', default=None,
78 '-g', dest='pattern', nargs='*', default=None,
79 help="""
79 help="""
80 treat the arg as a glob pattern to search for in (full) history.
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).
81 This includes the saved history (almost all commands ever written).
82 The pattern may contain '?' to match one unknown character and '*'
82 The pattern may contain '?' to match one unknown character and '*'
83 to match any number of unknown characters. Use '%%hist -g' to show
83 to match any number of unknown characters. Use '%%hist -g' to show
84 full saved history (may be very long).
84 full saved history (may be very long).
85 """)
85 """)
86 @argument(
86 @argument(
87 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
87 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
88 help="""
88 help="""
89 get the last n lines from all sessions. Specify n as a single
89 get the last n lines from all sessions. Specify n as a single
90 arg, or the default is the last 10 lines.
90 arg, or the default is the last 10 lines.
91 """)
91 """)
92 @argument(
92 @argument(
93 '-u', dest='unique', action='store_true',
93 '-u', dest='unique', action='store_true',
94 help="""
94 help="""
95 when searching history using `-g`, show only unique history.
95 when searching history using `-g`, show only unique history.
96 """)
96 """)
97 @argument('range', nargs='*')
97 @argument('range', nargs='*')
98 @skip_doctest
98 @skip_doctest
99 @line_magic
99 @line_magic
100 def history(self, parameter_s = ''):
100 def history(self, parameter_s = ''):
101 """Print input history (_i<n> variables), with most recent last.
101 """Print input history (_i<n> variables), with most recent last.
102
102
103 By default, input history is printed without line numbers so it can be
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.
104 directly pasted into an editor. Use -n to show them.
105
105
106 By default, all input history from the current session is displayed.
106 By default, all input history from the current session is displayed.
107 Ranges of history can be indicated using the syntax:
107 Ranges of history can be indicated using the syntax:
108
108
109 ``4``
109 ``4``
110 Line 4, current session
110 Line 4, current session
111 ``4-6``
111 ``4-6``
112 Lines 4-6, current session
112 Lines 4-6, current session
113 ``243/1-5``
113 ``243/1-5``
114 Lines 1-5, session 243
114 Lines 1-5, session 243
115 ``~2/7``
115 ``~2/7``
116 Line 7, session 2 before current
116 Line 7, session 2 before current
117 ``~8/1-~6/5``
117 ``~8/1-~6/5``
118 From the first line of 8 sessions ago, to the fifth line of 6
118 From the first line of 8 sessions ago, to the fifth line of 6
119 sessions ago.
119 sessions ago.
120
120
121 Multiple ranges can be entered, separated by spaces
121 Multiple ranges can be entered, separated by spaces
122
122
123 The same syntax is used by %macro, %save, %edit, %rerun
123 The same syntax is used by %macro, %save, %edit, %rerun
124
124
125 Examples
125 Examples
126 --------
126 --------
127 ::
127 ::
128
128
129 In [6]: %history -n 4-6
129 In [6]: %history -n 4-6
130 4:a = 12
130 4:a = 12
131 5:print a**2
131 5:print a**2
132 6:%history -n 4-6
132 6:%history -n 4-6
133
133
134 """
134 """
135
135
136 args = parse_argstring(self.history, parameter_s)
136 args = parse_argstring(self.history, parameter_s)
137
137
138 # For brevity
138 # For brevity
139 history_manager = self.shell.history_manager
139 history_manager = self.shell.history_manager
140
140
141 def _format_lineno(session, line):
141 def _format_lineno(session, line):
142 """Helper function to format line numbers properly."""
142 """Helper function to format line numbers properly."""
143 if session in (0, history_manager.session_number):
143 if session in (0, history_manager.session_number):
144 return str(line)
144 return str(line)
145 return "%s/%s" % (session, line)
145 return "%s/%s" % (session, line)
146
146
147 # Check if output to specific file was requested.
147 # Check if output to specific file was requested.
148 outfname = args.filename
148 outfname = args.filename
149 if not outfname:
149 if not outfname:
150 outfile = sys.stdout # default
150 outfile = sys.stdout # default
151 # We don't want to close stdout at the end!
151 # We don't want to close stdout at the end!
152 close_at_end = False
152 close_at_end = False
153 else:
153 else:
154 outfname = os.path.expanduser(outfname)
154 if os.path.exists(outfname):
155 if os.path.exists(outfname):
155 try:
156 try:
156 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
157 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
157 except StdinNotImplementedError:
158 except StdinNotImplementedError:
158 ans = True
159 ans = True
159 if not ans:
160 if not ans:
160 print('Aborting.')
161 print('Aborting.')
161 return
162 return
162 print("Overwriting file.")
163 print("Overwriting file.")
163 outfile = io_open(outfname, 'w', encoding='utf-8')
164 outfile = io_open(outfname, 'w', encoding='utf-8')
164 close_at_end = True
165 close_at_end = True
165
166
166 print_nums = args.print_nums
167 print_nums = args.print_nums
167 get_output = args.get_output
168 get_output = args.get_output
168 pyprompts = args.pyprompts
169 pyprompts = args.pyprompts
169 raw = args.raw
170 raw = args.raw
170
171
171 pattern = None
172 pattern = None
172 limit = None if args.limit is _unspecified else args.limit
173 limit = None if args.limit is _unspecified else args.limit
173
174
174 range_pattern = False
175 range_pattern = False
175 if args.pattern is not None and not args.range:
176 if args.pattern is not None and not args.range:
176 if args.pattern:
177 if args.pattern:
177 pattern = "*" + " ".join(args.pattern) + "*"
178 pattern = "*" + " ".join(args.pattern) + "*"
178 else:
179 else:
179 pattern = "*"
180 pattern = "*"
180 hist = history_manager.search(pattern, raw=raw, output=get_output,
181 hist = history_manager.search(pattern, raw=raw, output=get_output,
181 n=limit, unique=args.unique)
182 n=limit, unique=args.unique)
182 print_nums = True
183 print_nums = True
183 elif args.limit is not _unspecified:
184 elif args.limit is not _unspecified:
184 n = 10 if limit is None else limit
185 n = 10 if limit is None else limit
185 hist = history_manager.get_tail(n, raw=raw, output=get_output)
186 hist = history_manager.get_tail(n, raw=raw, output=get_output)
186 else:
187 else:
187 if args.pattern:
188 if args.pattern:
188 range_pattern = "*" + " ".join(args.pattern) + "*"
189 range_pattern = "*" + " ".join(args.pattern) + "*"
189 print_nums = True
190 print_nums = True
190 hist = history_manager.get_range_by_str(
191 hist = history_manager.get_range_by_str(
191 " ".join(args.range), raw, get_output
192 " ".join(args.range), raw, get_output
192 )
193 )
193
194
194 # We could be displaying the entire history, so let's not try to pull
195 # We could be displaying the entire history, so let's not try to pull
195 # it into a list in memory. Anything that needs more space will just
196 # it into a list in memory. Anything that needs more space will just
196 # misalign.
197 # misalign.
197 width = 4
198 width = 4
198
199
199 for session, lineno, inline in hist:
200 for session, lineno, inline in hist:
200 # Print user history with tabs expanded to 4 spaces. The GUI
201 # Print user history with tabs expanded to 4 spaces. The GUI
201 # clients use hard tabs for easier usability in auto-indented code,
202 # clients use hard tabs for easier usability in auto-indented code,
202 # but we want to produce PEP-8 compliant history for safe pasting
203 # but we want to produce PEP-8 compliant history for safe pasting
203 # into an editor.
204 # into an editor.
204 if get_output:
205 if get_output:
205 inline, output = inline
206 inline, output = inline
206 if range_pattern:
207 if range_pattern:
207 if not fnmatch.fnmatch(inline, range_pattern):
208 if not fnmatch.fnmatch(inline, range_pattern):
208 continue
209 continue
209 inline = inline.expandtabs(4).rstrip()
210 inline = inline.expandtabs(4).rstrip()
210
211
211 multiline = "\n" in inline
212 multiline = "\n" in inline
212 line_sep = '\n' if multiline else ' '
213 line_sep = '\n' if multiline else ' '
213 if print_nums:
214 if print_nums:
214 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
215 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
215 line_sep), file=outfile, end=u'')
216 line_sep), file=outfile, end=u'')
216 if pyprompts:
217 if pyprompts:
217 print(u">>> ", end=u"", file=outfile)
218 print(u">>> ", end=u"", file=outfile)
218 if multiline:
219 if multiline:
219 inline = "\n... ".join(inline.splitlines()) + "\n..."
220 inline = "\n... ".join(inline.splitlines()) + "\n..."
220 print(inline, file=outfile)
221 print(inline, file=outfile)
221 if get_output and output:
222 if get_output and output:
222 print(output, file=outfile)
223 print(output, file=outfile)
223
224
224 if close_at_end:
225 if close_at_end:
225 outfile.close()
226 outfile.close()
226
227
227 @line_magic
228 @line_magic
228 def recall(self, arg):
229 def recall(self, arg):
229 r"""Repeat a command, or get command to input line for editing.
230 r"""Repeat a command, or get command to input line for editing.
230
231
231 %recall and %rep are equivalent.
232 %recall and %rep are equivalent.
232
233
233 - %recall (no arguments):
234 - %recall (no arguments):
234
235
235 Place a string version of last computation result (stored in the
236 Place a string version of last computation result (stored in the
236 special '_' variable) to the next input prompt. Allows you to create
237 special '_' variable) to the next input prompt. Allows you to create
237 elaborate command lines without using copy-paste::
238 elaborate command lines without using copy-paste::
238
239
239 In[1]: l = ["hei", "vaan"]
240 In[1]: l = ["hei", "vaan"]
240 In[2]: "".join(l)
241 In[2]: "".join(l)
241 Out[2]: heivaan
242 Out[2]: heivaan
242 In[3]: %recall
243 In[3]: %recall
243 In[4]: heivaan_ <== cursor blinking
244 In[4]: heivaan_ <== cursor blinking
244
245
245 %recall 45
246 %recall 45
246
247
247 Place history line 45 on the next input prompt. Use %hist to find
248 Place history line 45 on the next input prompt. Use %hist to find
248 out the number.
249 out the number.
249
250
250 %recall 1-4
251 %recall 1-4
251
252
252 Combine the specified lines into one cell, and place it on the next
253 Combine the specified lines into one cell, and place it on the next
253 input prompt. See %history for the slice syntax.
254 input prompt. See %history for the slice syntax.
254
255
255 %recall foo+bar
256 %recall foo+bar
256
257
257 If foo+bar can be evaluated in the user namespace, the result is
258 If foo+bar can be evaluated in the user namespace, the result is
258 placed at the next input prompt. Otherwise, the history is searched
259 placed at the next input prompt. Otherwise, the history is searched
259 for lines which contain that substring, and the most recent one is
260 for lines which contain that substring, and the most recent one is
260 placed at the next input prompt.
261 placed at the next input prompt.
261 """
262 """
262 if not arg: # Last output
263 if not arg: # Last output
263 self.shell.set_next_input(str(self.shell.user_ns["_"]))
264 self.shell.set_next_input(str(self.shell.user_ns["_"]))
264 return
265 return
265 # Get history range
266 # Get history range
266 histlines = self.shell.history_manager.get_range_by_str(arg)
267 histlines = self.shell.history_manager.get_range_by_str(arg)
267 cmd = "\n".join(x[2] for x in histlines)
268 cmd = "\n".join(x[2] for x in histlines)
268 if cmd:
269 if cmd:
269 self.shell.set_next_input(cmd.rstrip())
270 self.shell.set_next_input(cmd.rstrip())
270 return
271 return
271
272
272 try: # Variable in user namespace
273 try: # Variable in user namespace
273 cmd = str(eval(arg, self.shell.user_ns))
274 cmd = str(eval(arg, self.shell.user_ns))
274 except Exception: # Search for term in history
275 except Exception: # Search for term in history
275 histlines = self.shell.history_manager.search("*"+arg+"*")
276 histlines = self.shell.history_manager.search("*"+arg+"*")
276 for h in reversed([x[2] for x in histlines]):
277 for h in reversed([x[2] for x in histlines]):
277 if 'recall' in h or 'rep' in h:
278 if 'recall' in h or 'rep' in h:
278 continue
279 continue
279 self.shell.set_next_input(h.rstrip())
280 self.shell.set_next_input(h.rstrip())
280 return
281 return
281 else:
282 else:
282 self.shell.set_next_input(cmd.rstrip())
283 self.shell.set_next_input(cmd.rstrip())
283 return
284 return
284 print("Couldn't evaluate or find in history:", arg)
285 print("Couldn't evaluate or find in history:", arg)
285
286
286 @line_magic
287 @line_magic
287 def rerun(self, parameter_s=''):
288 def rerun(self, parameter_s=''):
288 """Re-run previous input
289 """Re-run previous input
289
290
290 By default, you can specify ranges of input history to be repeated
291 By default, you can specify ranges of input history to be repeated
291 (as with %history). With no arguments, it will repeat the last line.
292 (as with %history). With no arguments, it will repeat the last line.
292
293
293 Options:
294 Options:
294
295
295 -l <n> : Repeat the last n lines of input, not including the
296 -l <n> : Repeat the last n lines of input, not including the
296 current command.
297 current command.
297
298
298 -g foo : Repeat the most recent line which contains foo
299 -g foo : Repeat the most recent line which contains foo
299 """
300 """
300 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
301 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
301 if "l" in opts: # Last n lines
302 if "l" in opts: # Last n lines
302 try:
303 try:
303 n = int(opts["l"])
304 n = int(opts["l"])
304 except ValueError:
305 except ValueError:
305 print("Number of lines must be an integer")
306 print("Number of lines must be an integer")
306 return
307 return
307
308
308 if n == 0:
309 if n == 0:
309 print("Requested 0 last lines - nothing to run")
310 print("Requested 0 last lines - nothing to run")
310 return
311 return
311 elif n < 0:
312 elif n < 0:
312 print("Number of lines to rerun cannot be negative")
313 print("Number of lines to rerun cannot be negative")
313 return
314 return
314
315
315 hist = self.shell.history_manager.get_tail(n)
316 hist = self.shell.history_manager.get_tail(n)
316 elif "g" in opts: # Search
317 elif "g" in opts: # Search
317 p = "*"+opts['g']+"*"
318 p = "*"+opts['g']+"*"
318 hist = list(self.shell.history_manager.search(p))
319 hist = list(self.shell.history_manager.search(p))
319 for l in reversed(hist):
320 for l in reversed(hist):
320 if "rerun" not in l[2]:
321 if "rerun" not in l[2]:
321 hist = [l] # The last match which isn't a %rerun
322 hist = [l] # The last match which isn't a %rerun
322 break
323 break
323 else:
324 else:
324 hist = [] # No matches except %rerun
325 hist = [] # No matches except %rerun
325 elif args: # Specify history ranges
326 elif args: # Specify history ranges
326 hist = self.shell.history_manager.get_range_by_str(args)
327 hist = self.shell.history_manager.get_range_by_str(args)
327 else: # Last line
328 else: # Last line
328 hist = self.shell.history_manager.get_tail(1)
329 hist = self.shell.history_manager.get_tail(1)
329 hist = [x[2] for x in hist]
330 hist = [x[2] for x in hist]
330 if not hist:
331 if not hist:
331 print("No lines in history match specification")
332 print("No lines in history match specification")
332 return
333 return
333 histlines = "\n".join(hist)
334 histlines = "\n".join(hist)
334 print("=== Executing: ===")
335 print("=== Executing: ===")
335 print(histlines)
336 print(histlines)
336 print("=== Output: ===")
337 print("=== Output: ===")
337 self.shell.run_cell("\n".join(hist), store_history=False)
338 self.shell.run_cell("\n".join(hist), store_history=False)
General Comments 0
You need to be logged in to leave comments. Login now