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