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