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