##// END OF EJS Templates
prefilter: make sure that ! gets precedence
vivainio -
Show More
@@ -1,313 +1,323 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Classes and functions for prefiltering (transforming) a line of user input.
4 4 This module is responsible, primarily, for breaking the line up into useful
5 5 pieces and triggering the appropriate handlers in iplib to do the actual
6 6 transforming work.
7 7 """
8 8 __docformat__ = "restructuredtext en"
9 9
10 10 import re
11 11 import IPython.ipapi
12 12
13 13 class LineInfo(object):
14 14 """A single line of input and associated info.
15 15
16 16 Includes the following as properties:
17 17
18 18 line
19 19 The original, raw line
20 20
21 21 continue_prompt
22 22 Is this line a continuation in a sequence of multiline input?
23 23
24 24 pre
25 25 The initial esc character or whitespace.
26 26
27 27 preChar
28 28 The escape character(s) in pre or the empty string if there isn't one.
29 29 Note that '!!' is a possible value for preChar. Otherwise it will
30 30 always be a single character.
31 31
32 32 preWhitespace
33 33 The leading whitespace from pre if it exists. If there is a preChar,
34 34 this is just ''.
35 35
36 36 iFun
37 37 The 'function part', which is basically the maximal initial sequence
38 38 of valid python identifiers and the '.' character. This is what is
39 39 checked for alias and magic transformations, used for auto-calling,
40 40 etc.
41 41
42 42 theRest
43 43 Everything else on the line.
44 44 """
45 45 def __init__(self, line, continue_prompt):
46 46 self.line = line
47 47 self.continue_prompt = continue_prompt
48 48 self.pre, self.iFun, self.theRest = splitUserInput(line)
49 49
50 50 self.preChar = self.pre.strip()
51
52 # special override for !, which MUST always have top priority
53 if not self.preChar and self.iFun.startswith('!'):
54 self.preChar = self.pre = '!'
55 self.iFun = self.iFun[1:]
51 56 if self.preChar:
52 57 self.preWhitespace = '' # No whitespace allowd before esc chars
53 58 else:
54 59 self.preWhitespace = self.pre
55 60
56 61 self._oinfo = None
57 62
58 63 def ofind(self, ip):
59 64 """Do a full, attribute-walking lookup of the iFun in the various
60 65 namespaces for the given IPython InteractiveShell instance.
61 66
62 67 Return a dict with keys: found,obj,ospace,ismagic
63 68
64 69 Note: can cause state changes because of calling getattr, but should
65 70 only be run if autocall is on and if the line hasn't matched any
66 71 other, less dangerous handlers.
67 72
68 73 Does cache the results of the call, so can be called multiple times
69 74 without worrying about *further* damaging state.
70 75 """
71 76 if not self._oinfo:
72 77 self._oinfo = ip._ofind(self.iFun)
73 78 return self._oinfo
79 def __str__(self):
80 return "Lineinfo [%s|%s|%s]" %(self.pre,self.iFun,self.theRest)
81
82
83
74 84
75 85
76 86 def splitUserInput(line, pattern=None):
77 87 """Split user input into pre-char/whitespace, function part and rest.
78 88
79 89 Mostly internal to this module, but also used by iplib.expand_aliases,
80 90 which passes in a shell pattern.
81 91 """
82 92 # It seems to me that the shell splitting should be a separate method.
83 93
84 94 if not pattern:
85 95 pattern = line_split
86 96 match = pattern.match(line)
87 97 if not match:
88 98 #print "match failed for line '%s'" % line
89 99 try:
90 100 iFun,theRest = line.split(None,1)
91 101 except ValueError:
92 102 #print "split failed for line '%s'" % line
93 103 iFun,theRest = line,''
94 104 pre = re.match('^(\s*)(.*)',line).groups()[0]
95 105 else:
96 106 pre,iFun,theRest = match.groups()
97 107
98 108 # iFun has to be a valid python identifier, so it better be only pure
99 109 # ascii, no unicode:
100 110 try:
101 111 iFun = iFun.encode('ascii')
102 112 except UnicodeEncodeError:
103 113 theRest = iFun + u' ' + theRest
104 114 iFun = u''
105 115
106 116 #print 'line:<%s>' % line # dbg
107 117 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun.strip(),theRest) # dbg
108 118 return pre,iFun.strip(),theRest.lstrip()
109 119
110 120
111 121 # RegExp for splitting line contents into pre-char//first word-method//rest.
112 122 # For clarity, each group in on one line.
113 123
114 124 # WARNING: update the regexp if the escapes in iplib are changed, as they
115 125 # are hardwired in.
116 126
117 127 # Although it's not solely driven by the regex, note that:
118 128 # ,;/% only trigger if they are the first character on the line
119 129 # ! and !! trigger if they are first char(s) *or* follow an indent
120 130 # ? triggers as first or last char.
121 131
122 132 # The three parts of the regex are:
123 133 # 1) pre: pre_char *or* initial whitespace
124 134 # 2) iFun: first word/method (mix of \w and '.')
125 135 # 3) theRest: rest of line (separated from iFun by space if non-empty)
126 136 line_split = re.compile(r'^([,;/%?]|!!?|\s*)'
127 137 r'\s*([\w\.]+)'
128 138 r'(\s+.*$|$)')
129 139
130 140 shell_line_split = re.compile(r'^(\s*)(\S*\s*)(.*$)')
131 141
132 142 def prefilter(line_info, ip):
133 143 """Call one of the passed-in InteractiveShell's handler preprocessors,
134 144 depending on the form of the line. Return the results, which must be a
135 145 value, even if it's a blank ('')."""
136 146 # Note: the order of these checks does matter.
137 147 for check in [ checkEmacs,
138 148 checkIPyAutocall,
139 149 checkMultiLineShell,
140 150 checkEscChars,
141 151 checkAssignment,
142 152 checkAutomagic,
143 153 checkAlias,
144 154 checkPythonOps,
145 155 checkAutocall,
146 156 ]:
147 157 handler = check(line_info, ip)
148 158 if handler:
149 159 return handler(line_info)
150 160
151 161 return ip.handle_normal(line_info)
152 162
153 163 # Handler checks
154 164 #
155 165 # All have the same interface: they take a LineInfo object and a ref to the
156 166 # iplib.InteractiveShell object. They check the line to see if a particular
157 167 # handler should be called, and return either a handler or None. The
158 168 # handlers which they return are *bound* methods of the InteractiveShell
159 169 # object.
160 170 #
161 171 # In general, these checks should only take responsibility for their 'own'
162 172 # handler. If it doesn't get triggered, they should just return None and
163 173 # let the rest of the check sequence run.
164 174 def checkEmacs(l_info,ip):
165 175 "Emacs ipython-mode tags certain input lines."
166 176 if l_info.line.endswith('# PYTHON-MODE'):
167 177 return ip.handle_emacs
168 178 else:
169 179 return None
170 180
171 181 def checkIPyAutocall(l_info,ip):
172 182 "Instances of IPyAutocall in user_ns get autocalled immediately"
173 183 obj = ip.user_ns.get(l_info.iFun, None)
174 184 if isinstance(obj, IPython.ipapi.IPyAutocall):
175 185 obj.set_ip(ip.api)
176 186 return ip.handle_auto
177 187 else:
178 188 return None
179 189
180 190
181 191 def checkMultiLineShell(l_info,ip):
182 192 "Allow ! and !! in multi-line statements if multi_line_specials is on"
183 193 # Note that this one of the only places we check the first character of
184 194 # iFun and *not* the preChar. Also note that the below test matches
185 195 # both ! and !!.
186 196 if l_info.continue_prompt \
187 197 and ip.rc.multi_line_specials \
188 198 and l_info.iFun.startswith(ip.ESC_SHELL):
189 199 return ip.handle_shell_escape
190 200 else:
191 201 return None
192 202
193 203 def checkEscChars(l_info,ip):
194 204 """Check for escape character and return either a handler to handle it,
195 205 or None if there is no escape char."""
196 206 if l_info.line[-1] == ip.ESC_HELP \
197 207 and l_info.preChar != ip.ESC_SHELL \
198 208 and l_info.preChar != ip.ESC_SH_CAP:
199 209 # the ? can be at the end, but *not* for either kind of shell escape,
200 210 # because a ? can be a vaild final char in a shell cmd
201 211 return ip.handle_help
202 212 elif l_info.preChar in ip.esc_handlers:
203 213 return ip.esc_handlers[l_info.preChar]
204 214 else:
205 215 return None
206 216
207 217
208 218 def checkAssignment(l_info,ip):
209 219 """Check to see if user is assigning to a var for the first time, in
210 220 which case we want to avoid any sort of automagic / autocall games.
211 221
212 222 This allows users to assign to either alias or magic names true python
213 223 variables (the magic/alias systems always take second seat to true
214 224 python code). E.g. ls='hi', or ls,that=1,2"""
215 225 if l_info.theRest and l_info.theRest[0] in '=,':
216 226 return ip.handle_normal
217 227 else:
218 228 return None
219 229
220 230
221 231 def checkAutomagic(l_info,ip):
222 232 """If the iFun is magic, and automagic is on, run it. Note: normal,
223 233 non-auto magic would already have been triggered via '%' in
224 234 check_esc_chars. This just checks for automagic. Also, before
225 235 triggering the magic handler, make sure that there is nothing in the
226 236 user namespace which could shadow it."""
227 237 if not ip.rc.automagic or not hasattr(ip,'magic_'+l_info.iFun):
228 238 return None
229 239
230 240 # We have a likely magic method. Make sure we should actually call it.
231 241 if l_info.continue_prompt and not ip.rc.multi_line_specials:
232 242 return None
233 243
234 244 head = l_info.iFun.split('.',1)[0]
235 245 if isShadowed(head,ip):
236 246 return None
237 247
238 248 return ip.handle_magic
239 249
240 250
241 251 def checkAlias(l_info,ip):
242 252 "Check if the initital identifier on the line is an alias."
243 253 # Note: aliases can not contain '.'
244 254 head = l_info.iFun.split('.',1)[0]
245 255
246 256 if l_info.iFun not in ip.alias_table \
247 257 or head not in ip.alias_table \
248 258 or isShadowed(head,ip):
249 259 return None
250 260
251 261 return ip.handle_alias
252 262
253 263
254 264 def checkPythonOps(l_info,ip):
255 265 """If the 'rest' of the line begins with a function call or pretty much
256 266 any python operator, we should simply execute the line (regardless of
257 267 whether or not there's a possible autocall expansion). This avoids
258 268 spurious (and very confusing) geattr() accesses."""
259 269 if l_info.theRest and l_info.theRest[0] in '!=()<>,+*/%^&|':
260 270 return ip.handle_normal
261 271 else:
262 272 return None
263 273
264 274
265 275 def checkAutocall(l_info,ip):
266 276 "Check if the initial word/function is callable and autocall is on."
267 277 if not ip.rc.autocall:
268 278 return None
269 279
270 280 oinfo = l_info.ofind(ip) # This can mutate state via getattr
271 281 if not oinfo['found']:
272 282 return None
273 283
274 284 if callable(oinfo['obj']) \
275 285 and (not re_exclude_auto.match(l_info.theRest)) \
276 286 and re_fun_name.match(l_info.iFun):
277 287 #print 'going auto' # dbg
278 288 return ip.handle_auto
279 289 else:
280 290 #print 'was callable?', callable(l_info.oinfo['obj']) # dbg
281 291 return None
282 292
283 293 # RegExp to identify potential function names
284 294 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
285 295
286 296 # RegExp to exclude strings with this start from autocalling. In
287 297 # particular, all binary operators should be excluded, so that if foo is
288 298 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
289 299 # characters '!=()' don't need to be checked for, as the checkPythonChars
290 300 # routine explicitely does so, to catch direct calls and rebindings of
291 301 # existing names.
292 302
293 303 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
294 304 # it affects the rest of the group in square brackets.
295 305 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
296 306 r'|^is |^not |^in |^and |^or ')
297 307
298 308 # try to catch also methods for stuff in lists/tuples/dicts: off
299 309 # (experimental). For this to work, the line_split regexp would need
300 310 # to be modified so it wouldn't break things at '['. That line is
301 311 # nasty enough that I shouldn't change it until I can test it _well_.
302 312 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
303 313
304 314 # Handler Check Utilities
305 315 def isShadowed(identifier,ip):
306 316 """Is the given identifier defined in one of the namespaces which shadow
307 317 the alias and magic namespaces? Note that an identifier is different
308 318 than iFun, because it can not contain a '.' character."""
309 319 # This is much safer than calling ofind, which can change state
310 320 return (identifier in ip.user_ns \
311 321 or identifier in ip.internal_ns \
312 322 or identifier in ip.ns_table['builtin'])
313 323
General Comments 0
You need to be logged in to leave comments. Login now