##// END OF EJS Templates
better docstring for the -r option
Martín Gaitán -
Show More
@@ -1,610 +1,614 b''
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 from itertools import chain
21 from itertools import chain
22
22
23 # Our own packages
23 # Our own packages
24 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
24 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
25 from IPython.core.macro import Macro
25 from IPython.core.macro import Macro
26 from IPython.core.magic import Magics, magics_class, line_magic
26 from IPython.core.magic import Magics, magics_class, line_magic
27 from IPython.core.oinspect import find_file, find_source_lines
27 from IPython.core.oinspect import find_file, find_source_lines
28 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.utils import py3compat
29 from IPython.utils import py3compat
30 from IPython.utils.contexts import preserve_keys
30 from IPython.utils.contexts import preserve_keys
31 from IPython.utils.path import get_py_filename, unquote_filename
31 from IPython.utils.path import get_py_filename, unquote_filename
32 from IPython.utils.warn import warn
32 from IPython.utils.warn import warn
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Magic implementation classes
35 # Magic implementation classes
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 # Used for exception handling in magic_edit
38 # Used for exception handling in magic_edit
39 class MacroToEdit(ValueError): pass
39 class MacroToEdit(ValueError): pass
40
40
41 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
41 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
42
42
43 # To match, e.g. 8-10 1:5 :10 3-
43 # To match, e.g. 8-10 1:5 :10 3-
44 range_re = re.compile(r"""
44 range_re = re.compile(r"""
45 (?P<start>\d+)?
45 (?P<start>\d+)?
46 ((?P<sep>[\-:])
46 ((?P<sep>[\-:])
47 (?P<end>\d+)?)?
47 (?P<end>\d+)?)?
48 $""", re.VERBOSE)
48 $""", re.VERBOSE)
49
49
50
50
51 def extract_code_ranges(ranges_str):
51 def extract_code_ranges(ranges_str):
52 """Turn a string of range for %%load into 2-tuples of (start, stop)
52 """Turn a string of range for %%load into 2-tuples of (start, stop)
53 ready to use as a slice of the content splitted by lines.
53 ready to use as a slice of the content splitted by lines.
54
54
55 Examples
55 Examples
56 --------
56 --------
57 list(extract_input_ranges("5-10 2"))
57 list(extract_input_ranges("5-10 2"))
58 [(4, 10), (1, 2)]
58 [(4, 10), (1, 2)]
59 """
59 """
60 for range_str in ranges_str.split():
60 for range_str in ranges_str.split():
61 rmatch = range_re.match(range_str)
61 rmatch = range_re.match(range_str)
62 if not rmatch:
62 if not rmatch:
63 continue
63 continue
64 sep = rmatch.group("sep")
64 sep = rmatch.group("sep")
65 start = rmatch.group("start")
65 start = rmatch.group("start")
66 end = rmatch.group("end")
66 end = rmatch.group("end")
67
67
68 if sep == '-':
68 if sep == '-':
69 start = int(start) - 1 if start else None
69 start = int(start) - 1 if start else None
70 end = int(end) if end else None
70 end = int(end) if end else None
71 elif sep == ':':
71 elif sep == ':':
72 start = int(start) - 1 if start else None
72 start = int(start) - 1 if start else None
73 end = int(end) - 1 if end else None
73 end = int(end) - 1 if end else None
74 else:
74 else:
75 end = int(start)
75 end = int(start)
76 start = int(start) - 1
76 start = int(start) - 1
77 yield (start, end)
77 yield (start, end)
78
78
79
79
80 class InteractivelyDefined(Exception):
80 class InteractivelyDefined(Exception):
81 """Exception for interactively defined variable in magic_edit"""
81 """Exception for interactively defined variable in magic_edit"""
82 def __init__(self, index):
82 def __init__(self, index):
83 self.index = index
83 self.index = index
84
84
85
85
86 @magics_class
86 @magics_class
87 class CodeMagics(Magics):
87 class CodeMagics(Magics):
88 """Magics related to code management (loading, saving, editing, ...)."""
88 """Magics related to code management (loading, saving, editing, ...)."""
89
89
90 @line_magic
90 @line_magic
91 def save(self, parameter_s=''):
91 def save(self, parameter_s=''):
92 """Save a set of lines or a macro to a given filename.
92 """Save a set of lines or a macro to a given filename.
93
93
94 Usage:\\
94 Usage:\\
95 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
95 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
96
96
97 Options:
97 Options:
98
98
99 -r: use 'raw' input. By default, the 'processed' history is used,
99 -r: use 'raw' input. By default, the 'processed' history is used,
100 so that magics are loaded in their transformed version to valid
100 so that magics are loaded in their transformed version to valid
101 Python. If this option is given, the raw input as typed as the
101 Python. If this option is given, the raw input as typed as the
102 command line is used instead.
102 command line is used instead.
103
103
104 -f: force overwrite. If file exists, %save will prompt for overwrite
104 -f: force overwrite. If file exists, %save will prompt for overwrite
105 unless -f is given.
105 unless -f is given.
106
106
107 -a: append to the file instead of overwriting it.
107 -a: append to the file instead of overwriting it.
108
108
109 This function uses the same syntax as %history for input ranges,
109 This function uses the same syntax as %history for input ranges,
110 then saves the lines to the filename you specify.
110 then saves the lines to the filename you specify.
111
111
112 It adds a '.py' extension to the file if you don't do so yourself, and
112 It adds a '.py' extension to the file if you don't do so yourself, and
113 it asks for confirmation before overwriting existing files.
113 it asks for confirmation before overwriting existing files.
114
114
115 If `-r` option is used, the default extension is `.ipy`.
115 If `-r` option is used, the default extension is `.ipy`.
116 """
116 """
117
117
118 opts,args = self.parse_options(parameter_s,'fra',mode='list')
118 opts,args = self.parse_options(parameter_s,'fra',mode='list')
119 if not args:
119 if not args:
120 raise UsageError('Missing filename.')
120 raise UsageError('Missing filename.')
121 raw = 'r' in opts
121 raw = 'r' in opts
122 force = 'f' in opts
122 force = 'f' in opts
123 append = 'a' in opts
123 append = 'a' in opts
124 mode = 'a' if append else 'w'
124 mode = 'a' if append else 'w'
125 ext = u'.ipy' if raw else u'.py'
125 ext = u'.ipy' if raw else u'.py'
126 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
126 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
127 if not fname.endswith((u'.py',u'.ipy')):
127 if not fname.endswith((u'.py',u'.ipy')):
128 fname += ext
128 fname += ext
129 file_exists = os.path.isfile(fname)
129 file_exists = os.path.isfile(fname)
130 if file_exists and not force and not append:
130 if file_exists and not force and not append:
131 try:
131 try:
132 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
132 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
133 except StdinNotImplementedError:
133 except StdinNotImplementedError:
134 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
134 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
135 return
135 return
136 if not overwrite :
136 if not overwrite :
137 print 'Operation cancelled.'
137 print 'Operation cancelled.'
138 return
138 return
139 try:
139 try:
140 cmds = self.shell.find_user_code(codefrom,raw)
140 cmds = self.shell.find_user_code(codefrom,raw)
141 except (TypeError, ValueError) as e:
141 except (TypeError, ValueError) as e:
142 print e.args[0]
142 print e.args[0]
143 return
143 return
144 out = py3compat.cast_unicode(cmds)
144 out = py3compat.cast_unicode(cmds)
145 with io.open(fname, mode, encoding="utf-8") as f:
145 with io.open(fname, mode, encoding="utf-8") as f:
146 if not file_exists or not append:
146 if not file_exists or not append:
147 f.write(u"# coding: utf-8\n")
147 f.write(u"# coding: utf-8\n")
148 f.write(out)
148 f.write(out)
149 # make sure we end on a newline
149 # make sure we end on a newline
150 if not out.endswith(u'\n'):
150 if not out.endswith(u'\n'):
151 f.write(u'\n')
151 f.write(u'\n')
152 print 'The following commands were written to file `%s`:' % fname
152 print 'The following commands were written to file `%s`:' % fname
153 print cmds
153 print cmds
154
154
155 @line_magic
155 @line_magic
156 def pastebin(self, parameter_s=''):
156 def pastebin(self, parameter_s=''):
157 """Upload code to Github's Gist paste bin, returning the URL.
157 """Upload code to Github's Gist paste bin, returning the URL.
158
158
159 Usage:\\
159 Usage:\\
160 %pastebin [-d "Custom description"] 1-7
160 %pastebin [-d "Custom description"] 1-7
161
161
162 The argument can be an input history range, a filename, or the name of a
162 The argument can be an input history range, a filename, or the name of a
163 string or macro.
163 string or macro.
164
164
165 Options:
165 Options:
166
166
167 -d: Pass a custom description for the gist. The default will say
167 -d: Pass a custom description for the gist. The default will say
168 "Pasted from IPython".
168 "Pasted from IPython".
169 """
169 """
170 opts, args = self.parse_options(parameter_s, 'd:')
170 opts, args = self.parse_options(parameter_s, 'd:')
171
171
172 try:
172 try:
173 code = self.shell.find_user_code(args)
173 code = self.shell.find_user_code(args)
174 except (ValueError, TypeError) as e:
174 except (ValueError, TypeError) as e:
175 print e.args[0]
175 print e.args[0]
176 return
176 return
177
177
178 from urllib2 import urlopen # Deferred import
178 from urllib2 import urlopen # Deferred import
179 import json
179 import json
180 post_data = json.dumps({
180 post_data = json.dumps({
181 "description": opts.get('d', "Pasted from IPython"),
181 "description": opts.get('d', "Pasted from IPython"),
182 "public": True,
182 "public": True,
183 "files": {
183 "files": {
184 "file1.py": {
184 "file1.py": {
185 "content": code
185 "content": code
186 }
186 }
187 }
187 }
188 }).encode('utf-8')
188 }).encode('utf-8')
189
189
190 response = urlopen("https://api.github.com/gists", post_data)
190 response = urlopen("https://api.github.com/gists", post_data)
191 response_data = json.loads(response.read().decode('utf-8'))
191 response_data = json.loads(response.read().decode('utf-8'))
192 return response_data['html_url']
192 return response_data['html_url']
193
193
194 @line_magic
194 @line_magic
195 def loadpy(self, arg_s):
195 def loadpy(self, arg_s):
196 """Alias of `%load`
196 """Alias of `%load`
197
197
198 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
198 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
199 extension. So it has been renamed simply into %load. You can look at
199 extension. So it has been renamed simply into %load. You can look at
200 `%load`'s docstring for more info.
200 `%load`'s docstring for more info.
201 """
201 """
202 self.load(arg_s)
202 self.load(arg_s)
203
203
204 @line_magic
204 @line_magic
205 def load(self, arg_s):
205 def load(self, arg_s):
206 """Load code into the current frontend.
206 """Load code into the current frontend.
207
207
208 Usage:\\
208 Usage:\\
209 %load [options] source
209 %load [options] source
210
210
211 where source can be a filename, URL, input history range or macro
211 where source can be a filename, URL, input history range or macro
212
212
213 Options:
213 Options:
214 --------
214 --------
215 -r : specify ranges of lines to load from the source
215 -r <lines>: Specify lines or ranges of lines to load from the source.
216 Ranges could be specified as x-y (x..y) or in python-style x:y
217 (x..(y-1)). Both limits x and y can be left blank (meaning the
218 beginning and end of the file, respectively).
219
216 -y : Don't ask confirmation for loading source above 200 000 characters.
220 -y : Don't ask confirmation for loading source above 200 000 characters.
217
221
218 This magic command can either take a local filename, a URL, an history
222 This magic command can either take a local filename, a URL, an history
219 range (see %history) or a macro as argument, it will prompt for
223 range (see %history) or a macro as argument, it will prompt for
220 confirmation before loading source with more than 200 000 characters, unless
224 confirmation before loading source with more than 200 000 characters, unless
221 -y flag is passed or if the frontend does not support raw_input::
225 -y flag is passed or if the frontend does not support raw_input::
222
226
223 %load myscript.py
227 %load myscript.py
224 %load 7-27
228 %load 7-27
225 %load myMacro
229 %load myMacro
226 %load http://www.example.com/myscript.py
230 %load http://www.example.com/myscript.py
227 %load -r 5-10 myscript.py
231 %load -r 5-10 myscript.py
228 %load -r 10-20,30,40-50 foo.py
232 %load -r 10-20,30,40: foo.py
229 """
233 """
230 opts,args = self.parse_options(arg_s,'yr:')
234 opts,args = self.parse_options(arg_s,'yr:')
231
235
232 if not args:
236 if not args:
233 raise UsageError('Missing filename, URL, input history range, '
237 raise UsageError('Missing filename, URL, input history range, '
234 'or macro.')
238 'or macro.')
235
239
236 contents = self.shell.find_user_code(args)
240 contents = self.shell.find_user_code(args)
237
241
238 if 'r' in opts:
242 if 'r' in opts:
239 ranges = opts['r'].replace(',', ' ')
243 ranges = opts['r'].replace(',', ' ')
240 lines = contents.split('\n')
244 lines = contents.split('\n')
241 slices = extract_code_ranges(ranges)
245 slices = extract_code_ranges(ranges)
242 contents = [lines[slice(*slc)] for slc in slices]
246 contents = [lines[slice(*slc)] for slc in slices]
243 contents = '\n'.join(chain.from_iterable(contents))
247 contents = '\n'.join(chain.from_iterable(contents))
244
248
245 l = len(contents)
249 l = len(contents)
246
250
247
251
248 # 200 000 is ~ 2500 full 80 caracter lines
252 # 200 000 is ~ 2500 full 80 caracter lines
249 # so in average, more than 5000 lines
253 # so in average, more than 5000 lines
250 if l > 200000 and 'y' not in opts:
254 if l > 200000 and 'y' not in opts:
251 try:
255 try:
252 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
256 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
253 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
257 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
254 except StdinNotImplementedError:
258 except StdinNotImplementedError:
255 #asume yes if raw input not implemented
259 #asume yes if raw input not implemented
256 ans = True
260 ans = True
257
261
258 if ans is False :
262 if ans is False :
259 print 'Operation cancelled.'
263 print 'Operation cancelled.'
260 return
264 return
261
265
262 self.shell.set_next_input(contents)
266 self.shell.set_next_input(contents)
263
267
264 @staticmethod
268 @staticmethod
265 def _find_edit_target(shell, args, opts, last_call):
269 def _find_edit_target(shell, args, opts, last_call):
266 """Utility method used by magic_edit to find what to edit."""
270 """Utility method used by magic_edit to find what to edit."""
267
271
268 def make_filename(arg):
272 def make_filename(arg):
269 "Make a filename from the given args"
273 "Make a filename from the given args"
270 arg = unquote_filename(arg)
274 arg = unquote_filename(arg)
271 try:
275 try:
272 filename = get_py_filename(arg)
276 filename = get_py_filename(arg)
273 except IOError:
277 except IOError:
274 # If it ends with .py but doesn't already exist, assume we want
278 # If it ends with .py but doesn't already exist, assume we want
275 # a new file.
279 # a new file.
276 if arg.endswith('.py'):
280 if arg.endswith('.py'):
277 filename = arg
281 filename = arg
278 else:
282 else:
279 filename = None
283 filename = None
280 return filename
284 return filename
281
285
282 # Set a few locals from the options for convenience:
286 # Set a few locals from the options for convenience:
283 opts_prev = 'p' in opts
287 opts_prev = 'p' in opts
284 opts_raw = 'r' in opts
288 opts_raw = 'r' in opts
285
289
286 # custom exceptions
290 # custom exceptions
287 class DataIsObject(Exception): pass
291 class DataIsObject(Exception): pass
288
292
289 # Default line number value
293 # Default line number value
290 lineno = opts.get('n',None)
294 lineno = opts.get('n',None)
291
295
292 if opts_prev:
296 if opts_prev:
293 args = '_%s' % last_call[0]
297 args = '_%s' % last_call[0]
294 if args not in shell.user_ns:
298 if args not in shell.user_ns:
295 args = last_call[1]
299 args = last_call[1]
296
300
297 # by default this is done with temp files, except when the given
301 # by default this is done with temp files, except when the given
298 # arg is a filename
302 # arg is a filename
299 use_temp = True
303 use_temp = True
300
304
301 data = ''
305 data = ''
302
306
303 # First, see if the arguments should be a filename.
307 # First, see if the arguments should be a filename.
304 filename = make_filename(args)
308 filename = make_filename(args)
305 if filename:
309 if filename:
306 use_temp = False
310 use_temp = False
307 elif args:
311 elif args:
308 # Mode where user specifies ranges of lines, like in %macro.
312 # Mode where user specifies ranges of lines, like in %macro.
309 data = shell.extract_input_lines(args, opts_raw)
313 data = shell.extract_input_lines(args, opts_raw)
310 if not data:
314 if not data:
311 try:
315 try:
312 # Load the parameter given as a variable. If not a string,
316 # Load the parameter given as a variable. If not a string,
313 # process it as an object instead (below)
317 # process it as an object instead (below)
314
318
315 #print '*** args',args,'type',type(args) # dbg
319 #print '*** args',args,'type',type(args) # dbg
316 data = eval(args, shell.user_ns)
320 data = eval(args, shell.user_ns)
317 if not isinstance(data, basestring):
321 if not isinstance(data, basestring):
318 raise DataIsObject
322 raise DataIsObject
319
323
320 except (NameError,SyntaxError):
324 except (NameError,SyntaxError):
321 # given argument is not a variable, try as a filename
325 # given argument is not a variable, try as a filename
322 filename = make_filename(args)
326 filename = make_filename(args)
323 if filename is None:
327 if filename is None:
324 warn("Argument given (%s) can't be found as a variable "
328 warn("Argument given (%s) can't be found as a variable "
325 "or as a filename." % args)
329 "or as a filename." % args)
326 return (None, None, None)
330 return (None, None, None)
327 use_temp = False
331 use_temp = False
328
332
329 except DataIsObject:
333 except DataIsObject:
330 # macros have a special edit function
334 # macros have a special edit function
331 if isinstance(data, Macro):
335 if isinstance(data, Macro):
332 raise MacroToEdit(data)
336 raise MacroToEdit(data)
333
337
334 # For objects, try to edit the file where they are defined
338 # For objects, try to edit the file where they are defined
335 filename = find_file(data)
339 filename = find_file(data)
336 if filename:
340 if filename:
337 if 'fakemodule' in filename.lower() and \
341 if 'fakemodule' in filename.lower() and \
338 inspect.isclass(data):
342 inspect.isclass(data):
339 # class created by %edit? Try to find source
343 # class created by %edit? Try to find source
340 # by looking for method definitions instead, the
344 # by looking for method definitions instead, the
341 # __module__ in those classes is FakeModule.
345 # __module__ in those classes is FakeModule.
342 attrs = [getattr(data, aname) for aname in dir(data)]
346 attrs = [getattr(data, aname) for aname in dir(data)]
343 for attr in attrs:
347 for attr in attrs:
344 if not inspect.ismethod(attr):
348 if not inspect.ismethod(attr):
345 continue
349 continue
346 filename = find_file(attr)
350 filename = find_file(attr)
347 if filename and \
351 if filename and \
348 'fakemodule' not in filename.lower():
352 'fakemodule' not in filename.lower():
349 # change the attribute to be the edit
353 # change the attribute to be the edit
350 # target instead
354 # target instead
351 data = attr
355 data = attr
352 break
356 break
353
357
354 m = ipython_input_pat.match(os.path.basename(filename))
358 m = ipython_input_pat.match(os.path.basename(filename))
355 if m:
359 if m:
356 raise InteractivelyDefined(int(m.groups()[0]))
360 raise InteractivelyDefined(int(m.groups()[0]))
357
361
358 datafile = 1
362 datafile = 1
359 if filename is None:
363 if filename is None:
360 filename = make_filename(args)
364 filename = make_filename(args)
361 datafile = 1
365 datafile = 1
362 if filename is not None:
366 if filename is not None:
363 # only warn about this if we get a real name
367 # only warn about this if we get a real name
364 warn('Could not find file where `%s` is defined.\n'
368 warn('Could not find file where `%s` is defined.\n'
365 'Opening a file named `%s`' % (args, filename))
369 'Opening a file named `%s`' % (args, filename))
366 # Now, make sure we can actually read the source (if it was
370 # Now, make sure we can actually read the source (if it was
367 # in a temp file it's gone by now).
371 # in a temp file it's gone by now).
368 if datafile:
372 if datafile:
369 if lineno is None:
373 if lineno is None:
370 lineno = find_source_lines(data)
374 lineno = find_source_lines(data)
371 if lineno is None:
375 if lineno is None:
372 filename = make_filename(args)
376 filename = make_filename(args)
373 if filename is None:
377 if filename is None:
374 warn('The file where `%s` was defined '
378 warn('The file where `%s` was defined '
375 'cannot be read or found.' % data)
379 'cannot be read or found.' % data)
376 return (None, None, None)
380 return (None, None, None)
377 use_temp = False
381 use_temp = False
378
382
379 if use_temp:
383 if use_temp:
380 filename = shell.mktempfile(data)
384 filename = shell.mktempfile(data)
381 print 'IPython will make a temporary file named:',filename
385 print 'IPython will make a temporary file named:',filename
382
386
383 # use last_call to remember the state of the previous call, but don't
387 # use last_call to remember the state of the previous call, but don't
384 # let it be clobbered by successive '-p' calls.
388 # let it be clobbered by successive '-p' calls.
385 try:
389 try:
386 last_call[0] = shell.displayhook.prompt_count
390 last_call[0] = shell.displayhook.prompt_count
387 if not opts_prev:
391 if not opts_prev:
388 last_call[1] = args
392 last_call[1] = args
389 except:
393 except:
390 pass
394 pass
391
395
392
396
393 return filename, lineno, use_temp
397 return filename, lineno, use_temp
394
398
395 def _edit_macro(self,mname,macro):
399 def _edit_macro(self,mname,macro):
396 """open an editor with the macro data in a file"""
400 """open an editor with the macro data in a file"""
397 filename = self.shell.mktempfile(macro.value)
401 filename = self.shell.mktempfile(macro.value)
398 self.shell.hooks.editor(filename)
402 self.shell.hooks.editor(filename)
399
403
400 # and make a new macro object, to replace the old one
404 # and make a new macro object, to replace the old one
401 mfile = open(filename)
405 mfile = open(filename)
402 mvalue = mfile.read()
406 mvalue = mfile.read()
403 mfile.close()
407 mfile.close()
404 self.shell.user_ns[mname] = Macro(mvalue)
408 self.shell.user_ns[mname] = Macro(mvalue)
405
409
406 @skip_doctest
410 @skip_doctest
407 @line_magic
411 @line_magic
408 def edit(self, parameter_s='',last_call=['','']):
412 def edit(self, parameter_s='',last_call=['','']):
409 """Bring up an editor and execute the resulting code.
413 """Bring up an editor and execute the resulting code.
410
414
411 Usage:
415 Usage:
412 %edit [options] [args]
416 %edit [options] [args]
413
417
414 %edit runs IPython's editor hook. The default version of this hook is
418 %edit runs IPython's editor hook. The default version of this hook is
415 set to call the editor specified by your $EDITOR environment variable.
419 set to call the editor specified by your $EDITOR environment variable.
416 If this isn't found, it will default to vi under Linux/Unix and to
420 If this isn't found, it will default to vi under Linux/Unix and to
417 notepad under Windows. See the end of this docstring for how to change
421 notepad under Windows. See the end of this docstring for how to change
418 the editor hook.
422 the editor hook.
419
423
420 You can also set the value of this editor via the
424 You can also set the value of this editor via the
421 ``TerminalInteractiveShell.editor`` option in your configuration file.
425 ``TerminalInteractiveShell.editor`` option in your configuration file.
422 This is useful if you wish to use a different editor from your typical
426 This is useful if you wish to use a different editor from your typical
423 default with IPython (and for Windows users who typically don't set
427 default with IPython (and for Windows users who typically don't set
424 environment variables).
428 environment variables).
425
429
426 This command allows you to conveniently edit multi-line code right in
430 This command allows you to conveniently edit multi-line code right in
427 your IPython session.
431 your IPython session.
428
432
429 If called without arguments, %edit opens up an empty editor with a
433 If called without arguments, %edit opens up an empty editor with a
430 temporary file and will execute the contents of this file when you
434 temporary file and will execute the contents of this file when you
431 close it (don't forget to save it!).
435 close it (don't forget to save it!).
432
436
433
437
434 Options:
438 Options:
435
439
436 -n <number>: open the editor at a specified line number. By default,
440 -n <number>: open the editor at a specified line number. By default,
437 the IPython editor hook uses the unix syntax 'editor +N filename', but
441 the IPython editor hook uses the unix syntax 'editor +N filename', but
438 you can configure this by providing your own modified hook if your
442 you can configure this by providing your own modified hook if your
439 favorite editor supports line-number specifications with a different
443 favorite editor supports line-number specifications with a different
440 syntax.
444 syntax.
441
445
442 -p: this will call the editor with the same data as the previous time
446 -p: this will call the editor with the same data as the previous time
443 it was used, regardless of how long ago (in your current session) it
447 it was used, regardless of how long ago (in your current session) it
444 was.
448 was.
445
449
446 -r: use 'raw' input. This option only applies to input taken from the
450 -r: use 'raw' input. This option only applies to input taken from the
447 user's history. By default, the 'processed' history is used, so that
451 user's history. By default, the 'processed' history is used, so that
448 magics are loaded in their transformed version to valid Python. If
452 magics are loaded in their transformed version to valid Python. If
449 this option is given, the raw input as typed as the command line is
453 this option is given, the raw input as typed as the command line is
450 used instead. When you exit the editor, it will be executed by
454 used instead. When you exit the editor, it will be executed by
451 IPython's own processor.
455 IPython's own processor.
452
456
453 -x: do not execute the edited code immediately upon exit. This is
457 -x: do not execute the edited code immediately upon exit. This is
454 mainly useful if you are editing programs which need to be called with
458 mainly useful if you are editing programs which need to be called with
455 command line arguments, which you can then do using %run.
459 command line arguments, which you can then do using %run.
456
460
457
461
458 Arguments:
462 Arguments:
459
463
460 If arguments are given, the following possibilities exist:
464 If arguments are given, the following possibilities exist:
461
465
462 - If the argument is a filename, IPython will load that into the
466 - If the argument is a filename, IPython will load that into the
463 editor. It will execute its contents with execfile() when you exit,
467 editor. It will execute its contents with execfile() when you exit,
464 loading any code in the file into your interactive namespace.
468 loading any code in the file into your interactive namespace.
465
469
466 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
470 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
467 The syntax is the same as in the %history magic.
471 The syntax is the same as in the %history magic.
468
472
469 - If the argument is a string variable, its contents are loaded
473 - If the argument is a string variable, its contents are loaded
470 into the editor. You can thus edit any string which contains
474 into the editor. You can thus edit any string which contains
471 python code (including the result of previous edits).
475 python code (including the result of previous edits).
472
476
473 - If the argument is the name of an object (other than a string),
477 - If the argument is the name of an object (other than a string),
474 IPython will try to locate the file where it was defined and open the
478 IPython will try to locate the file where it was defined and open the
475 editor at the point where it is defined. You can use `%edit function`
479 editor at the point where it is defined. You can use `%edit function`
476 to load an editor exactly at the point where 'function' is defined,
480 to load an editor exactly at the point where 'function' is defined,
477 edit it and have the file be executed automatically.
481 edit it and have the file be executed automatically.
478
482
479 - If the object is a macro (see %macro for details), this opens up your
483 - If the object is a macro (see %macro for details), this opens up your
480 specified editor with a temporary file containing the macro's data.
484 specified editor with a temporary file containing the macro's data.
481 Upon exit, the macro is reloaded with the contents of the file.
485 Upon exit, the macro is reloaded with the contents of the file.
482
486
483 Note: opening at an exact line is only supported under Unix, and some
487 Note: opening at an exact line is only supported under Unix, and some
484 editors (like kedit and gedit up to Gnome 2.8) do not understand the
488 editors (like kedit and gedit up to Gnome 2.8) do not understand the
485 '+NUMBER' parameter necessary for this feature. Good editors like
489 '+NUMBER' parameter necessary for this feature. Good editors like
486 (X)Emacs, vi, jed, pico and joe all do.
490 (X)Emacs, vi, jed, pico and joe all do.
487
491
488 After executing your code, %edit will return as output the code you
492 After executing your code, %edit will return as output the code you
489 typed in the editor (except when it was an existing file). This way
493 typed in the editor (except when it was an existing file). This way
490 you can reload the code in further invocations of %edit as a variable,
494 you can reload the code in further invocations of %edit as a variable,
491 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
495 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
492 the output.
496 the output.
493
497
494 Note that %edit is also available through the alias %ed.
498 Note that %edit is also available through the alias %ed.
495
499
496 This is an example of creating a simple function inside the editor and
500 This is an example of creating a simple function inside the editor and
497 then modifying it. First, start up the editor::
501 then modifying it. First, start up the editor::
498
502
499 In [1]: edit
503 In [1]: edit
500 Editing... done. Executing edited code...
504 Editing... done. Executing edited code...
501 Out[1]: 'def foo():\\n print "foo() was defined in an editing
505 Out[1]: 'def foo():\\n print "foo() was defined in an editing
502 session"\\n'
506 session"\\n'
503
507
504 We can then call the function foo()::
508 We can then call the function foo()::
505
509
506 In [2]: foo()
510 In [2]: foo()
507 foo() was defined in an editing session
511 foo() was defined in an editing session
508
512
509 Now we edit foo. IPython automatically loads the editor with the
513 Now we edit foo. IPython automatically loads the editor with the
510 (temporary) file where foo() was previously defined::
514 (temporary) file where foo() was previously defined::
511
515
512 In [3]: edit foo
516 In [3]: edit foo
513 Editing... done. Executing edited code...
517 Editing... done. Executing edited code...
514
518
515 And if we call foo() again we get the modified version::
519 And if we call foo() again we get the modified version::
516
520
517 In [4]: foo()
521 In [4]: foo()
518 foo() has now been changed!
522 foo() has now been changed!
519
523
520 Here is an example of how to edit a code snippet successive
524 Here is an example of how to edit a code snippet successive
521 times. First we call the editor::
525 times. First we call the editor::
522
526
523 In [5]: edit
527 In [5]: edit
524 Editing... done. Executing edited code...
528 Editing... done. Executing edited code...
525 hello
529 hello
526 Out[5]: "print 'hello'\\n"
530 Out[5]: "print 'hello'\\n"
527
531
528 Now we call it again with the previous output (stored in _)::
532 Now we call it again with the previous output (stored in _)::
529
533
530 In [6]: edit _
534 In [6]: edit _
531 Editing... done. Executing edited code...
535 Editing... done. Executing edited code...
532 hello world
536 hello world
533 Out[6]: "print 'hello world'\\n"
537 Out[6]: "print 'hello world'\\n"
534
538
535 Now we call it with the output #8 (stored in _8, also as Out[8])::
539 Now we call it with the output #8 (stored in _8, also as Out[8])::
536
540
537 In [7]: edit _8
541 In [7]: edit _8
538 Editing... done. Executing edited code...
542 Editing... done. Executing edited code...
539 hello again
543 hello again
540 Out[7]: "print 'hello again'\\n"
544 Out[7]: "print 'hello again'\\n"
541
545
542
546
543 Changing the default editor hook:
547 Changing the default editor hook:
544
548
545 If you wish to write your own editor hook, you can put it in a
549 If you wish to write your own editor hook, you can put it in a
546 configuration file which you load at startup time. The default hook
550 configuration file which you load at startup time. The default hook
547 is defined in the IPython.core.hooks module, and you can use that as a
551 is defined in the IPython.core.hooks module, and you can use that as a
548 starting example for further modifications. That file also has
552 starting example for further modifications. That file also has
549 general instructions on how to set a new hook for use once you've
553 general instructions on how to set a new hook for use once you've
550 defined it."""
554 defined it."""
551 opts,args = self.parse_options(parameter_s,'prxn:')
555 opts,args = self.parse_options(parameter_s,'prxn:')
552
556
553 try:
557 try:
554 filename, lineno, is_temp = self._find_edit_target(self.shell,
558 filename, lineno, is_temp = self._find_edit_target(self.shell,
555 args, opts, last_call)
559 args, opts, last_call)
556 except MacroToEdit as e:
560 except MacroToEdit as e:
557 self._edit_macro(args, e.args[0])
561 self._edit_macro(args, e.args[0])
558 return
562 return
559 except InteractivelyDefined as e:
563 except InteractivelyDefined as e:
560 print "Editing In[%i]" % e.index
564 print "Editing In[%i]" % e.index
561 args = str(e.index)
565 args = str(e.index)
562 filename, lineno, is_temp = self._find_edit_target(self.shell,
566 filename, lineno, is_temp = self._find_edit_target(self.shell,
563 args, opts, last_call)
567 args, opts, last_call)
564 if filename is None:
568 if filename is None:
565 # nothing was found, warnings have already been issued,
569 # nothing was found, warnings have already been issued,
566 # just give up.
570 # just give up.
567 return
571 return
568
572
569 # do actual editing here
573 # do actual editing here
570 print 'Editing...',
574 print 'Editing...',
571 sys.stdout.flush()
575 sys.stdout.flush()
572 try:
576 try:
573 # Quote filenames that may have spaces in them
577 # Quote filenames that may have spaces in them
574 if ' ' in filename:
578 if ' ' in filename:
575 filename = "'%s'" % filename
579 filename = "'%s'" % filename
576 self.shell.hooks.editor(filename,lineno)
580 self.shell.hooks.editor(filename,lineno)
577 except TryNext:
581 except TryNext:
578 warn('Could not open editor')
582 warn('Could not open editor')
579 return
583 return
580
584
581 # XXX TODO: should this be generalized for all string vars?
585 # XXX TODO: should this be generalized for all string vars?
582 # For now, this is special-cased to blocks created by cpaste
586 # For now, this is special-cased to blocks created by cpaste
583 if args.strip() == 'pasted_block':
587 if args.strip() == 'pasted_block':
584 with open(filename, 'r') as f:
588 with open(filename, 'r') as f:
585 self.shell.user_ns['pasted_block'] = f.read()
589 self.shell.user_ns['pasted_block'] = f.read()
586
590
587 if 'x' in opts: # -x prevents actual execution
591 if 'x' in opts: # -x prevents actual execution
588 print
592 print
589 else:
593 else:
590 print 'done. Executing edited code...'
594 print 'done. Executing edited code...'
591 with preserve_keys(self.shell.user_ns, '__file__'):
595 with preserve_keys(self.shell.user_ns, '__file__'):
592 if not is_temp:
596 if not is_temp:
593 self.shell.user_ns['__file__'] = filename
597 self.shell.user_ns['__file__'] = filename
594 if 'r' in opts: # Untranslated IPython code
598 if 'r' in opts: # Untranslated IPython code
595 with open(filename, 'r') as f:
599 with open(filename, 'r') as f:
596 source = f.read()
600 source = f.read()
597 self.shell.run_cell(source, store_history=False)
601 self.shell.run_cell(source, store_history=False)
598 else:
602 else:
599 self.shell.safe_execfile(filename, self.shell.user_ns,
603 self.shell.safe_execfile(filename, self.shell.user_ns,
600 self.shell.user_ns)
604 self.shell.user_ns)
601
605
602 if is_temp:
606 if is_temp:
603 try:
607 try:
604 return open(filename).read()
608 return open(filename).read()
605 except IOError as msg:
609 except IOError as msg:
606 if msg.filename == filename:
610 if msg.filename == filename:
607 warn('File not found. Did you forget to save?')
611 warn('File not found. Did you forget to save?')
608 return
612 return
609 else:
613 else:
610 self.shell.showtraceback()
614 self.shell.showtraceback()
General Comments 0
You need to be logged in to leave comments. Login now