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