##// END OF EJS Templates
Major refactoring of prefilter mechanism. Much of the transformation process has been moved out of the iplib.InteractiveShell class and into a separate module, IPython.prefilter. In addition, extensive tests have been added for prefiltering.
dan.milstein -
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 # print
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 This file contains all the classes and helper functions specific to IPython.
7 This file contains all the classes and helper functions specific to IPython.
8
8
9 $Id: iplib.py 2350 2007-05-15 16:56:44Z vivainio $
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 from IPython.strdispatch import StrDispatch
75 from IPython.strdispatch import StrDispatch
76 import IPython.ipapi
76 import IPython.ipapi
77
77
78 import IPython.prefilter as prefilter
79
78 # Globals
80 # Globals
79
81
80 # store the builtin raw_input globally, and use this always, in case user code
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 # escapes for automatic behavior on the command line
388 # escapes for automatic behavior on the command line
387 self.ESC_SHELL = '!'
389 self.ESC_SHELL = '!'
390 self.ESC_SH_CAP = '!!'
388 self.ESC_HELP = '?'
391 self.ESC_HELP = '?'
389 self.ESC_MAGIC = '%'
392 self.ESC_MAGIC = '%'
390 self.ESC_QUOTE = ','
393 self.ESC_QUOTE = ','
@@ -398,6 +401,7 b' class InteractiveShell(object,Magic):'
398 self.ESC_MAGIC : self.handle_magic,
401 self.ESC_MAGIC : self.handle_magic,
399 self.ESC_HELP : self.handle_help,
402 self.ESC_HELP : self.handle_help,
400 self.ESC_SHELL : self.handle_shell_escape,
403 self.ESC_SHELL : self.handle_shell_escape,
404 self.ESC_SH_CAP : self.handle_shell_escape,
401 }
405 }
402
406
403 # class initializations
407 # class initializations
@@ -484,57 +488,6 b' class InteractiveShell(object,Magic):'
484 header=self.rc.system_header,
488 header=self.rc.system_header,
485 verbose=self.rc.system_verbose)
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 # keep track of where we started running (mainly for crash post-mortem)
492 # keep track of where we started running (mainly for crash post-mortem)
540 self.starting_dir = os.getcwd()
493 self.starting_dir = os.getcwd()
@@ -1731,8 +1684,8 b' want to merge them back into the new files.""" % locals()'
1731
1684
1732 done = Set()
1685 done = Set()
1733 while 1:
1686 while 1:
1734 pre,fn,rest = self.split_user_input(line, pattern = self.shell_line_split)
1687 pre,fn,rest = prefilter.splitUserInput(line,
1735 # print "!",fn,"!",rest # dbg
1688 prefilter.shell_line_split)
1736 if fn in self.alias_table:
1689 if fn in self.alias_table:
1737 if fn in done:
1690 if fn in done:
1738 warn("Cyclic alias definition, repeated '%s'" % fn)
1691 warn("Cyclic alias definition, repeated '%s'" % fn)
@@ -2056,53 +2009,6 b' want to merge them back into the new files.""" % locals()'
2056 else:
2009 else:
2057 return lineout
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 def _prefilter(self, line, continue_prompt):
2012 def _prefilter(self, line, continue_prompt):
2107 """Calls different preprocessors, depending on the form of line."""
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 # needed, update the cache AND log it (so that the input cache array
2018 # needed, update the cache AND log it (so that the input cache array
2113 # stays synced).
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 # Code begins
2022 # Code begins
2126
2023
@@ -2131,6 +2028,8 b' want to merge them back into the new files.""" % locals()'
2131 self._last_input_line = line
2028 self._last_input_line = line
2132
2029
2133 #print '***line: <%s>' % line # dbg
2030 #print '***line: <%s>' % line # dbg
2031
2032 line_info = prefilter.LineInfo(line, continue_prompt)
2134
2033
2135 # the input history needs to track even empty lines
2034 # the input history needs to track even empty lines
2136 stripped = line.strip()
2035 stripped = line.strip()
@@ -2138,139 +2037,25 b' want to merge them back into the new files.""" % locals()'
2138 if not stripped:
2037 if not stripped:
2139 if not continue_prompt:
2038 if not continue_prompt:
2140 self.outputcache.prompt_count -= 1
2039 self.outputcache.prompt_count -= 1
2141 return self.handle_normal(line,continue_prompt)
2040 return self.handle_normal(line_info)
2142 #return self.handle_normal('',continue_prompt)
2143
2041
2144 # print '***cont',continue_prompt # dbg
2042 # print '***cont',continue_prompt # dbg
2145 # special handlers are only allowed for single line statements
2043 # special handlers are only allowed for single line statements
2146 if continue_prompt and not self.rc.multi_line_specials:
2044 if continue_prompt and not self.rc.multi_line_specials:
2147 return self.handle_normal(line,continue_prompt)
2045 return self.handle_normal(line_info)
2148
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
2048 # See whether any pre-existing handler can take care of it
2154
2155 rewritten = self.hooks.input_prefilter(stripped)
2049 rewritten = self.hooks.input_prefilter(stripped)
2156 if rewritten != stripped: # ok, some prefilter did something
2050 if rewritten != stripped: # ok, some prefilter did something
2157 rewritten = pre + rewritten # add indentation
2051 rewritten = line_info.pre + rewritten # add indentation
2158 return self.handle_normal(rewritten)
2052 return self.handle_normal(prefilter.LineInfo(rewritten,
2053 continue_prompt))
2159
2054
2160 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2055 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2161
2056
2162 # Next, check if we can automatically execute this thing
2057 return prefilter.prefilter(line_info, self)
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)
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 def _prefilter_dumb(self, line, continue_prompt):
2060 def _prefilter_dumb(self, line, continue_prompt):
2276 """simple prefilter function, for debugging"""
2061 """simple prefilter function, for debugging"""
@@ -2293,8 +2078,7 b' want to merge them back into the new files.""" % locals()'
2293 # Set the default prefilter() function (this can be user-overridden)
2078 # Set the default prefilter() function (this can be user-overridden)
2294 prefilter = multiline_prefilter
2079 prefilter = multiline_prefilter
2295
2080
2296 def handle_normal(self,line,continue_prompt=None,
2081 def handle_normal(self,line_info):
2297 pre=None,iFun=None,theRest=None):
2298 """Handle normal input lines. Use as a template for handlers."""
2082 """Handle normal input lines. Use as a template for handlers."""
2299
2083
2300 # With autoindent on, we need some way to exit the input loop, and I
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 # clear the line. The rule will be in this case, that either two
2086 # clear the line. The rule will be in this case, that either two
2303 # lines of pure whitespace in a row, or a line of pure whitespace but
2087 # lines of pure whitespace in a row, or a line of pure whitespace but
2304 # of a size different to the indent level, will exit the input loop.
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 if (continue_prompt and self.autoindent and line.isspace() and
2092 if (continue_prompt and self.autoindent and line.isspace() and
2307 (0 < abs(len(line) - self.indent_current_nsp) <= 2 or
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 self.log(line,line,continue_prompt)
2097 self.log(line,line,continue_prompt)
2312 return line
2098 return line
2313
2099
2314 def handle_alias(self,line,continue_prompt=None,
2100 def handle_alias(self,line_info):
2315 pre=None,iFun=None,theRest=None):
2101 """Handle alias input lines. """
2316 """Handle alias input lines. """
2102 transformed = self.expand_aliases(line_info.iFun,line_info.theRest)
2317
2103
2318 # pre is needed, because it carries the leading whitespace. Otherwise
2104 # pre is needed, because it carries the leading whitespace. Otherwise
2319 # aliases won't work in indented sections.
2105 # aliases won't work in indented sections.
2320 transformed = self.expand_aliases(iFun, theRest)
2106 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2321 line_out = '%s_ip.system(%s)' % (pre, make_quoted_expr( transformed ))
2107 make_quoted_expr( transformed ))
2322 self.log(line,line_out,continue_prompt)
2108
2109 self.log(line_info.line,line_out,line_info.continue_prompt)
2323 #print 'line out:',line_out # dbg
2110 #print 'line out:',line_out # dbg
2324 return line_out
2111 return line_out
2325
2112
2326 def handle_shell_escape(self, line, continue_prompt=None,
2113 def handle_shell_escape(self, line_info):
2327 pre=None,iFun=None,theRest=None):
2328 """Execute the line in a shell, empty return value"""
2114 """Execute the line in a shell, empty return value"""
2329
2330 #print 'line in :', `line` # dbg
2115 #print 'line in :', `line` # dbg
2331 # Example of a special handler. Others follow a similar pattern.
2116 line = line_info.line
2332 if line.lstrip().startswith('!!'):
2117 if line.lstrip().startswith('!!'):
2333 # rewrite iFun/theRest to properly hold the call to %sx and
2118 # rewrite LineInfo's line, iFun and theRest to properly hold the
2334 # the actual command to be executed, so handle_magic can work
2119 # call to %sx and the actual command to be executed, so
2335 # correctly
2120 # handle_magic can work correctly. Note that this works even if
2336 theRest = '%s %s' % (iFun[2:],theRest)
2121 # the line is indented, so it handles multi_line_specials
2337 iFun = 'sx'
2122 # properly.
2338 return self.handle_magic('%ssx %s' % (self.ESC_MAGIC,
2123 new_rest = line.lstrip()[2:]
2339 line.lstrip()[2:]),
2124 line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest)
2340 continue_prompt,pre,iFun,theRest)
2125 line_info.iFun = 'sx'
2126 line_info.theRest = new_rest
2127 return self.handle_magic(line_info)
2341 else:
2128 else:
2342 cmd=line.lstrip().lstrip('!')
2129 cmd = line.lstrip().lstrip('!')
2343 line_out = '%s_ip.system(%s)' % (pre,make_quoted_expr(cmd))
2130 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2131 make_quoted_expr(cmd))
2344 # update cache/log and return
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 return line_out
2134 return line_out
2347
2135
2348 def handle_magic(self, line, continue_prompt=None,
2136 def handle_magic(self, line_info):
2349 pre=None,iFun=None,theRest=None):
2350 """Execute magic functions."""
2137 """Execute magic functions."""
2351
2138 iFun = line_info.iFun
2352
2139 theRest = line_info.theRest
2353 cmd = '%s_ip.magic(%s)' % (pre,make_quoted_expr(iFun + " " + theRest))
2140 cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace,
2354 self.log(line,cmd,continue_prompt)
2141 make_quoted_expr(iFun + " " + theRest))
2142 self.log(line_info.line,cmd,line_info.continue_prompt)
2355 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2143 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2356 return cmd
2144 return cmd
2357
2145
2358 def handle_auto(self, line, continue_prompt=None,
2146 def handle_auto(self, line_info):
2359 pre=None,iFun=None,theRest=None,obj=None):
2360 """Hande lines which can be auto-executed, quoting if requested."""
2147 """Hande lines which can be auto-executed, quoting if requested."""
2361
2148
2362 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
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 # This should only be active for single-line input!
2157 # This should only be active for single-line input!
2365 if continue_prompt:
2158 if continue_prompt:
@@ -2408,14 +2201,14 b' want to merge them back into the new files.""" % locals()'
2408 self.log(line,newcmd,continue_prompt)
2201 self.log(line,newcmd,continue_prompt)
2409 return newcmd
2202 return newcmd
2410
2203
2411 def handle_help(self, line, continue_prompt=None,
2204 def handle_help(self, line_info):
2412 pre=None,iFun=None,theRest=None):
2413 """Try to get some help for the object.
2205 """Try to get some help for the object.
2414
2206
2415 obj? or ?obj -> basic information.
2207 obj? or ?obj -> basic information.
2416 obj?? or ??obj -> more details.
2208 obj?? or ??obj -> more details.
2417 """
2209 """
2418
2210
2211 line = line_info.line
2419 # We need to make sure that we don't process lines which would be
2212 # We need to make sure that we don't process lines which would be
2420 # otherwise valid python, such as "x=1 # what?"
2213 # otherwise valid python, such as "x=1 # what?"
2421 try:
2214 try:
@@ -2426,7 +2219,7 b' want to merge them back into the new files.""" % locals()'
2426 line = line[1:]
2219 line = line[1:]
2427 elif line[-1]==self.ESC_HELP:
2220 elif line[-1]==self.ESC_HELP:
2428 line = line[:-1]
2221 line = line[:-1]
2429 self.log(line,'#?'+line,continue_prompt)
2222 self.log(line,'#?'+line,line_info.continue_prompt)
2430 if line:
2223 if line:
2431 #print 'line:<%r>' % line # dbg
2224 #print 'line:<%r>' % line # dbg
2432 self.magic_pinfo(line)
2225 self.magic_pinfo(line)
@@ -2435,10 +2228,10 b' want to merge them back into the new files.""" % locals()'
2435 return '' # Empty string is needed here!
2228 return '' # Empty string is needed here!
2436 except:
2229 except:
2437 # Pass any other exceptions through to the normal handler
2230 # Pass any other exceptions through to the normal handler
2438 return self.handle_normal(line,continue_prompt)
2231 return self.handle_normal(line_info)
2439 else:
2232 else:
2440 # If the code compiles ok, we should handle it normally
2233 # If the code compiles ok, we should handle it normally
2441 return self.handle_normal(line,continue_prompt)
2234 return self.handle_normal(line_info)
2442
2235
2443 def getapi(self):
2236 def getapi(self):
2444 """ Get an IPApi object for this shell instance
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 return self.api
2246 return self.api
2454
2247
2455 def handle_emacs(self,line,continue_prompt=None,
2248 def handle_emacs(self, line_info):
2456 pre=None,iFun=None,theRest=None):
2457 """Handle input lines marked by python-mode."""
2249 """Handle input lines marked by python-mode."""
2458
2250
2459 # Currently, nothing is done. Later more functionality can be added
2251 # Currently, nothing is done. Later more functionality can be added
2460 # here if needed.
2252 # here if needed.
2461
2253
2462 # The input cache shouldn't be updated
2254 # The input cache shouldn't be updated
2463
2255 return line_info.line
2464 return line
2256
2465
2257
2466 def mktempfile(self,data=None):
2258 def mktempfile(self,data=None):
2467 """Make a new tempfile and return its filename.
2259 """Make a new tempfile and return its filename.
@@ -73,6 +73,7 b' def reset_esc_handlers():'
73 s.ESC_MAGIC : s.handle_magic,
73 s.ESC_MAGIC : s.handle_magic,
74 s.ESC_HELP : s.handle_help,
74 s.ESC_HELP : s.handle_help,
75 s.ESC_SHELL : s.handle_shell_escape,
75 s.ESC_SHELL : s.handle_shell_escape,
76 s.ESC_SH_CAP : s.handle_shell_escape,
76 }
77 }
77 reset_esc_handlers()
78 reset_esc_handlers()
78
79
@@ -145,7 +146,14 b' esc_handler_tests = ['
145 ( '?thing', handle_help, ),
146 ( '?thing', handle_help, ),
146 ( 'thing?', handle_help ), # '?' can trail...
147 ( 'thing?', handle_help ), # '?' can trail...
147 ( 'thing!', handle_normal), # but only '?' can trail
148 ( 'thing!', handle_normal), # but only '?' can trail
148 ( ' ?thing', handle_help), # ignore leading whitespace
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 # Trailing qmark combos. Odd special cases abound
157 # Trailing qmark combos. Odd special cases abound
150 ( '!thing?', handle_shell_escape), # trailing '?' loses to shell esc
158 ( '!thing?', handle_shell_escape), # trailing '?' loses to shell esc
151 ( '!thing ?', handle_shell_escape),
159 ( '!thing ?', handle_shell_escape),
@@ -154,11 +162,6 b' esc_handler_tests = ['
154 ( '/cmd?', handle_help),
162 ( '/cmd?', handle_help),
155 ( ';cmd?', handle_help),
163 ( ';cmd?', handle_help),
156 ( ',cmd?', handle_help),
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 run_handler_tests(esc_handler_tests)
166 run_handler_tests(esc_handler_tests)
164
167
@@ -167,19 +170,26 b' run_handler_tests(esc_handler_tests)'
167 # Shell Escapes in Multi-line statements
170 # Shell Escapes in Multi-line statements
168 # ======================================
171 # ======================================
169 #
172 #
170 # We can't test this via runlines, since the hacked over-handlers all
173 # We can't test this via runlines, since the hacked-over-for-testing
171 # return None, so continue_prompt never becomes true. Instead we drop
174 # handlers all return None, so continue_prompt never becomes true. Instead
172 # into prefilter directly and pass in continue_prompt.
175 # we drop into prefilter directly and pass in continue_prompt.
173
176
174 old_mls = ip.options.multi_line_specials
177 old_mls = ip.options.multi_line_specials
175 ln = '!ls $f multi_line_specials on'
178 for ln in [ ' !ls $f multi_line_specials %s',
176 ignore = ip.IP.prefilter(ln, continue_prompt=True)
179 ' !!ls $f multi_line_specials %s', # !! escapes work on mls
177 check_handler(handle_shell_escape, ln)
180 # Trailing ? doesn't trigger help:
178
181 ' !ls $f multi_line_specials %s ?',
179 ip.options.multi_line_specials = 0
182 ' !!ls $f multi_line_specials %s ?',
180 ln = '!ls $f multi_line_specials off'
183 ]:
181 ignore = ip.IP.prefilter(ln, continue_prompt=True)
184 ip.options.multi_line_specials = 1
182 check_handler(handle_normal, ln)
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 ip.options.multi_line_specials = old_mls
194 ip.options.multi_line_specials = old_mls
185
195
@@ -190,6 +200,7 b' ip.options.multi_line_specials = old_mls'
190 # Pick one magic fun and one non_magic fun, make sure both exist
200 # Pick one magic fun and one non_magic fun, make sure both exist
191 assert hasattr(ip.IP, "magic_cpaste")
201 assert hasattr(ip.IP, "magic_cpaste")
192 assert not hasattr(ip.IP, "magic_does_not_exist")
202 assert not hasattr(ip.IP, "magic_does_not_exist")
203 ip.options.autocall = 0 # gotta have this off to get handle_normal
193 ip.options.automagic = 0
204 ip.options.automagic = 0
194 run_handler_tests([
205 run_handler_tests([
195 # Without automagic, only shows up with explicit escape
206 # Without automagic, only shows up with explicit escape
@@ -214,12 +225,12 b' run_handler_tests(magic_killing_tests)'
214
225
215 # magic on indented continuation lines -- on iff multi_line_specials == 1
226 # magic on indented continuation lines -- on iff multi_line_specials == 1
216 ip.options.multi_line_specials = 0
227 ip.options.multi_line_specials = 0
217 ln = 'cpaste multi_line off kills magic'
228 ln = ' cpaste multi_line off kills magic'
218 ignore = ip.IP.prefilter(ln, continue_prompt=True)
229 ignore = ip.IP.prefilter(ln, continue_prompt=True)
219 check_handler(handle_normal, ln)
230 check_handler(handle_normal, ln)
220
231
221 ip.options.multi_line_specials = 1
232 ip.options.multi_line_specials = 1
222 ln = 'cpaste multi_line on enables magic'
233 ln = ' cpaste multi_line on enables magic'
223 ignore = ip.IP.prefilter(ln, continue_prompt=True)
234 ignore = ip.IP.prefilter(ln, continue_prompt=True)
224 check_handler(handle_magic, ln)
235 check_handler(handle_magic, ln)
225
236
@@ -231,6 +242,7 b' run_handler_tests(['
231 del ip.user_ns['cpaste']
242 del ip.user_ns['cpaste']
232
243
233
244
245
234 # Check for !=() turning off .ofind
246 # Check for !=() turning off .ofind
235 # =================================
247 # =================================
236 class AttributeMutator(object):
248 class AttributeMutator(object):
@@ -249,7 +261,7 b' ip.options.autocall = 1'
249 run_one_test('attr_mutator.foo should mutate', handle_normal)
261 run_one_test('attr_mutator.foo should mutate', handle_normal)
250 check(attr_mutator.called, 'ofind should be called in absence of assign characters')
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 attr_mutator.called = False
265 attr_mutator.called = False
254 run_one_test('attr_mutator.foo %s should *not* mutate' % c, handle_normal)
266 run_one_test('attr_mutator.foo %s should *not* mutate' % c, handle_normal)
255 run_one_test('attr_mutator.foo%s should *not* mutate' % c, handle_normal)
267 run_one_test('attr_mutator.foo%s should *not* mutate' % c, handle_normal)
@@ -296,51 +308,73 b' ip.options.autocall = 1'
296 # Autocall
308 # Autocall
297 # ========
309 # ========
298
310
299 # First, with autocalling fully off
311 # For all the tests below, 'len' is callable / 'thing' is not
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
306
312
307 #( '/len autocall_0', handle_auto),
313 # Objects which are instances of IPyAutocall are *always* autocalled
308 #( ',len autocall_0 b0', handle_auto),
314 import IPython.ipapi
309 #( ';len autocall_0 b0', handle_auto),
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
319 autocallable = Autocallable()
312 ( '/fun autocall_0', handle_normal),
320 ip.to_user_ns('autocallable')
313 ( ',fun autocall_0 b0', handle_normal),
321
314 ( ';fun autocall_0 b0', handle_normal),
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 ( 'len autocall_0', handle_normal),
328 ( 'len autocall_0', handle_normal),
318 ( 'fun autocall_0', handle_normal),
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 # Now, with autocall in default, 'smart' mode
356 # Now, with autocall in default, 'smart' mode
323 ip.options.autocall = 1
357 ip.options.autocall = 1
324 run_handler_tests( [
358 run_handler_tests( [
325 # Since len is callable, these *do* get auto-called
359 # Autocalls without escapes -- only expand if it's callable
326 ( '/len a1', handle_auto),
360 ( 'len a1', handle_auto),
327 ( ',len a1 b1', handle_auto),
361 ( 'thing a1', handle_normal),
328 ( ';len a1 b1', handle_auto),
362 ( 'autocallable', handle_auto),
329 # But these, since fun is not a callable, should *not* get auto-called
363
330 ( '/fun a1', handle_normal),
364 # As above, all explicit escapes generate auto-calls, callable or not
331 ( ',fun a1 b1', handle_normal),
365 ( '/len a1', handle_auto),
332 ( ';fun a1 b1', handle_normal),
366 ( ',len a1 b1', handle_auto),
333 # Autocalls without escapes
367 ( ';len a1 b1', handle_auto),
334 ( 'len a1', handle_auto),
368 ( '/thing a1', handle_auto),
335 ( 'fun a1', handle_normal), # Not callable -> no add
369 ( ',thing a1 b1', handle_auto),
370 ( ';thing a1 b1', handle_auto),
371
336 # Autocalls only happen on things which look like funcs, even if
372 # Autocalls only happen on things which look like funcs, even if
337 # explicitly requested. Which, in this case means they look like a
373 # explicitly requested. Which, in this case means they look like a
338 # sequence of identifiers and . attribute references. So the second
374 # sequence of identifiers and . attribute references. Possibly the
339 # test should pass, but it's not at the moment (meaning, IPython is
375 # second of these two should trigger handle_auto. But not for now.
340 # attempting to run an autocall). Though it does blow up in ipython
341 # later (because of how lines are split, I think).
342 ( '"abc".join range(4)', handle_normal),
376 ( '"abc".join range(4)', handle_normal),
343 # XXX ( '/"abc".join range(4)', handle_normal),
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