Show More
@@ -31,6 +31,7 b' 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 | from IPython.utils.text import get_text_list | |||
34 |
|
35 | |||
35 | #----------------------------------------------------------------------------- |
|
36 | #----------------------------------------------------------------------------- | |
36 | # Magic implementation classes |
|
37 | # Magic implementation classes | |
@@ -48,6 +49,7 b' range_re = re.compile(r"""' | |||||
48 | (?P<end>\d+)?)? |
|
49 | (?P<end>\d+)?)? | |
49 | $""", re.VERBOSE) |
|
50 | $""", re.VERBOSE) | |
50 |
|
51 | |||
|
52 | ||||
51 | def extract_code_ranges(ranges_str): |
|
53 | def extract_code_ranges(ranges_str): | |
52 | """Turn a string of range for %%load into 2-tuples of (start, stop) |
|
54 | """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. |
|
55 | ready to use as a slice of the content splitted by lines. | |
@@ -80,18 +82,21 b' def extract_code_ranges(ranges_str):' | |||||
80 | @skip_doctest |
|
82 | @skip_doctest | |
81 | def extract_symbols(code, symbols): |
|
83 | def extract_symbols(code, symbols): | |
82 | """ |
|
84 | """ | |
83 | Return a list of code fragments for each symbol parsed from code |
|
85 | Return a tuple (blocks, not_found) | |
84 | For example, suppose code is a string:: |
|
86 | where ``blocks`` is a list of code fragments | |
|
87 | for each symbol parsed from code, and ``not_found`` are | |||
|
88 | symbols not found in the code. | |||
|
89 | ||||
|
90 | For example:: | |||
85 |
|
91 | |||
86 | a = 10 |
|
92 | >>> code = '''a = 10 | |
87 |
|
93 | |||
88 | def b(): return 42 |
|
94 | def b(): return 42 | |
89 |
|
95 | |||
90 | class A: pass |
|
96 | class A: pass''' | |
91 |
|
97 | |||
92 | >>> extract_symbols(code, 'A,b') |
|
98 | >>> extract_symbols(code, 'A,b') | |
93 |
|
99 | (["class A: pass", "def b(): return 42"], []) | ||
94 | ["class A: pass", "def b(): return 42"] |
|
|||
95 | """ |
|
100 | """ | |
96 | try: |
|
101 | try: | |
97 | py_code = ast.parse(code) |
|
102 | py_code = ast.parse(code) | |
@@ -115,12 +120,15 b' def extract_symbols(code, symbols):' | |||||
115 |
|
120 | |||
116 | # fill a list with chunks of codes for each symbol |
|
121 | # fill a list with chunks of codes for each symbol | |
117 | blocks = [] |
|
122 | blocks = [] | |
|
123 | not_found = [] | |||
118 | for symbol in symbols.split(','): |
|
124 | for symbol in symbols.split(','): | |
119 | if symbol in symbols_lines: |
|
125 | if symbol in symbols_lines: | |
120 | start, end = symbols_lines[symbol] |
|
126 | start, end = symbols_lines[symbol] | |
121 | blocks.append('\n'.join(code[start:end]) + '\n') |
|
127 | blocks.append('\n'.join(code[start:end]) + '\n') | |
|
128 | else: | |||
|
129 | not_found.append(symbol) | |||
122 |
|
130 | |||
123 | return blocks |
|
131 | return blocks, not_found | |
124 |
|
132 | |||
125 |
|
133 | |||
126 | class InteractivelyDefined(Exception): |
|
134 | class InteractivelyDefined(Exception): | |
@@ -289,7 +297,15 b' class CodeMagics(Magics):' | |||||
289 | contents = self.shell.find_user_code(args) |
|
297 | contents = self.shell.find_user_code(args) | |
290 |
|
298 | |||
291 | if 's' in opts: |
|
299 | if 's' in opts: | |
292 |
|
|
300 | blocks, not_found = extract_symbols(contents, opts['s']) | |
|
301 | if len(not_found) == 1: | |||
|
302 | warn('The symbol `%s` was not found' % not_found[0]) | |||
|
303 | elif len(not_found) > 1: | |||
|
304 | warn('The symbols %s were not found' % get_text_list(not_found, | |||
|
305 | wrap_item_with='`') | |||
|
306 | ) | |||
|
307 | ||||
|
308 | contents = '\n'.join(blocks) | |||
293 |
|
309 | |||
294 | if 'r' in opts: |
|
310 | if 'r' in opts: | |
295 | ranges = opts['r'].replace(',', ' ') |
|
311 | ranges = opts['r'].replace(',', ' ') |
@@ -64,12 +64,12 b' def test_extract_code_ranges():' | |||||
64 | def test_extract_symbols(): |
|
64 | def test_extract_symbols(): | |
65 | source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n""" |
|
65 | source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n""" | |
66 | symbols_args = ["a", "b", "A", "A,b", "A,a", "z"] |
|
66 | symbols_args = ["a", "b", "A", "A,b", "A,a", "z"] | |
67 | expected = [[], |
|
67 | expected = [([], ['a']), | |
68 | ["def b():\n return 42\n"], |
|
68 | (["def b():\n return 42\n"], []), | |
69 | ["class A: pass\n"], |
|
69 | (["class A: pass\n"], []), | |
70 | ["class A: pass\n", "def b():\n return 42\n"], |
|
70 | (["class A: pass\n", "def b():\n return 42\n"], []), | |
71 | ["class A: pass\n"], |
|
71 | (["class A: pass\n"], ['a']), | |
72 | []] |
|
72 | ([], ['z'])] | |
73 | for symbols, exp in zip(symbols_args, expected): |
|
73 | for symbols, exp in zip(symbols_args, expected): | |
74 | nt.assert_equal(code.extract_symbols(source, symbols), exp) |
|
74 | nt.assert_equal(code.extract_symbols(source, symbols), exp) | |
75 |
|
75 |
General Comments 0
You need to be logged in to leave comments.
Login now