##// END OF EJS Templates
Refined checking for assignment vs other python operators in the new input transformation/prefiltering system. This makes it once again possible for magics to do useful things which involve python operator characters (e.g. 'cd /'). Also added tests to verify this.
dan.milstein -
Show More
@@ -138,8 +138,9 b' def prefilter(line_info, ip):'
138 checkIPyAutocall,
138 checkIPyAutocall,
139 checkMultiLineShell,
139 checkMultiLineShell,
140 checkEscChars,
140 checkEscChars,
141 checkPythonChars,
141 checkAssignment,
142 checkAutomagic,
142 checkAutomagic,
143 checkPythonOps,
143 checkAlias,
144 checkAlias,
144 checkAutocall,
145 checkAutocall,
145 ]:
146 ]:
@@ -202,24 +203,27 b' def checkEscChars(l_info,ip):'
202 return ip.esc_handlers[l_info.preChar]
203 return ip.esc_handlers[l_info.preChar]
203 else:
204 else:
204 return None
205 return None
206
207
208 def checkAssignment(l_info,ip):
209 """Check to see if user is assigning to a var for the first time, in
210 which case we want to avoid any sort of automagic / autocall games.
205
211
206 def checkPythonChars(l_info,ip):
212 This allows users to assign to either alias or magic names true python
207 """If the 'rest' of the line begins with an (in)equality, assginment,
213 variables (the magic/alias systems always take second seat to true
208 function call or tuple comma, we should simply execute the line
214 python code). E.g. ls='hi', or ls,that=1,2"""
209 (regardless of whether or not there's a possible alias, automagic or
215 if l_info.theRest and l_info.theRest[0] in '=,':
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 return ip.handle_normal
216 else:
217 else:
217 return None
218 return None
218
219
220
219 def checkAutomagic(l_info,ip):
221 def checkAutomagic(l_info,ip):
220 """If the iFun is magic, and automagic is on, run it. Note: normal,
222 """If the iFun is magic, and automagic is on, run it. Note: normal,
221 non-auto magic would already have been triggered via '%' in
223 non-auto magic would already have been triggered via '%' in
222 check_esc_chars. This just checks for automagic."""
224 check_esc_chars. This just checks for automagic. Also, before
225 triggering the magic handler, make sure that there is nothing in the
226 user namespace which could shadow it."""
223 if not ip.rc.automagic or not hasattr(ip,'magic_'+l_info.iFun):
227 if not ip.rc.automagic or not hasattr(ip,'magic_'+l_info.iFun):
224 return None
228 return None
225
229
@@ -233,7 +237,18 b' def checkAutomagic(l_info,ip):'
233
237
234 return ip.handle_magic
238 return ip.handle_magic
235
239
236
240
241 def checkPythonOps(l_info,ip):
242 """If the 'rest' of the line begins with a function call or pretty much
243 any python operator, we should simply execute the line (regardless of
244 whether or not there's a possible alias or autocall expansion). This
245 avoids spurious (and very confusing) geattr() accesses."""
246 if l_info.theRest and l_info.theRest[0] in '!=()<>,+*/%^&|':
247 return ip.handle_normal
248 else:
249 return None
250
251
237 def checkAlias(l_info,ip):
252 def checkAlias(l_info,ip):
238 "Check if the initital identifier on the line is an alias."
253 "Check if the initital identifier on the line is an alias."
239 # Note: aliases can not contain '.'
254 # Note: aliases can not contain '.'
@@ -206,22 +206,25 b' run_handler_tests(['
206 # Without automagic, only shows up with explicit escape
206 # Without automagic, only shows up with explicit escape
207 ( 'cpaste', handle_normal),
207 ( 'cpaste', handle_normal),
208 ( '%cpaste', handle_magic),
208 ( '%cpaste', handle_magic),
209 ( '%does_not_exist', handle_magic)
209 ( '%does_not_exist', handle_magic),
210 ])
210 ])
211 ip.options.automagic = 1
211 ip.options.automagic = 1
212 run_handler_tests([
212 run_handler_tests([
213 ( 'cpaste', handle_magic),
213 ( 'cpaste', handle_magic),
214 ( '%cpaste', handle_magic),
214 ( '%cpaste', handle_magic),
215 ( 'does_not_exist', handle_normal),
215 ( 'does_not_exist', handle_normal),
216 ( '%does_not_exist', handle_magic)])
216 ( '%does_not_exist', handle_magic),
217 ( 'cd /', handle_magic),
218 ( 'cd = 2', handle_normal),
219 ])
217
220
218 # If next elt starts with anything that could be an assignment, func call,
221 # If next elt starts with anything that could be an assignment, func call,
219 # etc, we don't call the magic func, unless explicitly escaped to do so.
222 # etc, we don't call the magic func, unless explicitly escaped to do so.
220 magic_killing_tests = []
223 #magic_killing_tests = []
221 for c in list('!=()<>,'):
224 #for c in list('!=()<>,'):
222 magic_killing_tests.append(('cpaste %s killed_automagic' % c, handle_normal))
225 # magic_killing_tests.append(('cpaste %s killed_automagic' % c, handle_normal))
223 magic_killing_tests.append(('%%cpaste %s escaped_magic' % c, handle_magic))
226 # magic_killing_tests.append(('%%cpaste %s escaped_magic' % c, handle_magic))
224 run_handler_tests(magic_killing_tests)
227 #run_handler_tests(magic_killing_tests)
225
228
226 # magic on indented continuation lines -- on iff multi_line_specials == 1
229 # magic on indented continuation lines -- on iff multi_line_specials == 1
227 ip.options.multi_line_specials = 0
230 ip.options.multi_line_specials = 0
General Comments 0
You need to be logged in to leave comments. Login now