Show More
@@ -18,6 +18,7 b' import io' | |||
|
18 | 18 | import os |
|
19 | 19 | import re |
|
20 | 20 | import sys |
|
21 | from itertools import chain | |
|
21 | 22 | |
|
22 | 23 | # Our own packages |
|
23 | 24 | from IPython.core.error import TryNext, StdinNotImplementedError, UsageError |
@@ -39,6 +40,43 b' class MacroToEdit(ValueError): pass' | |||
|
39 | 40 | |
|
40 | 41 | ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$") |
|
41 | 42 | |
|
43 | # To match, e.g. 8-10 1:5 :10 3- | |
|
44 | range_re = re.compile(r""" | |
|
45 | (?P<start>\d+)? | |
|
46 | ((?P<sep>[\-:]) | |
|
47 | (?P<end>\d+)?)? | |
|
48 | $""", re.VERBOSE) | |
|
49 | ||
|
50 | ||
|
51 | def extract_code_ranges(ranges_str): | |
|
52 | """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. | |
|
54 | ||
|
55 | Examples | |
|
56 | -------- | |
|
57 | list(extract_input_ranges("5-10 2")) | |
|
58 | [(4, 10), (1, 2)] | |
|
59 | """ | |
|
60 | for range_str in ranges_str.split(): | |
|
61 | rmatch = range_re.match(range_str) | |
|
62 | if not rmatch: | |
|
63 | continue | |
|
64 | sep = rmatch.group("sep") | |
|
65 | start = rmatch.group("start") | |
|
66 | end = rmatch.group("end") | |
|
67 | ||
|
68 | if sep == '-': | |
|
69 | start = int(start) - 1 if start else None | |
|
70 | end = int(end) if end else None | |
|
71 | elif sep == ':': | |
|
72 | start = int(start) - 1 if start else None | |
|
73 | end = int(end) - 1 if end else None | |
|
74 | else: | |
|
75 | end = int(start) | |
|
76 | start = int(start) - 1 | |
|
77 | yield (start, end) | |
|
78 | ||
|
79 | ||
|
42 | 80 | class InteractivelyDefined(Exception): |
|
43 | 81 | """Exception for interactively defined variable in magic_edit""" |
|
44 | 82 | def __init__(self, index): |
@@ -174,6 +212,11 b' class CodeMagics(Magics):' | |||
|
174 | 212 | |
|
175 | 213 | Options: |
|
176 | 214 | -------- |
|
215 | -r <lines>: Specify lines or ranges of lines to load from the source. | |
|
216 | Ranges could be specified as x-y (x..y) or in python-style x:y | |
|
217 | (x..(y-1)). Both limits x and y can be left blank (meaning the | |
|
218 | beginning and end of the file, respectively). | |
|
219 | ||
|
177 | 220 | -y : Don't ask confirmation for loading source above 200 000 characters. |
|
178 | 221 | |
|
179 | 222 | This magic command can either take a local filename, a URL, an history |
@@ -185,15 +228,27 b' class CodeMagics(Magics):' | |||
|
185 | 228 | %load 7-27 |
|
186 | 229 | %load myMacro |
|
187 | 230 | %load http://www.example.com/myscript.py |
|
231 | %load -r 5-10 myscript.py | |
|
232 | %load -r 10-20,30,40: foo.py | |
|
188 | 233 | """ |
|
189 | opts,args = self.parse_options(arg_s,'y') | |
|
234 | opts,args = self.parse_options(arg_s,'yr:') | |
|
235 | ||
|
190 | 236 | if not args: |
|
191 | 237 | raise UsageError('Missing filename, URL, input history range, ' |
|
192 | 238 | 'or macro.') |
|
193 | 239 | |
|
194 | 240 | contents = self.shell.find_user_code(args) |
|
241 | ||
|
242 | if 'r' in opts: | |
|
243 | ranges = opts['r'].replace(',', ' ') | |
|
244 | lines = contents.split('\n') | |
|
245 | slices = extract_code_ranges(ranges) | |
|
246 | contents = [lines[slice(*slc)] for slc in slices] | |
|
247 | contents = '\n'.join(chain.from_iterable(contents)) | |
|
248 | ||
|
195 | 249 | l = len(contents) |
|
196 | 250 | |
|
251 | ||
|
197 | 252 | # 200 000 is ~ 2500 full 80 caracter lines |
|
198 | 253 | # so in average, more than 5000 lines |
|
199 | 254 | if l > 200000 and 'y' not in opts: |
@@ -45,6 +45,21 b' from IPython.utils.process import find_cmd' | |||
|
45 | 45 | @magic.magics_class |
|
46 | 46 | class DummyMagics(magic.Magics): pass |
|
47 | 47 | |
|
48 | def test_extract_code_ranges(): | |
|
49 | instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :" | |
|
50 | expected = [(0, 1), | |
|
51 | (2, 3), | |
|
52 | (4, 6), | |
|
53 | (6, 9), | |
|
54 | (9, 14), | |
|
55 | (16, None), | |
|
56 | (None, 9), | |
|
57 | (9, None), | |
|
58 | (None, 13), | |
|
59 | (None, None)] | |
|
60 | actual = list(code.extract_code_ranges(instr)) | |
|
61 | nt.assert_equal(actual, expected) | |
|
62 | ||
|
48 | 63 | def test_rehashx(): |
|
49 | 64 | # clear up everything |
|
50 | 65 | _ip = get_ipython() |
General Comments 0
You need to be logged in to leave comments.
Login now