Show More
@@ -0,0 +1,298 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | """ | |
|
3 | Classes and functions for prefiltering (transforming) a line of user input. | |
|
4 | This module is responsible, primarily, for breaking the line up into useful | |
|
5 | pieces and triggering the appropriate handlers in iplib to do the actual | |
|
6 | transforming work. | |
|
7 | """ | |
|
8 | __docformat__ = "restructuredtext en" | |
|
9 | ||
|
10 | import re | |
|
11 | import IPython.ipapi | |
|
12 | ||
|
13 | class LineInfo(object): | |
|
14 | """A single line of input and associated info. | |
|
15 | ||
|
16 | Includes the following as properties: | |
|
17 | ||
|
18 | line | |
|
19 | The original, raw line | |
|
20 | ||
|
21 | continue_prompt | |
|
22 | Is this line a continuation in a sequence of multiline input? | |
|
23 | ||
|
24 | pre | |
|
25 | The initial esc character or whitespace. | |
|
26 | ||
|
27 | preChar | |
|
28 | The escape character(s) in pre or the empty string if there isn't one. | |
|
29 | Note that '!!' is a possible value for preChar. Otherwise it will | |
|
30 | always be a single character. | |
|
31 | ||
|
32 | preWhitespace | |
|
33 | The leading whitespace from pre if it exists. If there is a preChar, | |
|
34 | this is just ''. | |
|
35 | ||
|
36 | iFun | |
|
37 | The 'function part', which is basically the maximal initial sequence | |
|
38 | of valid python identifiers and the '.' character. This is what is | |
|
39 | checked for alias and magic transformations, used for auto-calling, | |
|
40 | etc. | |
|
41 | ||
|
42 | theRest | |
|
43 | Everything else on the line. | |
|
44 | """ | |
|
45 | def __init__(self, line, continue_prompt): | |
|
46 | self.line = line | |
|
47 | self.continue_prompt = continue_prompt | |
|
48 | self.pre, self.iFun, self.theRest = splitUserInput(line) | |
|
49 | ||
|
50 | self.preChar = self.pre.strip() | |
|
51 | if self.preChar: | |
|
52 | self.preWhitespace = '' # No whitespace allowd before esc chars | |
|
53 | else: | |
|
54 | self.preWhitespace = self.pre | |
|
55 | ||
|
56 | self._oinfo = None | |
|
57 | ||
|
58 | def ofind(self, ip): | |
|
59 | """Do a full, attribute-walking lookup of the iFun in the various | |
|
60 | namespaces for the given IPython InteractiveShell instance. | |
|
61 | ||
|
62 | Return a dict with keys: found,obj,ospace,ismagic | |
|
63 | ||
|
64 | Note: can cause state changes because of calling getattr, but should | |
|
65 | only be run if autocall is on and if the line hasn't matched any | |
|
66 | other, less dangerous handlers. | |
|
67 | ||
|
68 | Does cache the results of the call, so can be called multiple times | |
|
69 | without worrying about *further* damaging state. | |
|
70 | """ | |
|
71 | if not self._oinfo: | |
|
72 | self._oinfo = ip._ofind(self.iFun) | |
|
73 | return self._oinfo | |
|
74 | ||
|
75 | ||
|
76 | def splitUserInput(line, pattern=None): | |
|
77 | """Split user input into pre-char/whitespace, function part and rest. | |
|
78 | ||
|
79 | Mostly internal to this module, but also used by iplib.expand_aliases, | |
|
80 | which passes in a shell pattern. | |
|
81 | """ | |
|
82 | # It seems to me that the shell splitting should be a separate method. | |
|
83 | ||
|
84 | if not pattern: | |
|
85 | pattern = line_split | |
|
86 | match = pattern.match(line) | |
|
87 | if not match: | |
|
88 | #print "match failed for line '%s'" % line | |
|
89 | try: | |
|
90 | iFun,theRest = line.split(None,1) | |
|
91 | except ValueError: | |
|
92 | #print "split failed for line '%s'" % line | |
|
93 | iFun,theRest = line,'' | |
|
94 | pre = re.match('^(\s*)(.*)',line).groups()[0] | |
|
95 | else: | |
|
96 | pre,iFun,theRest = match.groups() | |
|
97 | ||
|
98 | # iFun has to be a valid python identifier, so it better be only pure | |
|
99 | # ascii, no unicode: | |
|
100 | try: | |
|
101 | iFun = iFun.encode('ascii') | |
|
102 | except UnicodeEncodeError: | |
|
103 | theRest = iFun + u' ' + theRest | |
|
104 | iFun = u'' | |
|
105 | ||
|
106 | #print 'line:<%s>' % line # dbg | |
|
107 | #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun.strip(),theRest) # dbg | |
|
108 | return pre,iFun.strip(),theRest | |
|
109 | ||
|
110 | ||
|
111 | # RegExp for splitting line contents into pre-char//first word-method//rest. | |
|
112 | # For clarity, each group in on one line. | |
|
113 | ||
|
114 | # WARNING: update the regexp if the escapes in iplib are changed, as they | |
|
115 | # are hardwired in. | |
|
116 | ||
|
117 | # Although it's not solely driven by the regex, note that: | |
|
118 | # ,;/% only trigger if they are the first character on the line | |
|
119 | # ! and !! trigger if they are first char(s) *or* follow an indent | |
|
120 | # ? triggers as first or last char. | |
|
121 | ||
|
122 | # The three parts of the regex are: | |
|
123 | # 1) pre: pre_char *or* initial whitespace | |
|
124 | # 2) iFun: first word/method (mix of \w and '.') | |
|
125 | # 3) theRest: rest of line | |
|
126 | line_split = re.compile(r'^([,;/%?]|!!?|\s*)' | |
|
127 | r'\s*([\w\.]+)\s*' | |
|
128 | r'(.*)$') | |
|
129 | ||
|
130 | shell_line_split = re.compile(r'^(\s*)(\S*\s*)(.*$)') | |
|
131 | ||
|
132 | def prefilter(line_info, ip): | |
|
133 | """Call one of the passed-in InteractiveShell's handler preprocessors, | |
|
134 | depending on the form of the line. Return the results, which must be a | |
|
135 | value, even if it's a blank ('').""" | |
|
136 | # Note: the order of these checks does matter. | |
|
137 | for check in [ checkEmacs, | |
|
138 | checkIPyAutocall, | |
|
139 | checkMultiLineShell, | |
|
140 | checkEscChars, | |
|
141 | checkPythonChars, | |
|
142 | checkAutomagic, | |
|
143 | checkAlias, | |
|
144 | checkAutocall, | |
|
145 | ]: | |
|
146 | handler = check(line_info, ip) | |
|
147 | if handler: | |
|
148 | return handler(line_info) | |
|
149 | ||
|
150 | return ip.handle_normal(line_info) | |
|
151 | ||
|
152 | # Handler checks | |
|
153 | # | |
|
154 | # All have the same interface: they take a LineInfo object and a ref to the | |
|
155 | # iplib.InteractiveShell object. They check the line to see if a particular | |
|
156 | # handler should be called, and return either a handler or None. The | |
|
157 | # handlers which they return are *bound* methods of the InteractiveShell | |
|
158 | # object. | |
|
159 | # | |
|
160 | # In general, these checks should only take responsibility for their 'own' | |
|
161 | # handler. If it doesn't get triggered, they should just return None and | |
|
162 | # let the rest of the check sequence run. | |
|
163 | def checkEmacs(l_info,ip): | |
|
164 | "Emacs ipython-mode tags certain input lines." | |
|
165 | if l_info.line.endswith('# PYTHON-MODE'): | |
|
166 | return ip.handle_emacs | |
|
167 | else: | |
|
168 | return None | |
|
169 | ||
|
170 | def checkIPyAutocall(l_info,ip): | |
|
171 | "Instances of IPyAutocall in user_ns get autocalled immediately" | |
|
172 | obj = ip.user_ns.get(l_info.iFun, None) | |
|
173 | if isinstance(obj, IPython.ipapi.IPyAutocall): | |
|
174 | obj.set_ip(ip.api) | |
|
175 | return ip.handle_auto | |
|
176 | else: | |
|
177 | return None | |
|
178 | ||
|
179 | ||
|
180 | def checkMultiLineShell(l_info,ip): | |
|
181 | "Allow ! and !! in multi-line statements if multi_line_specials is on" | |
|
182 | # Note that this one of the only places we check the first character of | |
|
183 | # iFun and *not* the preChar. Also note that the below test matches | |
|
184 | # both ! and !!. | |
|
185 | if l_info.continue_prompt \ | |
|
186 | and ip.rc.multi_line_specials \ | |
|
187 | and l_info.iFun.startswith(ip.ESC_SHELL): | |
|
188 | return ip.handle_shell_escape | |
|
189 | else: | |
|
190 | return None | |
|
191 | ||
|
192 | def checkEscChars(l_info,ip): | |
|
193 | """Check for escape character and return either a handler to handle it, | |
|
194 | or None if there is no escape char.""" | |
|
195 | if l_info.line[-1] == ip.ESC_HELP \ | |
|
196 | and l_info.preChar != ip.ESC_SHELL \ | |
|
197 | and l_info.preChar != ip.ESC_SH_CAP: | |
|
198 | # the ? can be at the end, but *not* for either kind of shell escape, | |
|
199 | # because a ? can be a vaild final char in a shell cmd | |
|
200 | return ip.handle_help | |
|
201 | elif l_info.preChar in ip.esc_handlers: | |
|
202 | return ip.esc_handlers[l_info.preChar] | |
|
203 | else: | |
|
204 | return None | |
|
205 | ||
|
206 | def checkPythonChars(l_info,ip): | |
|
207 | """If the 'rest' of the line begins with an (in)equality, assginment, | |
|
208 | function call or tuple comma, we should simply execute the line | |
|
209 | (regardless of whether or not there's a possible alias, automagic or | |
|
210 | autocall expansion). This both avoids spurious geattr() accesses on | |
|
211 | objects upon assignment, and also allows users to assign to either alias | |
|
212 | or magic names true python variables (the magic/alias systems always | |
|
213 | take second seat to true python code). E.g. ls='hi', or ls,that=1,2""" | |
|
214 | if l_info.theRest and l_info.theRest[0] in '!=()<>,+*/%^&|': | |
|
215 | return ip.handle_normal | |
|
216 | else: | |
|
217 | return None | |
|
218 | ||
|
219 | def checkAutomagic(l_info,ip): | |
|
220 | """If the iFun is magic, and automagic is on, run it. Note: normal, | |
|
221 | non-auto magic would already have been triggered via '%' in | |
|
222 | check_esc_chars. This just checks for automagic.""" | |
|
223 | if not ip.rc.automagic or not hasattr(ip,'magic_'+l_info.iFun): | |
|
224 | return None | |
|
225 | ||
|
226 | # We have a likely magic method. Make sure we should actually call it. | |
|
227 | if l_info.continue_prompt and not ip.rc.multi_line_specials: | |
|
228 | return None | |
|
229 | ||
|
230 | head = l_info.iFun.split('.',1)[0] | |
|
231 | if isShadowed(head,ip): | |
|
232 | return None | |
|
233 | ||
|
234 | return ip.handle_magic | |
|
235 | ||
|
236 | ||
|
237 | def checkAlias(l_info,ip): | |
|
238 | "Check if the initital identifier on the line is an alias." | |
|
239 | # Note: aliases can not contain '.' | |
|
240 | head = l_info.iFun.split('.',1)[0] | |
|
241 | ||
|
242 | if l_info.iFun not in ip.alias_table \ | |
|
243 | or head not in ip.alias_table \ | |
|
244 | or isShadowed(head,ip): | |
|
245 | return None | |
|
246 | ||
|
247 | return ip.handle_alias | |
|
248 | ||
|
249 | ||
|
250 | def checkAutocall(l_info,ip): | |
|
251 | "Check if the initial word/function is callable and autocall is on." | |
|
252 | if not ip.rc.autocall: | |
|
253 | return None | |
|
254 | ||
|
255 | oinfo = l_info.ofind(ip) # This can mutate state via getattr | |
|
256 | if not oinfo['found']: | |
|
257 | return None | |
|
258 | ||
|
259 | if callable(oinfo['obj']) \ | |
|
260 | and (not re_exclude_auto.match(l_info.theRest)) \ | |
|
261 | and re_fun_name.match(l_info.iFun): | |
|
262 | #print 'going auto' # dbg | |
|
263 | return ip.handle_auto | |
|
264 | else: | |
|
265 | #print 'was callable?', callable(l_info.oinfo['obj']) # dbg | |
|
266 | return None | |
|
267 | ||
|
268 | # RegExp to identify potential function names | |
|
269 | re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') | |
|
270 | ||
|
271 | # RegExp to exclude strings with this start from autocalling. In | |
|
272 | # particular, all binary operators should be excluded, so that if foo is | |
|
273 | # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The | |
|
274 | # characters '!=()' don't need to be checked for, as the checkPythonChars | |
|
275 | # routine explicitely does so, to catch direct calls and rebindings of | |
|
276 | # existing names. | |
|
277 | ||
|
278 | # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise | |
|
279 | # it affects the rest of the group in square brackets. | |
|
280 | re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' | |
|
281 | r'|^is |^not |^in |^and |^or ') | |
|
282 | ||
|
283 | # try to catch also methods for stuff in lists/tuples/dicts: off | |
|
284 | # (experimental). For this to work, the line_split regexp would need | |
|
285 | # to be modified so it wouldn't break things at '['. That line is | |
|
286 | # nasty enough that I shouldn't change it until I can test it _well_. | |
|
287 | #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') | |
|
288 | ||
|
289 | # Handler Check Utilities | |
|
290 | def isShadowed(identifier,ip): | |
|
291 | """Is the given identifier defined in one of the namespaces which shadow | |
|
292 | the alias and magic namespaces? Note that an identifier is different | |
|
293 | than iFun, because it can not contain a '.' character.""" | |
|
294 | # This is much safer than calling ofind, which can change state | |
|
295 | return (identifier in ip.user_ns \ | |
|
296 | or identifier in ip.internal_ns \ | |
|
297 | or identifier in ip.ns_table['builtin']) | |
|
298 |
@@ -0,0 +1,200 b'' | |||
|
1 | """Test the various handlers which do the actual rewriting of the line.""" | |
|
2 | ||
|
3 | from StringIO import StringIO | |
|
4 | import sys | |
|
5 | ||
|
6 | failures = [] | |
|
7 | num_tests = 0 | |
|
8 | ||
|
9 | def run(tests): | |
|
10 | """Loop through a list of (pre, post) inputs, where pre is the string | |
|
11 | handed to ipython, and post is how that string looks after it's been | |
|
12 | transformed (i.e. ipython's notion of _i)""" | |
|
13 | for pre, post in tests: | |
|
14 | global num_tests | |
|
15 | num_tests += 1 | |
|
16 | ip.runlines(pre) | |
|
17 | ip.runlines('_i') # Not sure why I need this... | |
|
18 | actual = ip.user_ns['_i'] | |
|
19 | if actual != None: actual = actual.rstrip('\n') | |
|
20 | if actual != post: | |
|
21 | failures.append('Expected %r to become %r, found %r' % ( | |
|
22 | pre, post, actual)) | |
|
23 | ||
|
24 | ||
|
25 | # Shutdown stdout/stderr so that ipython isn't noisy during tests. Have to | |
|
26 | # do this *before* importing IPython below. | |
|
27 | # | |
|
28 | # NOTE: this means that, if you stick print statements into code as part of | |
|
29 | # debugging, you won't see the results (unless you comment out some of the | |
|
30 | # below). I keep on doing this, so apparently it's easy. Or I am an idiot. | |
|
31 | old_stdout = sys.stdout | |
|
32 | old_stderr = sys.stderr | |
|
33 | ||
|
34 | sys.stdout = StringIO() | |
|
35 | sys.stderr = StringIO() | |
|
36 | ||
|
37 | import IPython | |
|
38 | import IPython.ipapi | |
|
39 | ||
|
40 | IPython.Shell.start() | |
|
41 | ip = IPython.ipapi.get() | |
|
42 | ||
|
43 | class CallableIndexable(object): | |
|
44 | def __getitem__(self, idx): return True | |
|
45 | def __call__(self, *args, **kws): return True | |
|
46 | ||
|
47 | ||
|
48 | try: | |
|
49 | # alias expansion | |
|
50 | ||
|
51 | # We're using 'true' as our syscall of choice because it doesn't | |
|
52 | # write anything to stdout. | |
|
53 | ||
|
54 | # Turn off actual execution of aliases, because it's noisy | |
|
55 | old_system_cmd = ip.IP.system | |
|
56 | ip.IP.system = lambda cmd: None | |
|
57 | ||
|
58 | ||
|
59 | ip.IP.alias_table['an_alias'] = (0, 'true') | |
|
60 | # These are useful for checking a particular recursive alias issue | |
|
61 | ip.IP.alias_table['top'] = (0, 'd:/cygwin/top') | |
|
62 | ip.IP.alias_table['d'] = (0, 'true') | |
|
63 | run([("an_alias", '_ip.system("true ")'), # alias | |
|
64 | # Below: recursive aliases should expand whitespace-surrounded | |
|
65 | # chars, *not* initial chars which happen to be aliases: | |
|
66 | ("top", '_ip.system("d:/cygwin/top ")'), | |
|
67 | ]) | |
|
68 | ip.IP.system = old_system_cmd | |
|
69 | ||
|
70 | ||
|
71 | call_idx = CallableIndexable() | |
|
72 | ip.to_user_ns('call_idx') | |
|
73 | ||
|
74 | # For many of the below, we're also checking that leading whitespace | |
|
75 | # turns off the esc char, which it should unless there is a continuation | |
|
76 | # line. | |
|
77 | run([('"no change"', '"no change"'), # normal | |
|
78 | ("!true", '_ip.system("true")'), # shell_escapes | |
|
79 | ("!! true", '_ip.magic("sx true")'), # shell_escapes + magic | |
|
80 | ("!!true", '_ip.magic("sx true")'), # shell_escapes + magic | |
|
81 | ("%lsmagic", '_ip.magic("lsmagic ")'), # magic | |
|
82 | ("lsmagic", '_ip.magic("lsmagic ")'), # magic | |
|
83 | ("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache | |
|
84 | ||
|
85 | # post-esc-char whitespace goes inside | |
|
86 | ("! true", '_ip.system(" true")'), | |
|
87 | ||
|
88 | # Leading whitespace generally turns off escape characters | |
|
89 | (" ! true", ' ! true'), | |
|
90 | (" !true", ' !true'), | |
|
91 | ||
|
92 | # handle_help | |
|
93 | ||
|
94 | # These are weak tests -- just looking at what the help handlers | |
|
95 | # logs, which is not how it really does its work. But it still | |
|
96 | # lets us check the key paths through the handler. | |
|
97 | ||
|
98 | ("x=1 # what?", "x=1 # what?"), # no help if valid python | |
|
99 | ("len?", "#?len"), # this is what help logs when it runs | |
|
100 | ("len??", "#?len?"), | |
|
101 | ("?len", "#?len"), | |
|
102 | ]) | |
|
103 | ||
|
104 | # multi_line_specials | |
|
105 | ip.options.multi_line_specials = 0 | |
|
106 | # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion | |
|
107 | run([ | |
|
108 | ('if 1:\n !true', 'if 1:\n !true'), | |
|
109 | ('if 1:\n lsmagic', 'if 1:\n lsmagic'), | |
|
110 | ('if 1:\n an_alias', 'if 1:\n an_alias'), | |
|
111 | ]) | |
|
112 | ||
|
113 | ip.options.multi_line_specials = 1 | |
|
114 | # initial indents must be preserved. | |
|
115 | run([ | |
|
116 | ('if 1:\n !true', 'if 1:\n _ip.system("true")'), | |
|
117 | ('if 1:\n lsmagic', 'if 1:\n _ip.magic("lsmagic ")'), | |
|
118 | ('if 1:\n an_alias', 'if 1:\n _ip.system("true ")'), | |
|
119 | # Weird one | |
|
120 | ('if 1:\n !!true', 'if 1:\n _ip.magic("sx true")'), | |
|
121 | ||
|
122 | ||
|
123 | # Even with m_l_s on, all esc_chars except ! are off | |
|
124 | ('if 1:\n %lsmagic', 'if 1:\n %lsmagic'), | |
|
125 | ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'), | |
|
126 | ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'), | |
|
127 | ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'), | |
|
128 | ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'), | |
|
129 | # What about !! | |
|
130 | ]) | |
|
131 | ||
|
132 | ||
|
133 | # Objects which are instances of IPyAutocall are *always* autocalled | |
|
134 | import IPython.ipapi | |
|
135 | class Autocallable(IPython.ipapi.IPyAutocall): | |
|
136 | def __call__(self): | |
|
137 | return "called" | |
|
138 | ||
|
139 | autocallable = Autocallable() | |
|
140 | ip.to_user_ns('autocallable') | |
|
141 | ||
|
142 | # auto | |
|
143 | ip.options.autocall = 0 | |
|
144 | # Only explicit escapes or instances of IPyAutocallable should get | |
|
145 | # expanded | |
|
146 | run([ | |
|
147 | ('len "abc"', 'len "abc"'), | |
|
148 | ('autocallable', 'autocallable()'), | |
|
149 | (",list 1 2 3", 'list("1", "2", "3")'), | |
|
150 | (";list 1 2 3", 'list("1 2 3")'), | |
|
151 | ("/len range(1,4)", 'len(range(1,4))'), | |
|
152 | ]) | |
|
153 | ip.options.autocall = 1 | |
|
154 | run([ | |
|
155 | (",list 1 2 3", 'list("1", "2", "3")'), | |
|
156 | (";list 1 2 3", 'list("1 2 3")'), | |
|
157 | ("/len range(1,4)", 'len(range(1,4))'), | |
|
158 | ('len "abc"', 'len("abc")'), | |
|
159 | ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens | |
|
160 | # Autocall is turned off if first arg is [] and the object | |
|
161 | # is both callable and indexable. Like so: | |
|
162 | ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__... | |
|
163 | ('call_idx [1]', 'call_idx [1]'), # call_idx *does*.. | |
|
164 | ('call_idx 1', 'call_idx(1)'), | |
|
165 | ('len', 'len '), # only at 2 does it auto-call on single args | |
|
166 | ]) | |
|
167 | ||
|
168 | ip.options.autocall = 2 | |
|
169 | run([ | |
|
170 | (",list 1 2 3", 'list("1", "2", "3")'), | |
|
171 | (";list 1 2 3", 'list("1 2 3")'), | |
|
172 | ("/len range(1,4)", 'len(range(1,4))'), | |
|
173 | ('len "abc"', 'len("abc")'), | |
|
174 | ('len "abc";', 'len("abc");'), | |
|
175 | ('len [1,2]', 'len([1,2])'), | |
|
176 | ('call_idx [1]', 'call_idx [1]'), | |
|
177 | ('call_idx 1', 'call_idx(1)'), | |
|
178 | # This is what's different: | |
|
179 | ('len', 'len()'), # only at 2 does it auto-call on single args | |
|
180 | ]) | |
|
181 | ip.options.autocall = 1 | |
|
182 | ||
|
183 | # Ignoring handle_emacs, 'cause it doesn't do anything. | |
|
184 | finally: | |
|
185 | sys.stdout = old_stdout | |
|
186 | sys.stderr = old_stderr | |
|
187 | ||
|
188 | ||
|
189 | ||
|
190 | ||
|
191 | num_f = len(failures) | |
|
192 | #if verbose: | |
|
193 | ||
|
194 | ||
|
195 | ||
|
196 | print "%s tests run, %s failure%s" % (num_tests, | |
|
197 | num_f, | |
|
198 | num_f != 1 and "s" or "") | |
|
199 | for f in failures: | |
|
200 | print f |
@@ -6,7 +6,7 b' Requires Python 2.3 or newer.' | |||
|
6 | 6 | |
|
7 | 7 | This file contains all the classes and helper functions specific to IPython. |
|
8 | 8 | |
|
9 |
$Id: iplib.py 235 |
|
|
9 | $Id: iplib.py 2354 2007-05-16 13:06:12Z dan.milstein $ | |
|
10 | 10 | """ |
|
11 | 11 | |
|
12 | 12 | #***************************************************************************** |
@@ -75,6 +75,8 b' from IPython.genutils import *' | |||
|
75 | 75 | from IPython.strdispatch import StrDispatch |
|
76 | 76 | import IPython.ipapi |
|
77 | 77 | |
|
78 | import IPython.prefilter as prefilter | |
|
79 | ||
|
78 | 80 | # Globals |
|
79 | 81 | |
|
80 | 82 | # store the builtin raw_input globally, and use this always, in case user code |
@@ -385,6 +387,7 b' class InteractiveShell(object,Magic):' | |||
|
385 | 387 | |
|
386 | 388 | # escapes for automatic behavior on the command line |
|
387 | 389 | self.ESC_SHELL = '!' |
|
390 | self.ESC_SH_CAP = '!!' | |
|
388 | 391 | self.ESC_HELP = '?' |
|
389 | 392 | self.ESC_MAGIC = '%' |
|
390 | 393 | self.ESC_QUOTE = ',' |
@@ -398,6 +401,7 b' class InteractiveShell(object,Magic):' | |||
|
398 | 401 | self.ESC_MAGIC : self.handle_magic, |
|
399 | 402 | self.ESC_HELP : self.handle_help, |
|
400 | 403 | self.ESC_SHELL : self.handle_shell_escape, |
|
404 | self.ESC_SH_CAP : self.handle_shell_escape, | |
|
401 | 405 | } |
|
402 | 406 | |
|
403 | 407 | # class initializations |
@@ -484,57 +488,6 b' class InteractiveShell(object,Magic):' | |||
|
484 | 488 | header=self.rc.system_header, |
|
485 | 489 | verbose=self.rc.system_verbose) |
|
486 | 490 | |
|
487 | # RegExp for splitting line contents into pre-char//first | |
|
488 | # word-method//rest. For clarity, each group in on one line. | |
|
489 | ||
|
490 | # WARNING: update the regexp if the above escapes are changed, as they | |
|
491 | # are hardwired in. | |
|
492 | ||
|
493 | # Don't get carried away with trying to make the autocalling catch too | |
|
494 | # much: it's better to be conservative rather than to trigger hidden | |
|
495 | # evals() somewhere and end up causing side effects. | |
|
496 | self.line_split = re.compile(r'^(\s*[,;/]?\s*)' | |
|
497 | r'([\?\w\.]+\w*\s*)' | |
|
498 | r'(\(?.*$)') | |
|
499 | ||
|
500 | self.shell_line_split = re.compile(r'^(\s*)' | |
|
501 | r'(\S*\s*)' | |
|
502 | r'(\(?.*$)') | |
|
503 | ||
|
504 | # A simpler regexp used as a fallback if the above doesn't work. This | |
|
505 | # one is more conservative in how it partitions the input. This code | |
|
506 | # can probably be cleaned up to do everything with just one regexp, but | |
|
507 | # I'm afraid of breaking something; do it once the unit tests are in | |
|
508 | # place. | |
|
509 | self.line_split_fallback = re.compile(r'^(\s*)' | |
|
510 | r'([%\!\?\w\.]*)' | |
|
511 | r'(.*)') | |
|
512 | ||
|
513 | # Original re, keep around for a while in case changes break something | |
|
514 | #self.line_split = re.compile(r'(^[\s*!\?%,/]?)' | |
|
515 | # r'(\s*[\?\w\.]+\w*\s*)' | |
|
516 | # r'(\(?.*$)') | |
|
517 | ||
|
518 | # RegExp to identify potential function names | |
|
519 | self.re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') | |
|
520 | ||
|
521 | # RegExp to exclude strings with this start from autocalling. In | |
|
522 | # particular, all binary operators should be excluded, so that if foo | |
|
523 | # is callable, foo OP bar doesn't become foo(OP bar), which is | |
|
524 | # invalid. The characters '!=()' don't need to be checked for, as the | |
|
525 | # _prefilter routine explicitely does so, to catch direct calls and | |
|
526 | # rebindings of existing names. | |
|
527 | ||
|
528 | # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise | |
|
529 | # it affects the rest of the group in square brackets. | |
|
530 | self.re_exclude_auto = re.compile(r'^[<>,&^\|\*/\+-]' | |
|
531 | '|^is |^not |^in |^and |^or ') | |
|
532 | ||
|
533 | # try to catch also methods for stuff in lists/tuples/dicts: off | |
|
534 | # (experimental). For this to work, the line_split regexp would need | |
|
535 | # to be modified so it wouldn't break things at '['. That line is | |
|
536 | # nasty enough that I shouldn't change it until I can test it _well_. | |
|
537 | #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') | |
|
538 | 491 | |
|
539 | 492 | # keep track of where we started running (mainly for crash post-mortem) |
|
540 | 493 | self.starting_dir = os.getcwd() |
@@ -1731,8 +1684,8 b' want to merge them back into the new files.""" % locals()' | |||
|
1731 | 1684 | |
|
1732 | 1685 | done = Set() |
|
1733 | 1686 | while 1: |
|
1734 |
pre,fn,rest = |
|
|
1735 | # print "!",fn,"!",rest # dbg | |
|
1687 | pre,fn,rest = prefilter.splitUserInput(line, | |
|
1688 | prefilter.shell_line_split) | |
|
1736 | 1689 | if fn in self.alias_table: |
|
1737 | 1690 | if fn in done: |
|
1738 | 1691 | warn("Cyclic alias definition, repeated '%s'" % fn) |
@@ -2056,53 +2009,6 b' want to merge them back into the new files.""" % locals()' | |||
|
2056 | 2009 | else: |
|
2057 | 2010 | return lineout |
|
2058 | 2011 | |
|
2059 | def split_user_input(self,line, pattern = None): | |
|
2060 | """Split user input into pre-char, function part and rest.""" | |
|
2061 | ||
|
2062 | if pattern is None: | |
|
2063 | pattern = self.line_split | |
|
2064 | ||
|
2065 | lsplit = pattern.match(line) | |
|
2066 | if lsplit is None: # no regexp match returns None | |
|
2067 | #print "match failed for line '%s'" % line # dbg | |
|
2068 | try: | |
|
2069 | iFun,theRest = line.split(None,1) | |
|
2070 | except ValueError: | |
|
2071 | #print "split failed for line '%s'" % line # dbg | |
|
2072 | iFun,theRest = line,'' | |
|
2073 | pre = re.match('^(\s*)(.*)',line).groups()[0] | |
|
2074 | else: | |
|
2075 | pre,iFun,theRest = lsplit.groups() | |
|
2076 | ||
|
2077 | # iFun has to be a valid python identifier, so it better be only pure | |
|
2078 | #ascii, no unicode: | |
|
2079 | try: | |
|
2080 | iFun = iFun.encode('ascii') | |
|
2081 | except UnicodeEncodeError: | |
|
2082 | theRest = iFun+u' '+theRest | |
|
2083 | iFun = u'' | |
|
2084 | ||
|
2085 | #print 'line:<%s>' % line # dbg | |
|
2086 | #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun.strip(),theRest) # dbg | |
|
2087 | return pre,iFun.strip(),theRest | |
|
2088 | ||
|
2089 | # THIS VERSION IS BROKEN!!! It was intended to prevent spurious attribute | |
|
2090 | # accesses with a more stringent check of inputs, but it introduced other | |
|
2091 | # bugs. Disable it for now until I can properly fix it. | |
|
2092 | def split_user_inputBROKEN(self,line): | |
|
2093 | """Split user input into pre-char, function part and rest.""" | |
|
2094 | ||
|
2095 | lsplit = self.line_split.match(line) | |
|
2096 | if lsplit is None: # no regexp match returns None | |
|
2097 | lsplit = self.line_split_fallback.match(line) | |
|
2098 | ||
|
2099 | #pre,iFun,theRest = lsplit.groups() # dbg | |
|
2100 | #print 'line:<%s>' % line # dbg | |
|
2101 | #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun.strip(),theRest) # dbg | |
|
2102 | #return pre,iFun.strip(),theRest # dbg | |
|
2103 | ||
|
2104 | return lsplit.groups() | |
|
2105 | ||
|
2106 | 2012 | def _prefilter(self, line, continue_prompt): |
|
2107 | 2013 | """Calls different preprocessors, depending on the form of line.""" |
|
2108 | 2014 | |
@@ -2112,15 +2018,6 b' want to merge them back into the new files.""" % locals()' | |||
|
2112 | 2018 | # needed, update the cache AND log it (so that the input cache array |
|
2113 | 2019 | # stays synced). |
|
2114 | 2020 | |
|
2115 | # This function is _very_ delicate, and since it's also the one which | |
|
2116 | # determines IPython's response to user input, it must be as efficient | |
|
2117 | # as possible. For this reason it has _many_ returns in it, trying | |
|
2118 | # always to exit as quickly as it can figure out what it needs to do. | |
|
2119 | ||
|
2120 | # This function is the main responsible for maintaining IPython's | |
|
2121 | # behavior respectful of Python's semantics. So be _very_ careful if | |
|
2122 | # making changes to anything here. | |
|
2123 | ||
|
2124 | 2021 | #..................................................................... |
|
2125 | 2022 | # Code begins |
|
2126 | 2023 | |
@@ -2131,6 +2028,8 b' want to merge them back into the new files.""" % locals()' | |||
|
2131 | 2028 | self._last_input_line = line |
|
2132 | 2029 | |
|
2133 | 2030 | #print '***line: <%s>' % line # dbg |
|
2031 | ||
|
2032 | line_info = prefilter.LineInfo(line, continue_prompt) | |
|
2134 | 2033 | |
|
2135 | 2034 | # the input history needs to track even empty lines |
|
2136 | 2035 | stripped = line.strip() |
@@ -2138,139 +2037,25 b' want to merge them back into the new files.""" % locals()' | |||
|
2138 | 2037 | if not stripped: |
|
2139 | 2038 | if not continue_prompt: |
|
2140 | 2039 | self.outputcache.prompt_count -= 1 |
|
2141 |
return self.handle_normal(line |
|
|
2142 | #return self.handle_normal('',continue_prompt) | |
|
2040 | return self.handle_normal(line_info) | |
|
2143 | 2041 | |
|
2144 | 2042 | # print '***cont',continue_prompt # dbg |
|
2145 | 2043 | # special handlers are only allowed for single line statements |
|
2146 | 2044 | if continue_prompt and not self.rc.multi_line_specials: |
|
2147 |
return self.handle_normal(line |
|
|
2148 | ||
|
2045 | return self.handle_normal(line_info) | |
|
2149 | 2046 | |
|
2150 | # For the rest, we need the structure of the input | |
|
2151 | pre,iFun,theRest = self.split_user_input(line) | |
|
2152 | 2047 | |
|
2153 | # See whether any pre-existing handler can take care of it | |
|
2154 | ||
|
2048 | # See whether any pre-existing handler can take care of it | |
|
2155 | 2049 | rewritten = self.hooks.input_prefilter(stripped) |
|
2156 | 2050 | if rewritten != stripped: # ok, some prefilter did something |
|
2157 | rewritten = pre + rewritten # add indentation | |
|
2158 |
return self.handle_normal(rewritten |
|
|
2051 | rewritten = line_info.pre + rewritten # add indentation | |
|
2052 | return self.handle_normal(prefilter.LineInfo(rewritten, | |
|
2053 | continue_prompt)) | |
|
2159 | 2054 | |
|
2160 | 2055 | #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg |
|
2161 | 2056 | |
|
2162 | # Next, check if we can automatically execute this thing | |
|
2163 | ||
|
2164 | # Allow ! in multi-line statements if multi_line_specials is on: | |
|
2165 | if continue_prompt and self.rc.multi_line_specials and \ | |
|
2166 | iFun.startswith(self.ESC_SHELL): | |
|
2167 | return self.handle_shell_escape(line,continue_prompt, | |
|
2168 | pre=pre,iFun=iFun, | |
|
2169 | theRest=theRest) | |
|
2170 | ||
|
2171 | # First check for explicit escapes in the last/first character | |
|
2172 | handler = None | |
|
2173 | if line[-1] == self.ESC_HELP and line[0] != self.ESC_SHELL: | |
|
2174 | handler = self.esc_handlers.get(line[-1]) # the ? can be at the end | |
|
2175 | if handler is None: | |
|
2176 | # look at the first character of iFun, NOT of line, so we skip | |
|
2177 | # leading whitespace in multiline input | |
|
2178 | handler = self.esc_handlers.get(iFun[0:1]) | |
|
2179 | if handler is not None: | |
|
2180 | return handler(line,continue_prompt,pre,iFun,theRest) | |
|
2181 | # Emacs ipython-mode tags certain input lines | |
|
2182 | if line.endswith('# PYTHON-MODE'): | |
|
2183 | return self.handle_emacs(line,continue_prompt) | |
|
2184 | ||
|
2185 | # instances of IPyAutocall in user_ns get autocalled immediately | |
|
2186 | obj = self.user_ns.get(iFun,None) | |
|
2187 | if isinstance(obj, IPython.ipapi.IPyAutocall): | |
|
2188 | obj.set_ip(self.api) | |
|
2189 | return self.handle_auto(line,continue_prompt, | |
|
2190 | pre,iFun,theRest,obj) | |
|
2191 | ||
|
2192 | # Let's try to find if the input line is a magic fn | |
|
2193 | oinfo = None | |
|
2194 | if hasattr(self,'magic_'+iFun): | |
|
2195 | # WARNING: _ofind uses getattr(), so it can consume generators and | |
|
2196 | # cause other side effects. | |
|
2197 | oinfo = self._ofind(iFun) # FIXME - _ofind is part of Magic | |
|
2198 | if oinfo['ismagic']: | |
|
2199 | # Be careful not to call magics when a variable assignment is | |
|
2200 | # being made (ls='hi', for example) | |
|
2201 | if self.rc.automagic and \ | |
|
2202 | (len(theRest)==0 or theRest[0] not in '!=()<>,') and \ | |
|
2203 | (self.rc.multi_line_specials or not continue_prompt): | |
|
2204 | return self.handle_magic(line,continue_prompt, | |
|
2205 | pre,iFun,theRest) | |
|
2206 | else: | |
|
2207 | return self.handle_normal(line,continue_prompt) | |
|
2208 | ||
|
2209 | # If the rest of the line begins with an (in)equality, assginment or | |
|
2210 | # function call, we should not call _ofind but simply execute it. | |
|
2211 | # This avoids spurious geattr() accesses on objects upon assignment. | |
|
2212 | # | |
|
2213 | # It also allows users to assign to either alias or magic names true | |
|
2214 | # python variables (the magic/alias systems always take second seat to | |
|
2215 | # true python code). | |
|
2216 | if theRest and theRest[0] in '!=()': | |
|
2217 | return self.handle_normal(line,continue_prompt) | |
|
2218 | ||
|
2219 | if oinfo is None: | |
|
2220 | # let's try to ensure that _oinfo is ONLY called when autocall is | |
|
2221 | # on. Since it has inevitable potential side effects, at least | |
|
2222 | # having autocall off should be a guarantee to the user that no | |
|
2223 | # weird things will happen. | |
|
2224 | ||
|
2225 | if self.rc.autocall: | |
|
2226 | oinfo = self._ofind(iFun) # FIXME - _ofind is part of Magic | |
|
2227 | else: | |
|
2228 | # in this case, all that's left is either an alias or | |
|
2229 | # processing the line normally. | |
|
2230 | if iFun in self.alias_table: | |
|
2231 | # if autocall is off, by not running _ofind we won't know | |
|
2232 | # whether the given name may also exist in one of the | |
|
2233 | # user's namespace. At this point, it's best to do a | |
|
2234 | # quick check just to be sure that we don't let aliases | |
|
2235 | # shadow variables. | |
|
2236 | head = iFun.split('.',1)[0] | |
|
2237 | if head in self.user_ns or head in self.internal_ns \ | |
|
2238 | or head in __builtin__.__dict__: | |
|
2239 | return self.handle_normal(line,continue_prompt) | |
|
2240 | else: | |
|
2241 | return self.handle_alias(line,continue_prompt, | |
|
2242 | pre,iFun,theRest) | |
|
2243 | ||
|
2244 | else: | |
|
2245 | return self.handle_normal(line,continue_prompt) | |
|
2246 | ||
|
2247 | if not oinfo['found']: | |
|
2248 | return self.handle_normal(line,continue_prompt) | |
|
2249 | else: | |
|
2250 | #print 'pre<%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg | |
|
2251 | if oinfo['isalias']: | |
|
2252 | return self.handle_alias(line,continue_prompt, | |
|
2253 | pre,iFun,theRest) | |
|
2254 | ||
|
2255 | if (self.rc.autocall | |
|
2256 | and | |
|
2257 | ( | |
|
2258 | #only consider exclusion re if not "," or ";" autoquoting | |
|
2259 | (pre == self.ESC_QUOTE or pre == self.ESC_QUOTE2 | |
|
2260 | or pre == self.ESC_PAREN) or | |
|
2261 | (not self.re_exclude_auto.match(theRest))) | |
|
2262 | and | |
|
2263 | self.re_fun_name.match(iFun) and | |
|
2264 | callable(oinfo['obj'])) : | |
|
2265 | #print 'going auto' # dbg | |
|
2266 | return self.handle_auto(line,continue_prompt, | |
|
2267 | pre,iFun,theRest,oinfo['obj']) | |
|
2268 | else: | |
|
2269 | #print 'was callable?', callable(oinfo['obj']) # dbg | |
|
2270 | return self.handle_normal(line,continue_prompt) | |
|
2057 | return prefilter.prefilter(line_info, self) | |
|
2271 | 2058 | |
|
2272 | # If we get here, we have a normal Python line. Log and return. | |
|
2273 | return self.handle_normal(line,continue_prompt) | |
|
2274 | 2059 | |
|
2275 | 2060 | def _prefilter_dumb(self, line, continue_prompt): |
|
2276 | 2061 | """simple prefilter function, for debugging""" |
@@ -2293,8 +2078,7 b' want to merge them back into the new files.""" % locals()' | |||
|
2293 | 2078 | # Set the default prefilter() function (this can be user-overridden) |
|
2294 | 2079 | prefilter = multiline_prefilter |
|
2295 | 2080 | |
|
2296 |
def handle_normal(self,line |
|
|
2297 | pre=None,iFun=None,theRest=None): | |
|
2081 | def handle_normal(self,line_info): | |
|
2298 | 2082 | """Handle normal input lines. Use as a template for handlers.""" |
|
2299 | 2083 | |
|
2300 | 2084 | # With autoindent on, we need some way to exit the input loop, and I |
@@ -2302,6 +2086,8 b' want to merge them back into the new files.""" % locals()' | |||
|
2302 | 2086 | # clear the line. The rule will be in this case, that either two |
|
2303 | 2087 | # lines of pure whitespace in a row, or a line of pure whitespace but |
|
2304 | 2088 | # of a size different to the indent level, will exit the input loop. |
|
2089 | line = line_info.line | |
|
2090 | continue_prompt = line_info.continue_prompt | |
|
2305 | 2091 | |
|
2306 | 2092 | if (continue_prompt and self.autoindent and line.isspace() and |
|
2307 | 2093 | (0 < abs(len(line) - self.indent_current_nsp) <= 2 or |
@@ -2311,55 +2097,62 b' want to merge them back into the new files.""" % locals()' | |||
|
2311 | 2097 | self.log(line,line,continue_prompt) |
|
2312 | 2098 | return line |
|
2313 | 2099 | |
|
2314 |
def handle_alias(self,line |
|
|
2315 | pre=None,iFun=None,theRest=None): | |
|
2316 | """Handle alias input lines. """ | |
|
2100 | def handle_alias(self,line_info): | |
|
2101 | """Handle alias input lines. """ | |
|
2102 | transformed = self.expand_aliases(line_info.iFun,line_info.theRest) | |
|
2317 | 2103 | |
|
2318 | 2104 | # pre is needed, because it carries the leading whitespace. Otherwise |
|
2319 | 2105 | # aliases won't work in indented sections. |
|
2320 | transformed = self.expand_aliases(iFun, theRest) | |
|
2321 | line_out = '%s_ip.system(%s)' % (pre, make_quoted_expr( transformed )) | |
|
2322 | self.log(line,line_out,continue_prompt) | |
|
2106 | line_out = '%s_ip.system(%s)' % (line_info.preWhitespace, | |
|
2107 | make_quoted_expr( transformed )) | |
|
2108 | ||
|
2109 | self.log(line_info.line,line_out,line_info.continue_prompt) | |
|
2323 | 2110 | #print 'line out:',line_out # dbg |
|
2324 | 2111 | return line_out |
|
2325 | 2112 | |
|
2326 |
def handle_shell_escape(self, line |
|
|
2327 | pre=None,iFun=None,theRest=None): | |
|
2113 | def handle_shell_escape(self, line_info): | |
|
2328 | 2114 | """Execute the line in a shell, empty return value""" |
|
2329 | ||
|
2330 | 2115 | #print 'line in :', `line` # dbg |
|
2331 | # Example of a special handler. Others follow a similar pattern. | |
|
2116 | line = line_info.line | |
|
2332 | 2117 | if line.lstrip().startswith('!!'): |
|
2333 |
# rewrite |
|
|
2334 |
# the actual command to be executed, so |
|
|
2335 | # correctly | |
|
2336 | theRest = '%s %s' % (iFun[2:],theRest) | |
|
2337 | iFun = 'sx' | |
|
2338 | return self.handle_magic('%ssx %s' % (self.ESC_MAGIC, | |
|
2339 | line.lstrip()[2:]), | |
|
2340 | continue_prompt,pre,iFun,theRest) | |
|
2118 | # rewrite LineInfo's line, iFun and theRest to properly hold the | |
|
2119 | # call to %sx and the actual command to be executed, so | |
|
2120 | # handle_magic can work correctly. Note that this works even if | |
|
2121 | # the line is indented, so it handles multi_line_specials | |
|
2122 | # properly. | |
|
2123 | new_rest = line.lstrip()[2:] | |
|
2124 | line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest) | |
|
2125 | line_info.iFun = 'sx' | |
|
2126 | line_info.theRest = new_rest | |
|
2127 | return self.handle_magic(line_info) | |
|
2341 | 2128 | else: |
|
2342 | cmd=line.lstrip().lstrip('!') | |
|
2343 |
line_out = '%s_ip.system(%s)' % (pre, |
|
|
2129 | cmd = line.lstrip().lstrip('!') | |
|
2130 | line_out = '%s_ip.system(%s)' % (line_info.preWhitespace, | |
|
2131 | make_quoted_expr(cmd)) | |
|
2344 | 2132 | # update cache/log and return |
|
2345 | self.log(line,line_out,continue_prompt) | |
|
2133 | self.log(line,line_out,line_info.continue_prompt) | |
|
2346 | 2134 | return line_out |
|
2347 | 2135 | |
|
2348 |
def handle_magic(self, line |
|
|
2349 | pre=None,iFun=None,theRest=None): | |
|
2136 | def handle_magic(self, line_info): | |
|
2350 | 2137 | """Execute magic functions.""" |
|
2351 | ||
|
2352 | ||
|
2353 | cmd = '%s_ip.magic(%s)' % (pre,make_quoted_expr(iFun + " " + theRest)) | |
|
2354 | self.log(line,cmd,continue_prompt) | |
|
2138 | iFun = line_info.iFun | |
|
2139 | theRest = line_info.theRest | |
|
2140 | cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace, | |
|
2141 | make_quoted_expr(iFun + " " + theRest)) | |
|
2142 | self.log(line_info.line,cmd,line_info.continue_prompt) | |
|
2355 | 2143 | #print 'in handle_magic, cmd=<%s>' % cmd # dbg |
|
2356 | 2144 | return cmd |
|
2357 | 2145 | |
|
2358 |
def handle_auto(self, line |
|
|
2359 | pre=None,iFun=None,theRest=None,obj=None): | |
|
2146 | def handle_auto(self, line_info): | |
|
2360 | 2147 | """Hande lines which can be auto-executed, quoting if requested.""" |
|
2361 | 2148 | |
|
2362 | 2149 | #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg |
|
2150 | line = line_info.line | |
|
2151 | iFun = line_info.iFun | |
|
2152 | theRest = line_info.theRest | |
|
2153 | pre = line_info.pre | |
|
2154 | continue_prompt = line_info.continue_prompt | |
|
2155 | obj = line_info.ofind(self)['obj'] | |
|
2363 | 2156 | |
|
2364 | 2157 | # This should only be active for single-line input! |
|
2365 | 2158 | if continue_prompt: |
@@ -2408,14 +2201,14 b' want to merge them back into the new files.""" % locals()' | |||
|
2408 | 2201 | self.log(line,newcmd,continue_prompt) |
|
2409 | 2202 | return newcmd |
|
2410 | 2203 | |
|
2411 |
def handle_help(self, line |
|
|
2412 | pre=None,iFun=None,theRest=None): | |
|
2204 | def handle_help(self, line_info): | |
|
2413 | 2205 | """Try to get some help for the object. |
|
2414 | 2206 | |
|
2415 | 2207 | obj? or ?obj -> basic information. |
|
2416 | 2208 | obj?? or ??obj -> more details. |
|
2417 | 2209 | """ |
|
2418 | ||
|
2210 | ||
|
2211 | line = line_info.line | |
|
2419 | 2212 | # We need to make sure that we don't process lines which would be |
|
2420 | 2213 | # otherwise valid python, such as "x=1 # what?" |
|
2421 | 2214 | try: |
@@ -2426,7 +2219,7 b' want to merge them back into the new files.""" % locals()' | |||
|
2426 | 2219 | line = line[1:] |
|
2427 | 2220 | elif line[-1]==self.ESC_HELP: |
|
2428 | 2221 | line = line[:-1] |
|
2429 | self.log(line,'#?'+line,continue_prompt) | |
|
2222 | self.log(line,'#?'+line,line_info.continue_prompt) | |
|
2430 | 2223 | if line: |
|
2431 | 2224 | #print 'line:<%r>' % line # dbg |
|
2432 | 2225 | self.magic_pinfo(line) |
@@ -2435,10 +2228,10 b' want to merge them back into the new files.""" % locals()' | |||
|
2435 | 2228 | return '' # Empty string is needed here! |
|
2436 | 2229 | except: |
|
2437 | 2230 | # Pass any other exceptions through to the normal handler |
|
2438 |
return self.handle_normal(line |
|
|
2231 | return self.handle_normal(line_info) | |
|
2439 | 2232 | else: |
|
2440 | 2233 | # If the code compiles ok, we should handle it normally |
|
2441 |
return self.handle_normal(line |
|
|
2234 | return self.handle_normal(line_info) | |
|
2442 | 2235 | |
|
2443 | 2236 | def getapi(self): |
|
2444 | 2237 | """ Get an IPApi object for this shell instance |
@@ -2451,17 +2244,16 b' want to merge them back into the new files.""" % locals()' | |||
|
2451 | 2244 | |
|
2452 | 2245 | """ |
|
2453 | 2246 | return self.api |
|
2454 | ||
|
2455 |
def handle_emacs(self, |
|
|
2456 | pre=None,iFun=None,theRest=None): | |
|
2247 | ||
|
2248 | def handle_emacs(self, line_info): | |
|
2457 | 2249 | """Handle input lines marked by python-mode.""" |
|
2458 | 2250 | |
|
2459 | 2251 | # Currently, nothing is done. Later more functionality can be added |
|
2460 | 2252 | # here if needed. |
|
2461 | 2253 | |
|
2462 | 2254 | # The input cache shouldn't be updated |
|
2463 | ||
|
2464 | return line | |
|
2255 | return line_info.line | |
|
2256 | ||
|
2465 | 2257 | |
|
2466 | 2258 | def mktempfile(self,data=None): |
|
2467 | 2259 | """Make a new tempfile and return its filename. |
@@ -73,6 +73,7 b' def reset_esc_handlers():' | |||
|
73 | 73 | s.ESC_MAGIC : s.handle_magic, |
|
74 | 74 | s.ESC_HELP : s.handle_help, |
|
75 | 75 | s.ESC_SHELL : s.handle_shell_escape, |
|
76 | s.ESC_SH_CAP : s.handle_shell_escape, | |
|
76 | 77 | } |
|
77 | 78 | reset_esc_handlers() |
|
78 | 79 | |
@@ -145,7 +146,14 b' esc_handler_tests = [' | |||
|
145 | 146 | ( '?thing', handle_help, ), |
|
146 | 147 | ( 'thing?', handle_help ), # '?' can trail... |
|
147 | 148 | ( 'thing!', handle_normal), # but only '?' can trail |
|
148 |
( ' ?thing', handle_ |
|
|
149 | ( ' ?thing', handle_normal), # leading whitespace turns off esc chars | |
|
150 | ( '!ls', handle_shell_escape), | |
|
151 | ( '! true', handle_shell_escape), | |
|
152 | ( '!! true', handle_shell_escape), | |
|
153 | ( '%magic', handle_magic), | |
|
154 | # XXX Possibly, add test for /,; once those are unhooked from %autocall | |
|
155 | ( 'emacs_mode # PYTHON-MODE', handle_emacs ), | |
|
156 | ( ' ', handle_normal), | |
|
149 | 157 | # Trailing qmark combos. Odd special cases abound |
|
150 | 158 | ( '!thing?', handle_shell_escape), # trailing '?' loses to shell esc |
|
151 | 159 | ( '!thing ?', handle_shell_escape), |
@@ -154,11 +162,6 b' esc_handler_tests = [' | |||
|
154 | 162 | ( '/cmd?', handle_help), |
|
155 | 163 | ( ';cmd?', handle_help), |
|
156 | 164 | ( ',cmd?', handle_help), |
|
157 | ( '!ls', handle_shell_escape ), | |
|
158 | ( '%magic', handle_magic), | |
|
159 | # Possibly, add test for /,; once those are unhooked from %autocall | |
|
160 | ( 'emacs_mode # PYTHON-MODE', handle_emacs ), | |
|
161 | ( ' ', handle_normal), | |
|
162 | 165 | ] |
|
163 | 166 | run_handler_tests(esc_handler_tests) |
|
164 | 167 | |
@@ -167,19 +170,26 b' run_handler_tests(esc_handler_tests)' | |||
|
167 | 170 | # Shell Escapes in Multi-line statements |
|
168 | 171 | # ====================================== |
|
169 | 172 | # |
|
170 |
# We can't test this via runlines, since the hacked |
|
|
171 |
# return None, so continue_prompt never becomes true. Instead |
|
|
172 | # into prefilter directly and pass in continue_prompt. | |
|
173 | # We can't test this via runlines, since the hacked-over-for-testing | |
|
174 | # handlers all return None, so continue_prompt never becomes true. Instead | |
|
175 | # we drop into prefilter directly and pass in continue_prompt. | |
|
173 | 176 | |
|
174 | 177 | old_mls = ip.options.multi_line_specials |
|
175 |
ln |
|
|
176 | ignore = ip.IP.prefilter(ln, continue_prompt=True) | |
|
177 | check_handler(handle_shell_escape, ln) | |
|
178 | ||
|
179 | ip.options.multi_line_specials = 0 | |
|
180 | ln = '!ls $f multi_line_specials off' | |
|
181 | ignore = ip.IP.prefilter(ln, continue_prompt=True) | |
|
182 | check_handler(handle_normal, ln) | |
|
178 | for ln in [ ' !ls $f multi_line_specials %s', | |
|
179 | ' !!ls $f multi_line_specials %s', # !! escapes work on mls | |
|
180 | # Trailing ? doesn't trigger help: | |
|
181 | ' !ls $f multi_line_specials %s ?', | |
|
182 | ' !!ls $f multi_line_specials %s ?', | |
|
183 | ]: | |
|
184 | ip.options.multi_line_specials = 1 | |
|
185 | on_ln = ln % 'on' | |
|
186 | ignore = ip.IP.prefilter(on_ln, continue_prompt=True) | |
|
187 | check_handler(handle_shell_escape, on_ln) | |
|
188 | ||
|
189 | ip.options.multi_line_specials = 0 | |
|
190 | off_ln = ln % 'off' | |
|
191 | ignore = ip.IP.prefilter(off_ln, continue_prompt=True) | |
|
192 | check_handler(handle_normal, off_ln) | |
|
183 | 193 | |
|
184 | 194 | ip.options.multi_line_specials = old_mls |
|
185 | 195 | |
@@ -190,6 +200,7 b' ip.options.multi_line_specials = old_mls' | |||
|
190 | 200 | # Pick one magic fun and one non_magic fun, make sure both exist |
|
191 | 201 | assert hasattr(ip.IP, "magic_cpaste") |
|
192 | 202 | assert not hasattr(ip.IP, "magic_does_not_exist") |
|
203 | ip.options.autocall = 0 # gotta have this off to get handle_normal | |
|
193 | 204 | ip.options.automagic = 0 |
|
194 | 205 | run_handler_tests([ |
|
195 | 206 | # Without automagic, only shows up with explicit escape |
@@ -214,12 +225,12 b' run_handler_tests(magic_killing_tests)' | |||
|
214 | 225 | |
|
215 | 226 | # magic on indented continuation lines -- on iff multi_line_specials == 1 |
|
216 | 227 | ip.options.multi_line_specials = 0 |
|
217 | ln = 'cpaste multi_line off kills magic' | |
|
228 | ln = ' cpaste multi_line off kills magic' | |
|
218 | 229 | ignore = ip.IP.prefilter(ln, continue_prompt=True) |
|
219 | 230 | check_handler(handle_normal, ln) |
|
220 | 231 | |
|
221 | 232 | ip.options.multi_line_specials = 1 |
|
222 | ln = 'cpaste multi_line on enables magic' | |
|
233 | ln = ' cpaste multi_line on enables magic' | |
|
223 | 234 | ignore = ip.IP.prefilter(ln, continue_prompt=True) |
|
224 | 235 | check_handler(handle_magic, ln) |
|
225 | 236 | |
@@ -231,6 +242,7 b' run_handler_tests([' | |||
|
231 | 242 | del ip.user_ns['cpaste'] |
|
232 | 243 | |
|
233 | 244 | |
|
245 | ||
|
234 | 246 | # Check for !=() turning off .ofind |
|
235 | 247 | # ================================= |
|
236 | 248 | class AttributeMutator(object): |
@@ -249,7 +261,7 b' ip.options.autocall = 1' | |||
|
249 | 261 | run_one_test('attr_mutator.foo should mutate', handle_normal) |
|
250 | 262 | check(attr_mutator.called, 'ofind should be called in absence of assign characters') |
|
251 | 263 | |
|
252 | for c in list('!=()'): # XXX What about <> -- they *are* important above | |
|
264 | for c in list('!=()<>+*/%^&|'): | |
|
253 | 265 | attr_mutator.called = False |
|
254 | 266 | run_one_test('attr_mutator.foo %s should *not* mutate' % c, handle_normal) |
|
255 | 267 | run_one_test('attr_mutator.foo%s should *not* mutate' % c, handle_normal) |
@@ -296,51 +308,73 b' ip.options.autocall = 1' | |||
|
296 | 308 | # Autocall |
|
297 | 309 | # ======== |
|
298 | 310 | |
|
299 | # First, with autocalling fully off | |
|
300 | ip.options.autocall = 0 | |
|
301 | run_handler_tests( [ | |
|
302 | # Since len is callable, these *should* get auto-called | |
|
303 | ||
|
304 | # XXX Except, at the moment, they're *not*, because the code is wrong | |
|
305 | # XXX So I'm commenting 'em out to keep the tests quiet | |
|
311 | # For all the tests below, 'len' is callable / 'thing' is not | |
|
306 | 312 | |
|
307 | #( '/len autocall_0', handle_auto), | |
|
308 | #( ',len autocall_0 b0', handle_auto), | |
|
309 | #( ';len autocall_0 b0', handle_auto), | |
|
313 | # Objects which are instances of IPyAutocall are *always* autocalled | |
|
314 | import IPython.ipapi | |
|
315 | class Autocallable(IPython.ipapi.IPyAutocall): | |
|
316 | def __call__(self): | |
|
317 | return "called" | |
|
310 | 318 | |
|
311 | # But these, since fun is not a callable, should *not* get auto-called | |
|
312 | ( '/fun autocall_0', handle_normal), | |
|
313 | ( ',fun autocall_0 b0', handle_normal), | |
|
314 | ( ';fun autocall_0 b0', handle_normal), | |
|
319 | autocallable = Autocallable() | |
|
320 | ip.to_user_ns('autocallable') | |
|
321 | ||
|
315 | 322 | |
|
316 | # With no escapes, no autocalling should happen, callable or not | |
|
323 | # First, with autocalling fully off | |
|
324 | ip.options.autocall = 0 | |
|
325 | run_handler_tests( [ | |
|
326 | # With no escapes, no autocalling expansions happen, callable or not, | |
|
327 | # unless the obj extends IPyAutocall | |
|
317 | 328 | ( 'len autocall_0', handle_normal), |
|
318 |
( ' |
|
|
329 | ( 'thing autocall_0', handle_normal), | |
|
330 | ( 'autocallable', handle_auto), | |
|
331 | ||
|
332 | # With explicit escapes, callable and non-callables both get expanded, | |
|
333 | # regardless of the %autocall setting: | |
|
334 | ( '/len autocall_0', handle_auto), | |
|
335 | ( ',len autocall_0 b0', handle_auto), | |
|
336 | ( ';len autocall_0 b0', handle_auto), | |
|
337 | ||
|
338 | ( '/thing autocall_0', handle_auto), | |
|
339 | ( ',thing autocall_0 b0', handle_auto), | |
|
340 | ( ';thing autocall_0 b0', handle_auto), | |
|
341 | ||
|
342 | # Explicit autocall should not trigger if there is leading whitespace | |
|
343 | ( ' /len autocall_0', handle_normal), | |
|
344 | ( ' ;len autocall_0', handle_normal), | |
|
345 | ( ' ,len autocall_0', handle_normal), | |
|
346 | ( ' / len autocall_0', handle_normal), | |
|
347 | ||
|
348 | # But should work if the whitespace comes after the esc char | |
|
349 | ( '/ len autocall_0', handle_auto), | |
|
350 | ( '; len autocall_0', handle_auto), | |
|
351 | ( ', len autocall_0', handle_auto), | |
|
352 | ( '/ len autocall_0', handle_auto), | |
|
319 | 353 | ]) |
|
320 | 354 | |
|
321 | 355 | |
|
322 | 356 | # Now, with autocall in default, 'smart' mode |
|
323 | 357 | ip.options.autocall = 1 |
|
324 | 358 | run_handler_tests( [ |
|
325 | # Since len is callable, these *do* get auto-called | |
|
326 |
( ' |
|
|
327 |
( ' |
|
|
328 |
( ' |
|
|
329 | # But these, since fun is not a callable, should *not* get auto-called | |
|
330 | ( '/fun a1', handle_normal), | |
|
331 |
( ' |
|
|
332 |
( ' |
|
|
333 | # Autocalls without escapes | |
|
334 |
( ' |
|
|
335 | ( 'fun a1', handle_normal), # Not callable -> no add | |
|
359 | # Autocalls without escapes -- only expand if it's callable | |
|
360 | ( 'len a1', handle_auto), | |
|
361 | ( 'thing a1', handle_normal), | |
|
362 | ( 'autocallable', handle_auto), | |
|
363 | ||
|
364 | # As above, all explicit escapes generate auto-calls, callable or not | |
|
365 | ( '/len a1', handle_auto), | |
|
366 | ( ',len a1 b1', handle_auto), | |
|
367 | ( ';len a1 b1', handle_auto), | |
|
368 | ( '/thing a1', handle_auto), | |
|
369 | ( ',thing a1 b1', handle_auto), | |
|
370 | ( ';thing a1 b1', handle_auto), | |
|
371 | ||
|
336 | 372 | # Autocalls only happen on things which look like funcs, even if |
|
337 | 373 | # explicitly requested. Which, in this case means they look like a |
|
338 |
# sequence of identifiers and . attribute references. |
|
|
339 | # test should pass, but it's not at the moment (meaning, IPython is | |
|
340 | # attempting to run an autocall). Though it does blow up in ipython | |
|
341 | # later (because of how lines are split, I think). | |
|
374 | # sequence of identifiers and . attribute references. Possibly the | |
|
375 | # second of these two should trigger handle_auto. But not for now. | |
|
342 | 376 | ( '"abc".join range(4)', handle_normal), |
|
343 |
|
|
|
377 | ( '/"abc".join range(4)', handle_normal), | |
|
344 | 378 | ]) |
|
345 | 379 | |
|
346 | 380 |
General Comments 0
You need to be logged in to leave comments.
Login now