##// END OF EJS Templates
Use the with statement to open a file.
Abhinav Upadhyay -
Show More
@@ -1,614 +1,613 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 <lines>: Specify lines or 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
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
217 (x..(y-1)). Both limits x and y can be left blank (meaning the
218 beginning and end of the file, respectively).
218 beginning and end of the file, respectively).
219
219
220 -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.
221
221
222 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
223 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
224 confirmation before loading source with more than 200 000 characters, unless
224 confirmation before loading source with more than 200 000 characters, unless
225 -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::
226
226
227 %load myscript.py
227 %load myscript.py
228 %load 7-27
228 %load 7-27
229 %load myMacro
229 %load myMacro
230 %load http://www.example.com/myscript.py
230 %load http://www.example.com/myscript.py
231 %load -r 5-10 myscript.py
231 %load -r 5-10 myscript.py
232 %load -r 10-20,30,40: foo.py
232 %load -r 10-20,30,40: foo.py
233 """
233 """
234 opts,args = self.parse_options(arg_s,'yr:')
234 opts,args = self.parse_options(arg_s,'yr:')
235
235
236 if not args:
236 if not args:
237 raise UsageError('Missing filename, URL, input history range, '
237 raise UsageError('Missing filename, URL, input history range, '
238 'or macro.')
238 'or macro.')
239
239
240 contents = self.shell.find_user_code(args)
240 contents = self.shell.find_user_code(args)
241
241
242 if 'r' in opts:
242 if 'r' in opts:
243 ranges = opts['r'].replace(',', ' ')
243 ranges = opts['r'].replace(',', ' ')
244 lines = contents.split('\n')
244 lines = contents.split('\n')
245 slices = extract_code_ranges(ranges)
245 slices = extract_code_ranges(ranges)
246 contents = [lines[slice(*slc)] for slc in slices]
246 contents = [lines[slice(*slc)] for slc in slices]
247 contents = '\n'.join(chain.from_iterable(contents))
247 contents = '\n'.join(chain.from_iterable(contents))
248
248
249 l = len(contents)
249 l = len(contents)
250
250
251
251
252 # 200 000 is ~ 2500 full 80 caracter lines
252 # 200 000 is ~ 2500 full 80 caracter lines
253 # so in average, more than 5000 lines
253 # so in average, more than 5000 lines
254 if l > 200000 and 'y' not in opts:
254 if l > 200000 and 'y' not in opts:
255 try:
255 try:
256 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"\
257 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
257 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
258 except StdinNotImplementedError:
258 except StdinNotImplementedError:
259 #asume yes if raw input not implemented
259 #asume yes if raw input not implemented
260 ans = True
260 ans = True
261
261
262 if ans is False :
262 if ans is False :
263 print 'Operation cancelled.'
263 print 'Operation cancelled.'
264 return
264 return
265
265
266 self.shell.set_next_input(contents)
266 self.shell.set_next_input(contents)
267
267
268 @staticmethod
268 @staticmethod
269 def _find_edit_target(shell, args, opts, last_call):
269 def _find_edit_target(shell, args, opts, last_call):
270 """Utility method used by magic_edit to find what to edit."""
270 """Utility method used by magic_edit to find what to edit."""
271
271
272 def make_filename(arg):
272 def make_filename(arg):
273 "Make a filename from the given args"
273 "Make a filename from the given args"
274 arg = unquote_filename(arg)
274 arg = unquote_filename(arg)
275 try:
275 try:
276 filename = get_py_filename(arg)
276 filename = get_py_filename(arg)
277 except IOError:
277 except IOError:
278 # 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
279 # a new file.
279 # a new file.
280 if arg.endswith('.py'):
280 if arg.endswith('.py'):
281 filename = arg
281 filename = arg
282 else:
282 else:
283 filename = None
283 filename = None
284 return filename
284 return filename
285
285
286 # Set a few locals from the options for convenience:
286 # Set a few locals from the options for convenience:
287 opts_prev = 'p' in opts
287 opts_prev = 'p' in opts
288 opts_raw = 'r' in opts
288 opts_raw = 'r' in opts
289
289
290 # custom exceptions
290 # custom exceptions
291 class DataIsObject(Exception): pass
291 class DataIsObject(Exception): pass
292
292
293 # Default line number value
293 # Default line number value
294 lineno = opts.get('n',None)
294 lineno = opts.get('n',None)
295
295
296 if opts_prev:
296 if opts_prev:
297 args = '_%s' % last_call[0]
297 args = '_%s' % last_call[0]
298 if args not in shell.user_ns:
298 if args not in shell.user_ns:
299 args = last_call[1]
299 args = last_call[1]
300
300
301 # 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
302 # arg is a filename
302 # arg is a filename
303 use_temp = True
303 use_temp = True
304
304
305 data = ''
305 data = ''
306
306
307 # First, see if the arguments should be a filename.
307 # First, see if the arguments should be a filename.
308 filename = make_filename(args)
308 filename = make_filename(args)
309 if filename:
309 if filename:
310 use_temp = False
310 use_temp = False
311 elif args:
311 elif args:
312 # Mode where user specifies ranges of lines, like in %macro.
312 # Mode where user specifies ranges of lines, like in %macro.
313 data = shell.extract_input_lines(args, opts_raw)
313 data = shell.extract_input_lines(args, opts_raw)
314 if not data:
314 if not data:
315 try:
315 try:
316 # Load the parameter given as a variable. If not a string,
316 # Load the parameter given as a variable. If not a string,
317 # process it as an object instead (below)
317 # process it as an object instead (below)
318
318
319 #print '*** args',args,'type',type(args) # dbg
319 #print '*** args',args,'type',type(args) # dbg
320 data = eval(args, shell.user_ns)
320 data = eval(args, shell.user_ns)
321 if not isinstance(data, basestring):
321 if not isinstance(data, basestring):
322 raise DataIsObject
322 raise DataIsObject
323
323
324 except (NameError,SyntaxError):
324 except (NameError,SyntaxError):
325 # given argument is not a variable, try as a filename
325 # given argument is not a variable, try as a filename
326 filename = make_filename(args)
326 filename = make_filename(args)
327 if filename is None:
327 if filename is None:
328 warn("Argument given (%s) can't be found as a variable "
328 warn("Argument given (%s) can't be found as a variable "
329 "or as a filename." % args)
329 "or as a filename." % args)
330 return (None, None, None)
330 return (None, None, None)
331 use_temp = False
331 use_temp = False
332
332
333 except DataIsObject:
333 except DataIsObject:
334 # macros have a special edit function
334 # macros have a special edit function
335 if isinstance(data, Macro):
335 if isinstance(data, Macro):
336 raise MacroToEdit(data)
336 raise MacroToEdit(data)
337
337
338 # For objects, try to edit the file where they are defined
338 # For objects, try to edit the file where they are defined
339 filename = find_file(data)
339 filename = find_file(data)
340 if filename:
340 if filename:
341 if 'fakemodule' in filename.lower() and \
341 if 'fakemodule' in filename.lower() and \
342 inspect.isclass(data):
342 inspect.isclass(data):
343 # class created by %edit? Try to find source
343 # class created by %edit? Try to find source
344 # by looking for method definitions instead, the
344 # by looking for method definitions instead, the
345 # __module__ in those classes is FakeModule.
345 # __module__ in those classes is FakeModule.
346 attrs = [getattr(data, aname) for aname in dir(data)]
346 attrs = [getattr(data, aname) for aname in dir(data)]
347 for attr in attrs:
347 for attr in attrs:
348 if not inspect.ismethod(attr):
348 if not inspect.ismethod(attr):
349 continue
349 continue
350 filename = find_file(attr)
350 filename = find_file(attr)
351 if filename and \
351 if filename and \
352 'fakemodule' not in filename.lower():
352 'fakemodule' not in filename.lower():
353 # change the attribute to be the edit
353 # change the attribute to be the edit
354 # target instead
354 # target instead
355 data = attr
355 data = attr
356 break
356 break
357
357
358 m = ipython_input_pat.match(os.path.basename(filename))
358 m = ipython_input_pat.match(os.path.basename(filename))
359 if m:
359 if m:
360 raise InteractivelyDefined(int(m.groups()[0]))
360 raise InteractivelyDefined(int(m.groups()[0]))
361
361
362 datafile = 1
362 datafile = 1
363 if filename is None:
363 if filename is None:
364 filename = make_filename(args)
364 filename = make_filename(args)
365 datafile = 1
365 datafile = 1
366 if filename is not None:
366 if filename is not None:
367 # only warn about this if we get a real name
367 # only warn about this if we get a real name
368 warn('Could not find file where `%s` is defined.\n'
368 warn('Could not find file where `%s` is defined.\n'
369 'Opening a file named `%s`' % (args, filename))
369 'Opening a file named `%s`' % (args, filename))
370 # 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
371 # in a temp file it's gone by now).
371 # in a temp file it's gone by now).
372 if datafile:
372 if datafile:
373 if lineno is None:
373 if lineno is None:
374 lineno = find_source_lines(data)
374 lineno = find_source_lines(data)
375 if lineno is None:
375 if lineno is None:
376 filename = make_filename(args)
376 filename = make_filename(args)
377 if filename is None:
377 if filename is None:
378 warn('The file where `%s` was defined '
378 warn('The file where `%s` was defined '
379 'cannot be read or found.' % data)
379 'cannot be read or found.' % data)
380 return (None, None, None)
380 return (None, None, None)
381 use_temp = False
381 use_temp = False
382
382
383 if use_temp:
383 if use_temp:
384 filename = shell.mktempfile(data)
384 filename = shell.mktempfile(data)
385 print 'IPython will make a temporary file named:',filename
385 print 'IPython will make a temporary file named:',filename
386
386
387 # 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
388 # let it be clobbered by successive '-p' calls.
388 # let it be clobbered by successive '-p' calls.
389 try:
389 try:
390 last_call[0] = shell.displayhook.prompt_count
390 last_call[0] = shell.displayhook.prompt_count
391 if not opts_prev:
391 if not opts_prev:
392 last_call[1] = args
392 last_call[1] = args
393 except:
393 except:
394 pass
394 pass
395
395
396
396
397 return filename, lineno, use_temp
397 return filename, lineno, use_temp
398
398
399 def _edit_macro(self,mname,macro):
399 def _edit_macro(self,mname,macro):
400 """open an editor with the macro data in a file"""
400 """open an editor with the macro data in a file"""
401 filename = self.shell.mktempfile(macro.value)
401 filename = self.shell.mktempfile(macro.value)
402 self.shell.hooks.editor(filename)
402 self.shell.hooks.editor(filename)
403
403
404 # and make a new macro object, to replace the old one
404 # and make a new macro object, to replace the old one
405 mfile = open(filename)
405 with open(filename) as mfile:
406 mvalue = mfile.read()
406 mvalue = mfile.read()
407 mfile.close()
408 self.shell.user_ns[mname] = Macro(mvalue)
407 self.shell.user_ns[mname] = Macro(mvalue)
409
408
410 @skip_doctest
409 @skip_doctest
411 @line_magic
410 @line_magic
412 def edit(self, parameter_s='',last_call=['','']):
411 def edit(self, parameter_s='',last_call=['','']):
413 """Bring up an editor and execute the resulting code.
412 """Bring up an editor and execute the resulting code.
414
413
415 Usage:
414 Usage:
416 %edit [options] [args]
415 %edit [options] [args]
417
416
418 %edit runs IPython's editor hook. The default version of this hook is
417 %edit runs IPython's editor hook. The default version of this hook is
419 set to call the editor specified by your $EDITOR environment variable.
418 set to call the editor specified by your $EDITOR environment variable.
420 If this isn't found, it will default to vi under Linux/Unix and to
419 If this isn't found, it will default to vi under Linux/Unix and to
421 notepad under Windows. See the end of this docstring for how to change
420 notepad under Windows. See the end of this docstring for how to change
422 the editor hook.
421 the editor hook.
423
422
424 You can also set the value of this editor via the
423 You can also set the value of this editor via the
425 ``TerminalInteractiveShell.editor`` option in your configuration file.
424 ``TerminalInteractiveShell.editor`` option in your configuration file.
426 This is useful if you wish to use a different editor from your typical
425 This is useful if you wish to use a different editor from your typical
427 default with IPython (and for Windows users who typically don't set
426 default with IPython (and for Windows users who typically don't set
428 environment variables).
427 environment variables).
429
428
430 This command allows you to conveniently edit multi-line code right in
429 This command allows you to conveniently edit multi-line code right in
431 your IPython session.
430 your IPython session.
432
431
433 If called without arguments, %edit opens up an empty editor with a
432 If called without arguments, %edit opens up an empty editor with a
434 temporary file and will execute the contents of this file when you
433 temporary file and will execute the contents of this file when you
435 close it (don't forget to save it!).
434 close it (don't forget to save it!).
436
435
437
436
438 Options:
437 Options:
439
438
440 -n <number>: open the editor at a specified line number. By default,
439 -n <number>: open the editor at a specified line number. By default,
441 the IPython editor hook uses the unix syntax 'editor +N filename', but
440 the IPython editor hook uses the unix syntax 'editor +N filename', but
442 you can configure this by providing your own modified hook if your
441 you can configure this by providing your own modified hook if your
443 favorite editor supports line-number specifications with a different
442 favorite editor supports line-number specifications with a different
444 syntax.
443 syntax.
445
444
446 -p: this will call the editor with the same data as the previous time
445 -p: this will call the editor with the same data as the previous time
447 it was used, regardless of how long ago (in your current session) it
446 it was used, regardless of how long ago (in your current session) it
448 was.
447 was.
449
448
450 -r: use 'raw' input. This option only applies to input taken from the
449 -r: use 'raw' input. This option only applies to input taken from the
451 user's history. By default, the 'processed' history is used, so that
450 user's history. By default, the 'processed' history is used, so that
452 magics are loaded in their transformed version to valid Python. If
451 magics are loaded in their transformed version to valid Python. If
453 this option is given, the raw input as typed as the command line is
452 this option is given, the raw input as typed as the command line is
454 used instead. When you exit the editor, it will be executed by
453 used instead. When you exit the editor, it will be executed by
455 IPython's own processor.
454 IPython's own processor.
456
455
457 -x: do not execute the edited code immediately upon exit. This is
456 -x: do not execute the edited code immediately upon exit. This is
458 mainly useful if you are editing programs which need to be called with
457 mainly useful if you are editing programs which need to be called with
459 command line arguments, which you can then do using %run.
458 command line arguments, which you can then do using %run.
460
459
461
460
462 Arguments:
461 Arguments:
463
462
464 If arguments are given, the following possibilities exist:
463 If arguments are given, the following possibilities exist:
465
464
466 - If the argument is a filename, IPython will load that into the
465 - If the argument is a filename, IPython will load that into the
467 editor. It will execute its contents with execfile() when you exit,
466 editor. It will execute its contents with execfile() when you exit,
468 loading any code in the file into your interactive namespace.
467 loading any code in the file into your interactive namespace.
469
468
470 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
469 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
471 The syntax is the same as in the %history magic.
470 The syntax is the same as in the %history magic.
472
471
473 - If the argument is a string variable, its contents are loaded
472 - If the argument is a string variable, its contents are loaded
474 into the editor. You can thus edit any string which contains
473 into the editor. You can thus edit any string which contains
475 python code (including the result of previous edits).
474 python code (including the result of previous edits).
476
475
477 - If the argument is the name of an object (other than a string),
476 - If the argument is the name of an object (other than a string),
478 IPython will try to locate the file where it was defined and open the
477 IPython will try to locate the file where it was defined and open the
479 editor at the point where it is defined. You can use `%edit function`
478 editor at the point where it is defined. You can use `%edit function`
480 to load an editor exactly at the point where 'function' is defined,
479 to load an editor exactly at the point where 'function' is defined,
481 edit it and have the file be executed automatically.
480 edit it and have the file be executed automatically.
482
481
483 - If the object is a macro (see %macro for details), this opens up your
482 - If the object is a macro (see %macro for details), this opens up your
484 specified editor with a temporary file containing the macro's data.
483 specified editor with a temporary file containing the macro's data.
485 Upon exit, the macro is reloaded with the contents of the file.
484 Upon exit, the macro is reloaded with the contents of the file.
486
485
487 Note: opening at an exact line is only supported under Unix, and some
486 Note: opening at an exact line is only supported under Unix, and some
488 editors (like kedit and gedit up to Gnome 2.8) do not understand the
487 editors (like kedit and gedit up to Gnome 2.8) do not understand the
489 '+NUMBER' parameter necessary for this feature. Good editors like
488 '+NUMBER' parameter necessary for this feature. Good editors like
490 (X)Emacs, vi, jed, pico and joe all do.
489 (X)Emacs, vi, jed, pico and joe all do.
491
490
492 After executing your code, %edit will return as output the code you
491 After executing your code, %edit will return as output the code you
493 typed in the editor (except when it was an existing file). This way
492 typed in the editor (except when it was an existing file). This way
494 you can reload the code in further invocations of %edit as a variable,
493 you can reload the code in further invocations of %edit as a variable,
495 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
494 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
496 the output.
495 the output.
497
496
498 Note that %edit is also available through the alias %ed.
497 Note that %edit is also available through the alias %ed.
499
498
500 This is an example of creating a simple function inside the editor and
499 This is an example of creating a simple function inside the editor and
501 then modifying it. First, start up the editor::
500 then modifying it. First, start up the editor::
502
501
503 In [1]: edit
502 In [1]: edit
504 Editing... done. Executing edited code...
503 Editing... done. Executing edited code...
505 Out[1]: 'def foo():\\n print "foo() was defined in an editing
504 Out[1]: 'def foo():\\n print "foo() was defined in an editing
506 session"\\n'
505 session"\\n'
507
506
508 We can then call the function foo()::
507 We can then call the function foo()::
509
508
510 In [2]: foo()
509 In [2]: foo()
511 foo() was defined in an editing session
510 foo() was defined in an editing session
512
511
513 Now we edit foo. IPython automatically loads the editor with the
512 Now we edit foo. IPython automatically loads the editor with the
514 (temporary) file where foo() was previously defined::
513 (temporary) file where foo() was previously defined::
515
514
516 In [3]: edit foo
515 In [3]: edit foo
517 Editing... done. Executing edited code...
516 Editing... done. Executing edited code...
518
517
519 And if we call foo() again we get the modified version::
518 And if we call foo() again we get the modified version::
520
519
521 In [4]: foo()
520 In [4]: foo()
522 foo() has now been changed!
521 foo() has now been changed!
523
522
524 Here is an example of how to edit a code snippet successive
523 Here is an example of how to edit a code snippet successive
525 times. First we call the editor::
524 times. First we call the editor::
526
525
527 In [5]: edit
526 In [5]: edit
528 Editing... done. Executing edited code...
527 Editing... done. Executing edited code...
529 hello
528 hello
530 Out[5]: "print 'hello'\\n"
529 Out[5]: "print 'hello'\\n"
531
530
532 Now we call it again with the previous output (stored in _)::
531 Now we call it again with the previous output (stored in _)::
533
532
534 In [6]: edit _
533 In [6]: edit _
535 Editing... done. Executing edited code...
534 Editing... done. Executing edited code...
536 hello world
535 hello world
537 Out[6]: "print 'hello world'\\n"
536 Out[6]: "print 'hello world'\\n"
538
537
539 Now we call it with the output #8 (stored in _8, also as Out[8])::
538 Now we call it with the output #8 (stored in _8, also as Out[8])::
540
539
541 In [7]: edit _8
540 In [7]: edit _8
542 Editing... done. Executing edited code...
541 Editing... done. Executing edited code...
543 hello again
542 hello again
544 Out[7]: "print 'hello again'\\n"
543 Out[7]: "print 'hello again'\\n"
545
544
546
545
547 Changing the default editor hook:
546 Changing the default editor hook:
548
547
549 If you wish to write your own editor hook, you can put it in a
548 If you wish to write your own editor hook, you can put it in a
550 configuration file which you load at startup time. The default hook
549 configuration file which you load at startup time. The default hook
551 is defined in the IPython.core.hooks module, and you can use that as a
550 is defined in the IPython.core.hooks module, and you can use that as a
552 starting example for further modifications. That file also has
551 starting example for further modifications. That file also has
553 general instructions on how to set a new hook for use once you've
552 general instructions on how to set a new hook for use once you've
554 defined it."""
553 defined it."""
555 opts,args = self.parse_options(parameter_s,'prxn:')
554 opts,args = self.parse_options(parameter_s,'prxn:')
556
555
557 try:
556 try:
558 filename, lineno, is_temp = self._find_edit_target(self.shell,
557 filename, lineno, is_temp = self._find_edit_target(self.shell,
559 args, opts, last_call)
558 args, opts, last_call)
560 except MacroToEdit as e:
559 except MacroToEdit as e:
561 self._edit_macro(args, e.args[0])
560 self._edit_macro(args, e.args[0])
562 return
561 return
563 except InteractivelyDefined as e:
562 except InteractivelyDefined as e:
564 print "Editing In[%i]" % e.index
563 print "Editing In[%i]" % e.index
565 args = str(e.index)
564 args = str(e.index)
566 filename, lineno, is_temp = self._find_edit_target(self.shell,
565 filename, lineno, is_temp = self._find_edit_target(self.shell,
567 args, opts, last_call)
566 args, opts, last_call)
568 if filename is None:
567 if filename is None:
569 # nothing was found, warnings have already been issued,
568 # nothing was found, warnings have already been issued,
570 # just give up.
569 # just give up.
571 return
570 return
572
571
573 # do actual editing here
572 # do actual editing here
574 print 'Editing...',
573 print 'Editing...',
575 sys.stdout.flush()
574 sys.stdout.flush()
576 try:
575 try:
577 # Quote filenames that may have spaces in them
576 # Quote filenames that may have spaces in them
578 if ' ' in filename:
577 if ' ' in filename:
579 filename = "'%s'" % filename
578 filename = "'%s'" % filename
580 self.shell.hooks.editor(filename,lineno)
579 self.shell.hooks.editor(filename,lineno)
581 except TryNext:
580 except TryNext:
582 warn('Could not open editor')
581 warn('Could not open editor')
583 return
582 return
584
583
585 # XXX TODO: should this be generalized for all string vars?
584 # XXX TODO: should this be generalized for all string vars?
586 # For now, this is special-cased to blocks created by cpaste
585 # For now, this is special-cased to blocks created by cpaste
587 if args.strip() == 'pasted_block':
586 if args.strip() == 'pasted_block':
588 with open(filename, 'r') as f:
587 with open(filename, 'r') as f:
589 self.shell.user_ns['pasted_block'] = f.read()
588 self.shell.user_ns['pasted_block'] = f.read()
590
589
591 if 'x' in opts: # -x prevents actual execution
590 if 'x' in opts: # -x prevents actual execution
592 print
591 print
593 else:
592 else:
594 print 'done. Executing edited code...'
593 print 'done. Executing edited code...'
595 with preserve_keys(self.shell.user_ns, '__file__'):
594 with preserve_keys(self.shell.user_ns, '__file__'):
596 if not is_temp:
595 if not is_temp:
597 self.shell.user_ns['__file__'] = filename
596 self.shell.user_ns['__file__'] = filename
598 if 'r' in opts: # Untranslated IPython code
597 if 'r' in opts: # Untranslated IPython code
599 with open(filename, 'r') as f:
598 with open(filename, 'r') as f:
600 source = f.read()
599 source = f.read()
601 self.shell.run_cell(source, store_history=False)
600 self.shell.run_cell(source, store_history=False)
602 else:
601 else:
603 self.shell.safe_execfile(filename, self.shell.user_ns,
602 self.shell.safe_execfile(filename, self.shell.user_ns,
604 self.shell.user_ns)
603 self.shell.user_ns)
605
604
606 if is_temp:
605 if is_temp:
607 try:
606 try:
608 return open(filename).read()
607 return open(filename).read()
609 except IOError as msg:
608 except IOError as msg:
610 if msg.filename == filename:
609 if msg.filename == filename:
611 warn('File not found. Did you forget to save?')
610 warn('File not found. Did you forget to save?')
612 return
611 return
613 else:
612 else:
614 self.shell.showtraceback()
613 self.shell.showtraceback()
General Comments 0
You need to be logged in to leave comments. Login now