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