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