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