##// END OF EJS Templates
update prefilter tests
vivainio -
Show More
@@ -1,443 +1,439 b''
1 """
1 """
2 Test which prefilter transformations get called for various input lines.
2 Test which prefilter transformations get called for various input lines.
3 Note that this does *not* test the transformations themselves -- it's just
3 Note that this does *not* test the transformations themselves -- it's just
4 verifying that a particular combination of, e.g. config options and escape
4 verifying that a particular combination of, e.g. config options and escape
5 chars trigger the proper handle_X transform of the input line.
5 chars trigger the proper handle_X transform of the input line.
6
6
7 Usage: run from the command line with *normal* python, not ipython:
7 Usage: run from the command line with *normal* python, not ipython:
8 > python test_prefilter.py
8 > python test_prefilter.py
9
9
10 Fairly quiet output by default. Pass in -v to get everyone's favorite dots.
10 Fairly quiet output by default. Pass in -v to get everyone's favorite dots.
11 """
11 """
12
12
13 # The prefilter always ends in a call to some self.handle_X method. We swap
13 # The prefilter always ends in a call to some self.handle_X method. We swap
14 # all of those out so that we can capture which one was called.
14 # all of those out so that we can capture which one was called.
15
15
16 import sys
16 import sys
17 sys.path.append('..')
17 sys.path.append('..')
18 import IPython
18 import IPython
19 import IPython.ipapi
19 import IPython.ipapi
20
20
21 verbose = False
21 verbose = False
22 if len(sys.argv) > 1:
22 if len(sys.argv) > 1:
23 if sys.argv[1] == '-v':
23 if sys.argv[1] == '-v':
24 sys.argv = sys.argv[:-1] # IPython is confused by -v, apparently
24 sys.argv = sys.argv[:-1] # IPython is confused by -v, apparently
25 verbose = True
25 verbose = True
26
26
27 IPython.Shell.start()
27 IPython.Shell.start()
28
28
29 ip = IPython.ipapi.get()
29 ip = IPython.ipapi.get()
30
30
31 # Collect failed tests + stats and print them at the end
31 # Collect failed tests + stats and print them at the end
32 failures = []
32 failures = []
33 num_tests = 0
33 num_tests = 0
34
34
35 # Store the results in module vars as we go
35 # Store the results in module vars as we go
36 last_line = None
36 last_line = None
37 handler_called = None
37 handler_called = None
38 def install_mock_handler(name):
38 def install_mock_handler(name):
39 """Swap out one of the IP.handle_x methods with a function which can
39 """Swap out one of the IP.handle_x methods with a function which can
40 record which handler was called and what line was produced. The mock
40 record which handler was called and what line was produced. The mock
41 handler func always returns '', which causes ipython to cease handling
41 handler func always returns '', which causes ipython to cease handling
42 the string immediately. That way, that it doesn't echo output, raise
42 the string immediately. That way, that it doesn't echo output, raise
43 exceptions, etc. But do note that testing multiline strings thus gets
43 exceptions, etc. But do note that testing multiline strings thus gets
44 a bit hard."""
44 a bit hard."""
45 def mock_handler(self, line, continue_prompt=None,
45 def mock_handler(self, line, continue_prompt=None,
46 pre=None,iFun=None,theRest=None,
46 pre=None,iFun=None,theRest=None,
47 obj=None):
47 obj=None):
48 #print "Inside %s with '%s'" % (name, line)
48 #print "Inside %s with '%s'" % (name, line)
49 global last_line, handler_called
49 global last_line, handler_called
50 last_line = line
50 last_line = line
51 handler_called = name
51 handler_called = name
52 return ''
52 return ''
53 mock_handler.name = name
53 mock_handler.name = name
54 setattr(IPython.iplib.InteractiveShell, name, mock_handler)
54 setattr(IPython.iplib.InteractiveShell, name, mock_handler)
55
55
56 install_mock_handler('handle_normal')
56 install_mock_handler('handle_normal')
57 install_mock_handler('handle_auto')
57 install_mock_handler('handle_auto')
58 install_mock_handler('handle_magic')
58 install_mock_handler('handle_magic')
59 install_mock_handler('handle_help')
59 install_mock_handler('handle_help')
60 install_mock_handler('handle_shell_escape')
60 install_mock_handler('handle_shell_escape')
61 install_mock_handler('handle_alias')
61 install_mock_handler('handle_alias')
62 install_mock_handler('handle_emacs')
62 install_mock_handler('handle_emacs')
63
63
64
64
65 def reset_esc_handlers():
65 def reset_esc_handlers():
66 """The escape handlers are stored in a hash (as an attribute of the
66 """The escape handlers are stored in a hash (as an attribute of the
67 InteractiveShell *instance*), so we have to rebuild that hash to get our
67 InteractiveShell *instance*), so we have to rebuild that hash to get our
68 new handlers in there."""
68 new handlers in there."""
69 s = ip.IP
69 s = ip.IP
70 s.esc_handlers = {s.ESC_PAREN : s.handle_auto,
70 s.esc_handlers = {s.ESC_PAREN : s.handle_auto,
71 s.ESC_QUOTE : s.handle_auto,
71 s.ESC_QUOTE : s.handle_auto,
72 s.ESC_QUOTE2 : s.handle_auto,
72 s.ESC_QUOTE2 : s.handle_auto,
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 s.ESC_SH_CAP : s.handle_shell_escape,
77 }
77 }
78 reset_esc_handlers()
78 reset_esc_handlers()
79
79
80 # This is so I don't have to quote over and over. Gotta be a better way.
80 # This is so I don't have to quote over and over. Gotta be a better way.
81 handle_normal = 'handle_normal'
81 handle_normal = 'handle_normal'
82 handle_auto = 'handle_auto'
82 handle_auto = 'handle_auto'
83 handle_magic = 'handle_magic'
83 handle_magic = 'handle_magic'
84 handle_help = 'handle_help'
84 handle_help = 'handle_help'
85 handle_shell_escape = 'handle_shell_escape'
85 handle_shell_escape = 'handle_shell_escape'
86 handle_alias = 'handle_alias'
86 handle_alias = 'handle_alias'
87 handle_emacs = 'handle_emacs'
87 handle_emacs = 'handle_emacs'
88
88
89 def check(assertion, failure_msg):
89 def check(assertion, failure_msg):
90 """Check a boolean assertion and fail with a message if necessary. Store
90 """Check a boolean assertion and fail with a message if necessary. Store
91 an error essage in module-level failures list in case of failure. Print
91 an error essage in module-level failures list in case of failure. Print
92 '.' or 'F' if module var Verbose is true.
92 '.' or 'F' if module var Verbose is true.
93 """
93 """
94 global num_tests
94 global num_tests
95 num_tests += 1
95 num_tests += 1
96 if assertion:
96 if assertion:
97 if verbose:
97 if verbose:
98 sys.stdout.write('.')
98 sys.stdout.write('.')
99 sys.stdout.flush()
99 sys.stdout.flush()
100 else:
100 else:
101 if verbose:
101 if verbose:
102 sys.stdout.write('F')
102 sys.stdout.write('F')
103 sys.stdout.flush()
103 sys.stdout.flush()
104 failures.append(failure_msg)
104 failures.append(failure_msg)
105
105
106
106
107 def check_handler(expected_handler, line):
107 def check_handler(expected_handler, line):
108 """Verify that the expected hander was called (for the given line,
108 """Verify that the expected hander was called (for the given line,
109 passed in for failure reporting).
109 passed in for failure reporting).
110
110
111 Pulled out to its own function so that tests which don't use
111 Pulled out to its own function so that tests which don't use
112 run_handler_tests can still take advantage of it."""
112 run_handler_tests can still take advantage of it."""
113 check(handler_called == expected_handler,
113 check(handler_called == expected_handler,
114 "Expected %s to be called for %s, "
114 "Expected %s to be called for %s, "
115 "instead %s called" % (expected_handler,
115 "instead %s called" % (expected_handler,
116 repr(line),
116 repr(line),
117 handler_called))
117 handler_called))
118
118
119
119
120 def run_handler_tests(h_tests):
120 def run_handler_tests(h_tests):
121 """Loop through a series of (input_line, handler_name) pairs, verifying
121 """Loop through a series of (input_line, handler_name) pairs, verifying
122 that, for each ip calls the given handler for the given line.
122 that, for each ip calls the given handler for the given line.
123
123
124 The verbose complaint includes the line passed in, so if that line can
124 The verbose complaint includes the line passed in, so if that line can
125 include enough info to find the error, the tests are modestly
125 include enough info to find the error, the tests are modestly
126 self-documenting.
126 self-documenting.
127 """
127 """
128 for ln, expected_handler in h_tests:
128 for ln, expected_handler in h_tests:
129 global handler_called
129 global handler_called
130 handler_called = None
130 handler_called = None
131 ip.runlines(ln)
131 ip.runlines(ln)
132 check_handler(expected_handler, ln)
132 check_handler(expected_handler, ln)
133
133
134 def run_one_test(ln, expected_handler):
134 def run_one_test(ln, expected_handler):
135 run_handler_tests([(ln, expected_handler)])
135 run_handler_tests([(ln, expected_handler)])
136
136
137
137
138 # =========================================
138 # =========================================
139 # Tests
139 # Tests
140 # =========================================
140 # =========================================
141
141
142
142
143 # Fundamental escape characters + whitespace & misc
143 # Fundamental escape characters + whitespace & misc
144 # =================================================
144 # =================================================
145 esc_handler_tests = [
145 esc_handler_tests = [
146 ( '?thing', handle_help, ),
146 ( '?thing', handle_help, ),
147 ( 'thing?', handle_help ), # '?' can trail...
147 ( 'thing?', handle_help ), # '?' can trail...
148 ( 'thing!', handle_normal), # but only '?' can trail
148 ( 'thing!', handle_normal), # but only '?' can trail
149 ( ' ?thing', handle_normal), # leading whitespace turns off esc chars
149 ( ' ?thing', handle_normal), # leading whitespace turns off esc chars
150 ( '!ls', handle_shell_escape),
150 ( '!ls', handle_shell_escape),
151 ( '! true', handle_shell_escape),
151 ( '! true', handle_shell_escape),
152 ( '!! true', handle_shell_escape),
152 ( '!! true', handle_shell_escape),
153 ( '%magic', handle_magic),
153 ( '%magic', handle_magic),
154 # XXX Possibly, add test for /,; once those are unhooked from %autocall
154 # XXX Possibly, add test for /,; once those are unhooked from %autocall
155 ( 'emacs_mode # PYTHON-MODE', handle_emacs ),
155 ( 'emacs_mode # PYTHON-MODE', handle_emacs ),
156 ( ' ', handle_normal),
156 ( ' ', handle_normal),
157
157
158 # Trailing qmark combos. Odd special cases abound
158 # Trailing qmark combos. Odd special cases abound
159
159
160 # The key is: we don't want the trailing ? to trigger help if it's a
160 # ! always takes priority!
161 # part of a shell glob (like, e.g. '!ls file.?'). Instead, we want the
161 ( '!thing?', handle_shell_escape),
162 # shell handler to be called. Due to subtleties of the input string
163 # parsing, however, we only call the shell handler if the trailing ? is
164 # part of something whitespace-separated from the !cmd. See examples.
165 ( '!thing?', handle_help),
166 ( '!thing arg?', handle_shell_escape),
162 ( '!thing arg?', handle_shell_escape),
167 ( '!!thing?', handle_help),
163 ( '!!thing?', handle_shell_escape),
168 ( '!!thing arg?', handle_shell_escape),
164 ( '!!thing arg?', handle_shell_escape),
169
165
170 # For all other leading esc chars, we always trigger help
166 # For all other leading esc chars, we always trigger help
171 ( '%cmd?', handle_help),
167 ( '%cmd?', handle_help),
172 ( '%cmd ?', handle_help),
168 ( '%cmd ?', handle_help),
173 ( '/cmd?', handle_help),
169 ( '/cmd?', handle_help),
174 ( '/cmd ?', handle_help),
170 ( '/cmd ?', handle_help),
175 ( ';cmd?', handle_help),
171 ( ';cmd?', handle_help),
176 ( ',cmd?', handle_help),
172 ( ',cmd?', handle_help),
177 ]
173 ]
178 run_handler_tests(esc_handler_tests)
174 run_handler_tests(esc_handler_tests)
179
175
180
176
181
177
182 # Shell Escapes in Multi-line statements
178 # Shell Escapes in Multi-line statements
183 # ======================================
179 # ======================================
184 #
180 #
185 # We can't test this via runlines, since the hacked-over-for-testing
181 # We can't test this via runlines, since the hacked-over-for-testing
186 # handlers all return None, so continue_prompt never becomes true. Instead
182 # handlers all return None, so continue_prompt never becomes true. Instead
187 # we drop into prefilter directly and pass in continue_prompt.
183 # we drop into prefilter directly and pass in continue_prompt.
188
184
189 old_mls = ip.options.multi_line_specials
185 old_mls = ip.options.multi_line_specials
190 for ln in [ ' !ls $f multi_line_specials %s',
186 for ln in [ ' !ls $f multi_line_specials %s',
191 ' !!ls $f multi_line_specials %s', # !! escapes work on mls
187 ' !!ls $f multi_line_specials %s', # !! escapes work on mls
192 # Trailing ? doesn't trigger help:
188 # Trailing ? doesn't trigger help:
193 ' !ls $f multi_line_specials %s ?',
189 ' !ls $f multi_line_specials %s ?',
194 ' !!ls $f multi_line_specials %s ?',
190 ' !!ls $f multi_line_specials %s ?',
195 ]:
191 ]:
196 ip.options.multi_line_specials = 1
192 ip.options.multi_line_specials = 1
197 on_ln = ln % 'on'
193 on_ln = ln % 'on'
198 ignore = ip.IP.prefilter(on_ln, continue_prompt=True)
194 ignore = ip.IP.prefilter(on_ln, continue_prompt=True)
199 check_handler(handle_shell_escape, on_ln)
195 check_handler(handle_shell_escape, on_ln)
200
196
201 ip.options.multi_line_specials = 0
197 ip.options.multi_line_specials = 0
202 off_ln = ln % 'off'
198 off_ln = ln % 'off'
203 ignore = ip.IP.prefilter(off_ln, continue_prompt=True)
199 ignore = ip.IP.prefilter(off_ln, continue_prompt=True)
204 check_handler(handle_normal, off_ln)
200 check_handler(handle_normal, off_ln)
205
201
206 ip.options.multi_line_specials = old_mls
202 ip.options.multi_line_specials = old_mls
207
203
208
204
209 # Automagic
205 # Automagic
210 # =========
206 # =========
211
207
212 # Pick one magic fun and one non_magic fun, make sure both exist
208 # Pick one magic fun and one non_magic fun, make sure both exist
213 assert hasattr(ip.IP, "magic_cpaste")
209 assert hasattr(ip.IP, "magic_cpaste")
214 assert not hasattr(ip.IP, "magic_does_not_exist")
210 assert not hasattr(ip.IP, "magic_does_not_exist")
215 ip.options.autocall = 0 # gotta have this off to get handle_normal
211 ip.options.autocall = 0 # gotta have this off to get handle_normal
216 ip.options.automagic = 0
212 ip.options.automagic = 0
217 run_handler_tests([
213 run_handler_tests([
218 # Without automagic, only shows up with explicit escape
214 # Without automagic, only shows up with explicit escape
219 ( 'cpaste', handle_normal),
215 ( 'cpaste', handle_normal),
220 ( '%cpaste', handle_magic),
216 ( '%cpaste', handle_magic),
221 ( '%does_not_exist', handle_magic),
217 ( '%does_not_exist', handle_magic),
222 ])
218 ])
223 ip.options.automagic = 1
219 ip.options.automagic = 1
224 run_handler_tests([
220 run_handler_tests([
225 ( 'cpaste', handle_magic),
221 ( 'cpaste', handle_magic),
226 ( '%cpaste', handle_magic),
222 ( '%cpaste', handle_magic),
227 ( 'does_not_exist', handle_normal),
223 ( 'does_not_exist', handle_normal),
228 ( '%does_not_exist', handle_magic),
224 ( '%does_not_exist', handle_magic),
229 ( 'cd /', handle_magic),
225 ( 'cd /', handle_magic),
230 ( 'cd = 2', handle_normal),
226 ( 'cd = 2', handle_normal),
231 ( 'r', handle_magic),
227 ( 'r', handle_magic),
232 ( 'r thing', handle_magic),
228 ( 'r thing', handle_magic),
233 ( 'r"str"', handle_normal),
229 ( 'r"str"', handle_normal),
234 ])
230 ])
235
231
236 # If next elt starts with anything that could be an assignment, func call,
232 # If next elt starts with anything that could be an assignment, func call,
237 # etc, we don't call the magic func, unless explicitly escaped to do so.
233 # etc, we don't call the magic func, unless explicitly escaped to do so.
238 #magic_killing_tests = []
234 #magic_killing_tests = []
239 #for c in list('!=()<>,'):
235 #for c in list('!=()<>,'):
240 # magic_killing_tests.append(('cpaste %s killed_automagic' % c, handle_normal))
236 # magic_killing_tests.append(('cpaste %s killed_automagic' % c, handle_normal))
241 # magic_killing_tests.append(('%%cpaste %s escaped_magic' % c, handle_magic))
237 # magic_killing_tests.append(('%%cpaste %s escaped_magic' % c, handle_magic))
242 #run_handler_tests(magic_killing_tests)
238 #run_handler_tests(magic_killing_tests)
243
239
244 # magic on indented continuation lines -- on iff multi_line_specials == 1
240 # magic on indented continuation lines -- on iff multi_line_specials == 1
245 ip.options.multi_line_specials = 0
241 ip.options.multi_line_specials = 0
246 ln = ' cpaste multi_line off kills magic'
242 ln = ' cpaste multi_line off kills magic'
247 ignore = ip.IP.prefilter(ln, continue_prompt=True)
243 ignore = ip.IP.prefilter(ln, continue_prompt=True)
248 check_handler(handle_normal, ln)
244 check_handler(handle_normal, ln)
249
245
250 ip.options.multi_line_specials = 1
246 ip.options.multi_line_specials = 1
251 ln = ' cpaste multi_line on enables magic'
247 ln = ' cpaste multi_line on enables magic'
252 ignore = ip.IP.prefilter(ln, continue_prompt=True)
248 ignore = ip.IP.prefilter(ln, continue_prompt=True)
253 check_handler(handle_magic, ln)
249 check_handler(handle_magic, ln)
254
250
255 # user namespace shadows the magic one unless shell escaped
251 # user namespace shadows the magic one unless shell escaped
256 ip.user_ns['cpaste'] = 'user_ns'
252 ip.user_ns['cpaste'] = 'user_ns'
257 run_handler_tests([
253 run_handler_tests([
258 ( 'cpaste', handle_normal),
254 ( 'cpaste', handle_normal),
259 ( '%cpaste', handle_magic)])
255 ( '%cpaste', handle_magic)])
260 del ip.user_ns['cpaste']
256 del ip.user_ns['cpaste']
261
257
262
258
263
259
264 # Check for !=() turning off .ofind
260 # Check for !=() turning off .ofind
265 # =================================
261 # =================================
266 class AttributeMutator(object):
262 class AttributeMutator(object):
267 """A class which will be modified on attribute access, to test ofind"""
263 """A class which will be modified on attribute access, to test ofind"""
268 def __init__(self):
264 def __init__(self):
269 self.called = False
265 self.called = False
270
266
271 def getFoo(self): self.called = True
267 def getFoo(self): self.called = True
272 foo = property(getFoo)
268 foo = property(getFoo)
273
269
274 attr_mutator = AttributeMutator()
270 attr_mutator = AttributeMutator()
275 ip.to_user_ns('attr_mutator')
271 ip.to_user_ns('attr_mutator')
276
272
277 ip.options.autocall = 1
273 ip.options.autocall = 1
278
274
279 run_one_test('attr_mutator.foo should mutate', handle_normal)
275 run_one_test('attr_mutator.foo should mutate', handle_normal)
280 check(attr_mutator.called, 'ofind should be called in absence of assign characters')
276 check(attr_mutator.called, 'ofind should be called in absence of assign characters')
281
277
282 for c in list('!=()<>+*/%^&|'):
278 for c in list('!=()<>+*/%^&|'):
283 attr_mutator.called = False
279 attr_mutator.called = False
284 run_one_test('attr_mutator.foo %s should *not* mutate' % c, handle_normal)
280 run_one_test('attr_mutator.foo %s should *not* mutate' % c, handle_normal)
285 run_one_test('attr_mutator.foo%s should *not* mutate' % c, handle_normal)
281 run_one_test('attr_mutator.foo%s should *not* mutate' % c, handle_normal)
286
282
287 check(not attr_mutator.called,
283 check(not attr_mutator.called,
288 'ofind should not be called near character %s' % c)
284 'ofind should not be called near character %s' % c)
289
285
290
286
291
287
292 # Alias expansion
288 # Alias expansion
293 # ===============
289 # ===============
294
290
295 # With autocall on or off, aliases should be shadowed by user, internal and
291 # With autocall on or off, aliases should be shadowed by user, internal and
296 # __builtin__ namespaces
292 # __builtin__ namespaces
297 #
293 #
298 # XXX Can aliases have '.' in their name? With autocall off, that works,
294 # XXX Can aliases have '.' in their name? With autocall off, that works,
299 # with autocall on, it doesn't. Hmmm.
295 # with autocall on, it doesn't. Hmmm.
300 import __builtin__
296 import __builtin__
301 for ac_state in [0,1]:
297 for ac_state in [0,1]:
302 ip.options.autocall = ac_state
298 ip.options.autocall = ac_state
303 ip.IP.alias_table['alias_cmd'] = 'alias_result'
299 ip.IP.alias_table['alias_cmd'] = 'alias_result'
304 ip.IP.alias_table['alias_head.with_dot'] = 'alias_result'
300 ip.IP.alias_table['alias_head.with_dot'] = 'alias_result'
305 run_handler_tests([
301 run_handler_tests([
306 ("alias_cmd", handle_alias),
302 ("alias_cmd", handle_alias),
307 # XXX See note above
303 # XXX See note above
308 #("alias_head.with_dot unshadowed, autocall=%s" % ac_state, handle_alias),
304 #("alias_head.with_dot unshadowed, autocall=%s" % ac_state, handle_alias),
309 ("alias_cmd.something aliases must match whole expr", handle_normal),
305 ("alias_cmd.something aliases must match whole expr", handle_normal),
310 ("alias_cmd /", handle_alias),
306 ("alias_cmd /", handle_alias),
311 ])
307 ])
312
308
313 for ns in [ip.user_ns, ip.IP.internal_ns, __builtin__.__dict__ ]:
309 for ns in [ip.user_ns, ip.IP.internal_ns, __builtin__.__dict__ ]:
314 ns['alias_cmd'] = 'a user value'
310 ns['alias_cmd'] = 'a user value'
315 ns['alias_head'] = 'a user value'
311 ns['alias_head'] = 'a user value'
316 run_handler_tests([
312 run_handler_tests([
317 ("alias_cmd", handle_normal),
313 ("alias_cmd", handle_normal),
318 ("alias_head.with_dot", handle_normal)])
314 ("alias_head.with_dot", handle_normal)])
319 del ns['alias_cmd']
315 del ns['alias_cmd']
320 del ns['alias_head']
316 del ns['alias_head']
321
317
322 ip.options.autocall = 1
318 ip.options.autocall = 1
323
319
324
320
325
321
326
322
327 # Autocall
323 # Autocall
328 # ========
324 # ========
329
325
330 # For all the tests below, 'len' is callable / 'thing' is not
326 # For all the tests below, 'len' is callable / 'thing' is not
331
327
332 # Objects which are instances of IPyAutocall are *always* autocalled
328 # Objects which are instances of IPyAutocall are *always* autocalled
333 import IPython.ipapi
329 import IPython.ipapi
334 class Autocallable(IPython.ipapi.IPyAutocall):
330 class Autocallable(IPython.ipapi.IPyAutocall):
335 def __call__(self):
331 def __call__(self):
336 return "called"
332 return "called"
337
333
338 autocallable = Autocallable()
334 autocallable = Autocallable()
339 ip.to_user_ns('autocallable')
335 ip.to_user_ns('autocallable')
340
336
341
337
342 # First, with autocalling fully off
338 # First, with autocalling fully off
343 ip.options.autocall = 0
339 ip.options.autocall = 0
344 run_handler_tests( [
340 run_handler_tests( [
345 # With no escapes, no autocalling expansions happen, callable or not,
341 # With no escapes, no autocalling expansions happen, callable or not,
346 # unless the obj extends IPyAutocall
342 # unless the obj extends IPyAutocall
347 ( 'len autocall_0', handle_normal),
343 ( 'len autocall_0', handle_normal),
348 ( 'thing autocall_0', handle_normal),
344 ( 'thing autocall_0', handle_normal),
349 ( 'autocallable', handle_auto),
345 ( 'autocallable', handle_auto),
350
346
351 # With explicit escapes, callable and non-callables both get expanded,
347 # With explicit escapes, callable and non-callables both get expanded,
352 # regardless of the %autocall setting:
348 # regardless of the %autocall setting:
353 ( '/len autocall_0', handle_auto),
349 ( '/len autocall_0', handle_auto),
354 ( ',len autocall_0 b0', handle_auto),
350 ( ',len autocall_0 b0', handle_auto),
355 ( ';len autocall_0 b0', handle_auto),
351 ( ';len autocall_0 b0', handle_auto),
356
352
357 ( '/thing autocall_0', handle_auto),
353 ( '/thing autocall_0', handle_auto),
358 ( ',thing autocall_0 b0', handle_auto),
354 ( ',thing autocall_0 b0', handle_auto),
359 ( ';thing autocall_0 b0', handle_auto),
355 ( ';thing autocall_0 b0', handle_auto),
360
356
361 # Explicit autocall should not trigger if there is leading whitespace
357 # Explicit autocall should not trigger if there is leading whitespace
362 ( ' /len autocall_0', handle_normal),
358 ( ' /len autocall_0', handle_normal),
363 ( ' ;len autocall_0', handle_normal),
359 ( ' ;len autocall_0', handle_normal),
364 ( ' ,len autocall_0', handle_normal),
360 ( ' ,len autocall_0', handle_normal),
365 ( ' / len autocall_0', handle_normal),
361 ( ' / len autocall_0', handle_normal),
366
362
367 # But should work if the whitespace comes after the esc char
363 # But should work if the whitespace comes after the esc char
368 ( '/ len autocall_0', handle_auto),
364 ( '/ len autocall_0', handle_auto),
369 ( '; len autocall_0', handle_auto),
365 ( '; len autocall_0', handle_auto),
370 ( ', len autocall_0', handle_auto),
366 ( ', len autocall_0', handle_auto),
371 ( '/ len autocall_0', handle_auto),
367 ( '/ len autocall_0', handle_auto),
372 ])
368 ])
373
369
374
370
375 # Now, with autocall in default, 'smart' mode
371 # Now, with autocall in default, 'smart' mode
376 ip.options.autocall = 1
372 ip.options.autocall = 1
377 run_handler_tests( [
373 run_handler_tests( [
378 # Autocalls without escapes -- only expand if it's callable
374 # Autocalls without escapes -- only expand if it's callable
379 ( 'len a1', handle_auto),
375 ( 'len a1', handle_auto),
380 ( 'thing a1', handle_normal),
376 ( 'thing a1', handle_normal),
381 ( 'autocallable', handle_auto),
377 ( 'autocallable', handle_auto),
382
378
383 # As above, all explicit escapes generate auto-calls, callable or not
379 # As above, all explicit escapes generate auto-calls, callable or not
384 ( '/len a1', handle_auto),
380 ( '/len a1', handle_auto),
385 ( ',len a1 b1', handle_auto),
381 ( ',len a1 b1', handle_auto),
386 ( ';len a1 b1', handle_auto),
382 ( ';len a1 b1', handle_auto),
387 ( '/thing a1', handle_auto),
383 ( '/thing a1', handle_auto),
388 ( ',thing a1 b1', handle_auto),
384 ( ',thing a1 b1', handle_auto),
389 ( ';thing a1 b1', handle_auto),
385 ( ';thing a1 b1', handle_auto),
390
386
391 # Autocalls only happen on things which look like funcs, even if
387 # Autocalls only happen on things which look like funcs, even if
392 # explicitly requested. Which, in this case means they look like a
388 # explicitly requested. Which, in this case means they look like a
393 # sequence of identifiers and . attribute references. Possibly the
389 # sequence of identifiers and . attribute references. Possibly the
394 # second of these two should trigger handle_auto. But not for now.
390 # second of these two should trigger handle_auto. But not for now.
395 ( '"abc".join range(4)', handle_normal),
391 ( '"abc".join range(4)', handle_normal),
396 ( '/"abc".join range(4)', handle_normal),
392 ( '/"abc".join range(4)', handle_normal),
397 ])
393 ])
398
394
399
395
400 # No tests for autocall = 2, since the extra magic there happens inside the
396 # No tests for autocall = 2, since the extra magic there happens inside the
401 # handle_auto function, which our test doesn't examine.
397 # handle_auto function, which our test doesn't examine.
402
398
403 # Note that we leave autocall in default, 1, 'smart' mode
399 # Note that we leave autocall in default, 1, 'smart' mode
404
400
405
401
406 # Autocall / Binary operators
402 # Autocall / Binary operators
407 # ==========================
403 # ==========================
408
404
409 # Even with autocall on, 'len in thing' won't transform.
405 # Even with autocall on, 'len in thing' won't transform.
410 # But ';len in thing' will
406 # But ';len in thing' will
411
407
412 # Note, the tests below don't check for multi-char ops. It could.
408 # Note, the tests below don't check for multi-char ops. It could.
413
409
414 # XXX % is a binary op and should be in the list, too, but fails
410 # XXX % is a binary op and should be in the list, too, but fails
415 bin_ops = list(r'<>,&^|*/+-') + 'is not in and or'.split()
411 bin_ops = list(r'<>,&^|*/+-') + 'is not in and or'.split()
416 bin_tests = []
412 bin_tests = []
417 for b in bin_ops:
413 for b in bin_ops:
418 bin_tests.append(('len %s binop_autocall' % b, handle_normal))
414 bin_tests.append(('len %s binop_autocall' % b, handle_normal))
419 bin_tests.append((';len %s binop_autocall' % b, handle_auto))
415 bin_tests.append((';len %s binop_autocall' % b, handle_auto))
420 bin_tests.append((',len %s binop_autocall' % b, handle_auto))
416 bin_tests.append((',len %s binop_autocall' % b, handle_auto))
421 bin_tests.append(('/len %s binop_autocall' % b, handle_auto))
417 bin_tests.append(('/len %s binop_autocall' % b, handle_auto))
422
418
423 # Who loves auto-generating tests?
419 # Who loves auto-generating tests?
424 run_handler_tests(bin_tests)
420 run_handler_tests(bin_tests)
425
421
426
422
427 # Possibly add tests for namespace shadowing (really ofind's business?).
423 # Possibly add tests for namespace shadowing (really ofind's business?).
428 #
424 #
429 # user > ipython internal > python builtin > alias > magic
425 # user > ipython internal > python builtin > alias > magic
430
426
431
427
432 # ============
428 # ============
433 # Test Summary
429 # Test Summary
434 # ============
430 # ============
435 num_f = len(failures)
431 num_f = len(failures)
436 if verbose:
432 if verbose:
437 print
433 print
438 print "%s tests run, %s failure%s" % (num_tests,
434 print "%s tests run, %s failure%s" % (num_tests,
439 num_f,
435 num_f,
440 num_f != 1 and "s" or "")
436 num_f != 1 and "s" or "")
441 for f in failures:
437 for f in failures:
442 print f
438 print f
443
439
General Comments 0
You need to be logged in to leave comments. Login now