Show More
@@ -17,6 +17,7 b' import inspect' | |||||
17 | import io |
|
17 | import io | |
18 | import json |
|
18 | import json | |
19 | import os |
|
19 | import os | |
|
20 | import re | |||
20 | import sys |
|
21 | import sys | |
21 | from urllib2 import urlopen |
|
22 | from urllib2 import urlopen | |
22 |
|
23 | |||
@@ -39,6 +40,13 b' from IPython.utils.warn import warn' | |||||
39 | # Used for exception handling in magic_edit |
|
40 | # Used for exception handling in magic_edit | |
40 | class MacroToEdit(ValueError): pass |
|
41 | class MacroToEdit(ValueError): pass | |
41 |
|
42 | |||
|
43 | ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$") | |||
|
44 | ||||
|
45 | class InteractivelyDefined(Exception): | |||
|
46 | """Exception for interactively defined variable in magic_edit""" | |||
|
47 | def __init__(self, index): | |||
|
48 | self.index = index | |||
|
49 | ||||
42 |
|
50 | |||
43 | @magics_class |
|
51 | @magics_class | |
44 | class CodeMagics(Magics): |
|
52 | class CodeMagics(Magics): | |
@@ -274,7 +282,7 b' class CodeMagics(Magics):' | |||||
274 | if filename is None: |
|
282 | if filename is None: | |
275 | warn("Argument given (%s) can't be found as a variable " |
|
283 | warn("Argument given (%s) can't be found as a variable " | |
276 | "or as a filename." % args) |
|
284 | "or as a filename." % args) | |
277 | return |
|
285 | return (None, None, None) | |
278 | use_temp = False |
|
286 | use_temp = False | |
279 |
|
287 | |||
280 | except DataIsObject: |
|
288 | except DataIsObject: | |
@@ -302,10 +310,16 b' class CodeMagics(Magics):' | |||||
302 | data = attr |
|
310 | data = attr | |
303 | break |
|
311 | break | |
304 |
|
312 | |||
|
313 | m = ipython_input_pat.match(os.path.basename(filename)) | |||
|
314 | if m: | |||
|
315 | raise InteractivelyDefined(int(m.groups()[0])) | |||
|
316 | ||||
305 | datafile = 1 |
|
317 | datafile = 1 | |
306 | if filename is None: |
|
318 | if filename is None: | |
307 | filename = make_filename(args) |
|
319 | filename = make_filename(args) | |
308 | datafile = 1 |
|
320 | datafile = 1 | |
|
321 | if filename is not None: | |||
|
322 | # only warn about this if we get a real name | |||
309 | warn('Could not find file where `%s` is defined.\n' |
|
323 | warn('Could not find file where `%s` is defined.\n' | |
310 | 'Opening a file named `%s`' % (args, filename)) |
|
324 | 'Opening a file named `%s`' % (args, filename)) | |
311 | # Now, make sure we can actually read the source (if it was |
|
325 | # Now, make sure we can actually read the source (if it was | |
@@ -316,9 +330,9 b' class CodeMagics(Magics):' | |||||
316 | if lineno is None: |
|
330 | if lineno is None: | |
317 | filename = make_filename(args) |
|
331 | filename = make_filename(args) | |
318 | if filename is None: |
|
332 | if filename is None: | |
319 |
warn('The file |
|
333 | warn('The file where `%s` was defined ' | |
320 |
'cannot be read.' % |
|
334 | 'cannot be read or found.' % data) | |
321 | return |
|
335 | return (None, None, None) | |
322 | use_temp = False |
|
336 | use_temp = False | |
323 |
|
337 | |||
324 | if use_temp: |
|
338 | if use_temp: | |
@@ -491,6 +505,15 b' class CodeMagics(Magics):' | |||||
491 | except MacroToEdit as e: |
|
505 | except MacroToEdit as e: | |
492 | self._edit_macro(args, e.args[0]) |
|
506 | self._edit_macro(args, e.args[0]) | |
493 | return |
|
507 | return | |
|
508 | except InteractivelyDefined as e: | |||
|
509 | print "Editing In[%i]" % e.index | |||
|
510 | args = str(e.index) | |||
|
511 | filename, lineno, is_temp = self._find_edit_target(self.shell, | |||
|
512 | args, opts, last_call) | |||
|
513 | if filename is None: | |||
|
514 | # nothing was found, warnings have already been issued, | |||
|
515 | # just give up. | |||
|
516 | return | |||
494 |
|
517 | |||
495 | # do actual editing here |
|
518 | # do actual editing here | |
496 | print 'Editing...', |
|
519 | print 'Editing...', |
@@ -296,7 +296,7 b' def find_file(obj):' | |||||
296 | pass |
|
296 | pass | |
297 | except: |
|
297 | except: | |
298 | pass |
|
298 | pass | |
299 | return fname |
|
299 | return cast_unicode(fname) | |
300 |
|
300 | |||
301 |
|
301 | |||
302 | def find_source_lines(obj): |
|
302 | def find_source_lines(obj): | |
@@ -326,6 +326,8 b' def find_source_lines(obj):' | |||||
326 | # For instances, try the class object like getsource() does |
|
326 | # For instances, try the class object like getsource() does | |
327 | if hasattr(obj, '__class__'): |
|
327 | if hasattr(obj, '__class__'): | |
328 | lineno = inspect.getsourcelines(obj.__class__)[1] |
|
328 | lineno = inspect.getsourcelines(obj.__class__)[1] | |
|
329 | else: | |||
|
330 | lineno = None | |||
329 | except: |
|
331 | except: | |
330 | return None |
|
332 | return None | |
331 |
|
333 |
@@ -28,7 +28,7 b' from IPython.core.magic import (Magics, magics_class, line_magic,' | |||||
28 | cell_magic, line_cell_magic, |
|
28 | cell_magic, line_cell_magic, | |
29 | register_line_magic, register_cell_magic, |
|
29 | register_line_magic, register_cell_magic, | |
30 | register_line_cell_magic) |
|
30 | register_line_cell_magic) | |
31 | from IPython.core.magics import execution, script |
|
31 | from IPython.core.magics import execution, script, code | |
32 | from IPython.nbformat.v3.tests.nbexamples import nb0 |
|
32 | from IPython.nbformat.v3.tests.nbexamples import nb0 | |
33 | from IPython.nbformat import current |
|
33 | from IPython.nbformat import current | |
34 | from IPython.testing import decorators as dec |
|
34 | from IPython.testing import decorators as dec | |
@@ -792,3 +792,49 b' def test_store():' | |||||
792 | ip.user_ns['var'] = 39 |
|
792 | ip.user_ns['var'] = 39 | |
793 | ip.run_line_magic('store' , '-r') |
|
793 | ip.run_line_magic('store' , '-r') | |
794 | nt.assert_equal(ip.user_ns['var'], 39) |
|
794 | nt.assert_equal(ip.user_ns['var'], 39) | |
|
795 | ||||
|
796 | ||||
|
797 | def _run_edit_test(arg_s, exp_filename=None, | |||
|
798 | exp_lineno=-1, | |||
|
799 | exp_contents=None, | |||
|
800 | exp_is_temp=None): | |||
|
801 | ip = get_ipython() | |||
|
802 | M = code.CodeMagics(ip) | |||
|
803 | last_call = ['',''] | |||
|
804 | opts,args = M.parse_options(arg_s,'prxn:') | |||
|
805 | filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call) | |||
|
806 | ||||
|
807 | if exp_filename is not None: | |||
|
808 | nt.assert_equal(exp_filename, filename) | |||
|
809 | if exp_contents is not None: | |||
|
810 | with io.open(filename, 'r') as f: | |||
|
811 | contents = f.read() | |||
|
812 | nt.assert_equal(exp_contents, contents) | |||
|
813 | if exp_lineno != -1: | |||
|
814 | nt.assert_equal(exp_lineno, lineno) | |||
|
815 | if exp_is_temp is not None: | |||
|
816 | nt.assert_equal(exp_is_temp, is_temp) | |||
|
817 | ||||
|
818 | ||||
|
819 | def test_edit_interactive(): | |||
|
820 | """%edit on interactively defined objects""" | |||
|
821 | ip = get_ipython() | |||
|
822 | n = ip.execution_count | |||
|
823 | ip.run_cell(u"def foo(): return 1", store_history=True) | |||
|
824 | ||||
|
825 | try: | |||
|
826 | _run_edit_test("foo") | |||
|
827 | except code.InteractivelyDefined as e: | |||
|
828 | nt.assert_equal(e.index, n) | |||
|
829 | else: | |||
|
830 | nt.fail("Should have raised InteractivelyDefined") | |||
|
831 | ||||
|
832 | ||||
|
833 | def test_edit_cell(): | |||
|
834 | """%edit [cell id]""" | |||
|
835 | ip = get_ipython() | |||
|
836 | ||||
|
837 | ip.run_cell(u"def foo(): return 1", store_history=True) | |||
|
838 | ||||
|
839 | # test | |||
|
840 | _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True) |
General Comments 0
You need to be logged in to leave comments.
Login now