Show More
@@ -31,6 +31,7 b' from IPython.utils import py3compat' | |||
|
31 | 31 | from IPython.utils.contexts import preserve_keys |
|
32 | 32 | from IPython.utils.path import get_py_filename, unquote_filename |
|
33 | 33 | from IPython.utils.warn import warn |
|
34 | from IPython.utils.text import get_text_list | |
|
34 | 35 | |
|
35 | 36 | #----------------------------------------------------------------------------- |
|
36 | 37 | # Magic implementation classes |
@@ -48,6 +49,7 b' range_re = re.compile(r"""' | |||
|
48 | 49 | (?P<end>\d+)?)? |
|
49 | 50 | $""", re.VERBOSE) |
|
50 | 51 | |
|
52 | ||
|
51 | 53 | def extract_code_ranges(ranges_str): |
|
52 | 54 | """Turn a string of range for %%load into 2-tuples of (start, stop) |
|
53 | 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 | 82 | @skip_doctest |
|
81 | 83 | def extract_symbols(code, symbols): |
|
82 | 84 | """ |
|
83 | Return a list of code fragments for each symbol parsed from code | |
|
84 | For example, suppose code is a string:: | |
|
85 | Return a tuple (blocks, not_found) | |
|
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 | 94 | def b(): return 42 |
|
89 | 95 | |
|
90 | class A: pass | |
|
96 | class A: pass''' | |
|
91 | 97 | |
|
92 | 98 | >>> extract_symbols(code, 'A,b') |
|
93 | ||
|
94 | ["class A: pass", "def b(): return 42"] | |
|
99 | (["class A: pass", "def b(): return 42"], []) | |
|
95 | 100 | """ |
|
96 | 101 | try: |
|
97 | 102 | py_code = ast.parse(code) |
@@ -115,12 +120,15 b' def extract_symbols(code, symbols):' | |||
|
115 | 120 | |
|
116 | 121 | # fill a list with chunks of codes for each symbol |
|
117 | 122 | blocks = [] |
|
123 | not_found = [] | |
|
118 | 124 | for symbol in symbols.split(','): |
|
119 | 125 | if symbol in symbols_lines: |
|
120 | 126 | start, end = symbols_lines[symbol] |
|
121 | 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 | 134 | class InteractivelyDefined(Exception): |
@@ -289,7 +297,15 b' class CodeMagics(Magics):' | |||
|
289 | 297 | contents = self.shell.find_user_code(args) |
|
290 | 298 | |
|
291 | 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 | 310 | if 'r' in opts: |
|
295 | 311 | ranges = opts['r'].replace(',', ' ') |
@@ -64,12 +64,12 b' def test_extract_code_ranges():' | |||
|
64 | 64 | def test_extract_symbols(): |
|
65 | 65 | source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n""" |
|
66 | 66 | symbols_args = ["a", "b", "A", "A,b", "A,a", "z"] |
|
67 | expected = [[], | |
|
68 | ["def b():\n return 42\n"], | |
|
69 | ["class A: pass\n"], | |
|
70 | ["class A: pass\n", "def b():\n return 42\n"], | |
|
71 | ["class A: pass\n"], | |
|
72 | []] | |
|
67 | expected = [([], ['a']), | |
|
68 | (["def b():\n return 42\n"], []), | |
|
69 | (["class A: pass\n"], []), | |
|
70 | (["class A: pass\n", "def b():\n return 42\n"], []), | |
|
71 | (["class A: pass\n"], ['a']), | |
|
72 | ([], ['z'])] | |
|
73 | 73 | for symbols, exp in zip(symbols_args, expected): |
|
74 | 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