##// END OF EJS Templates
Add test for gh-1117
Thomas Kluyver -
Show More
@@ -1,168 +1,170 b''
1 """Tests for input handlers.
1 """Tests for input handlers.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Module imports
4 # Module imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6
6
7 # third party
7 # third party
8 import nose.tools as nt
8 import nose.tools as nt
9
9
10 # our own packages
10 # our own packages
11 from IPython.core import autocall
11 from IPython.core import autocall
12 from IPython.testing import decorators as dec
12 from IPython.testing import decorators as dec
13 from IPython.testing import tools as tt
13 from IPython.testing import tools as tt
14 from IPython.testing.globalipapp import get_ipython
14 from IPython.testing.globalipapp import get_ipython
15 from IPython.utils import py3compat
15 from IPython.utils import py3compat
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Globals
18 # Globals
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 # Get the public instance of IPython
21 # Get the public instance of IPython
22 ip = get_ipython()
22 ip = get_ipython()
23
23
24 failures = []
24 failures = []
25 num_tests = 0
25 num_tests = 0
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Test functions
28 # Test functions
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 class CallableIndexable(object):
31 class CallableIndexable(object):
32 def __getitem__(self, idx): return True
32 def __getitem__(self, idx): return True
33 def __call__(self, *args, **kws): return True
33 def __call__(self, *args, **kws): return True
34
34
35
35
36 class Autocallable(autocall.IPyAutocall):
36 class Autocallable(autocall.IPyAutocall):
37 def __call__(self):
37 def __call__(self):
38 return "called"
38 return "called"
39
39
40
40
41 def run(tests):
41 def run(tests):
42 """Loop through a list of (pre, post) inputs, where pre is the string
42 """Loop through a list of (pre, post) inputs, where pre is the string
43 handed to ipython, and post is how that string looks after it's been
43 handed to ipython, and post is how that string looks after it's been
44 transformed (i.e. ipython's notion of _i)"""
44 transformed (i.e. ipython's notion of _i)"""
45 tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
45 tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
46
46
47
47
48 def test_handlers():
48 def test_handlers():
49 # alias expansion
49 # alias expansion
50
50
51 # We're using 'true' as our syscall of choice because it doesn't
51 # We're using 'true' as our syscall of choice because it doesn't
52 # write anything to stdout.
52 # write anything to stdout.
53
53
54 # Turn off actual execution of aliases, because it's noisy
54 # Turn off actual execution of aliases, because it's noisy
55 old_system_cmd = ip.system
55 old_system_cmd = ip.system
56 ip.system = lambda cmd: None
56 ip.system = lambda cmd: None
57
57
58
58
59 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
59 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
60 # These are useful for checking a particular recursive alias issue
60 # These are useful for checking a particular recursive alias issue
61 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
61 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
62 ip.alias_manager.alias_table['d'] = (0, 'true')
62 ip.alias_manager.alias_table['d'] = (0, 'true')
63 run([(i,py3compat.u_format(o)) for i,o in \
63 run([(i,py3compat.u_format(o)) for i,o in \
64 [("an_alias", "get_ipython().system({u}'true ')"), # alias
64 [("an_alias", "get_ipython().system({u}'true ')"), # alias
65 # Below: recursive aliases should expand whitespace-surrounded
65 # Below: recursive aliases should expand whitespace-surrounded
66 # chars, *not* initial chars which happen to be aliases:
66 # chars, *not* initial chars which happen to be aliases:
67 ("top", "get_ipython().system({u}'d:/cygwin/top ')"),
67 ("top", "get_ipython().system({u}'d:/cygwin/top ')"),
68 ]])
68 ]])
69 ip.system = old_system_cmd
69 ip.system = old_system_cmd
70
70
71 call_idx = CallableIndexable()
71 call_idx = CallableIndexable()
72 ip.user_ns['call_idx'] = call_idx
72 ip.user_ns['call_idx'] = call_idx
73
73
74 # For many of the below, we're also checking that leading whitespace
74 # For many of the below, we're also checking that leading whitespace
75 # turns off the esc char, which it should unless there is a continuation
75 # turns off the esc char, which it should unless there is a continuation
76 # line.
76 # line.
77 run([(i,py3compat.u_format(o)) for i,o in \
77 run([(i,py3compat.u_format(o)) for i,o in \
78 [('"no change"', '"no change"'), # normal
78 [('"no change"', '"no change"'), # normal
79 (u"!true", "get_ipython().system({u}'true')"), # shell_escapes
79 (u"!true", "get_ipython().system({u}'true')"), # shell_escapes
80 (u"!! true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
80 (u"!! true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
81 (u"!!true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
81 (u"!!true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
82 (u"%lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
82 (u"%lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
83 (u"lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
83 (u"lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
84 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
84 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
85
85
86 # post-esc-char whitespace goes inside
86 # post-esc-char whitespace goes inside
87 (u"! true", "get_ipython().system({u}' true')"),
87 (u"! true", "get_ipython().system({u}' true')"),
88
88
89 # handle_help
89 # handle_help
90
90
91 # These are weak tests -- just looking at what the help handlers
91 # These are weak tests -- just looking at what the help handlers
92 # logs, which is not how it really does its work. But it still
92 # logs, which is not how it really does its work. But it still
93 # lets us check the key paths through the handler.
93 # lets us check the key paths through the handler.
94
94
95 ("x=1 # what?", "x=1 # what?"), # no help if valid python
95 ("x=1 # what?", "x=1 # what?"), # no help if valid python
96 ]])
96 ]])
97
97
98 # multi_line_specials
98 # multi_line_specials
99 ip.prefilter_manager.multi_line_specials = False
99 ip.prefilter_manager.multi_line_specials = False
100 # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
100 # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
101 run([
101 run([
102 (u'if 1:\n !true', u'if 1:\n !true'),
102 (u'if 1:\n !true', u'if 1:\n !true'),
103 (u'if 1:\n lsmagic', u'if 1:\n lsmagic'),
103 (u'if 1:\n lsmagic', u'if 1:\n lsmagic'),
104 (u'if 1:\n an_alias', u'if 1:\n an_alias'),
104 (u'if 1:\n an_alias', u'if 1:\n an_alias'),
105 ])
105 ])
106
106
107 ip.prefilter_manager.multi_line_specials = True
107 ip.prefilter_manager.multi_line_specials = True
108 # initial indents must be preserved.
108 # initial indents must be preserved.
109 run([(i,py3compat.u_format(o)) for i,o in \
109 run([(i,py3compat.u_format(o)) for i,o in \
110 [(u'if 1:\n !true', "if 1:\n get_ipython().system({u}'true')"),
110 [(u'if 1:\n !true', "if 1:\n get_ipython().system({u}'true')"),
111 (u'if 2:\n lsmagic', "if 2:\n get_ipython().magic({u}'lsmagic ')"),
111 (u'if 2:\n lsmagic', "if 2:\n get_ipython().magic({u}'lsmagic ')"),
112 (u'if 1:\n an_alias', "if 1:\n get_ipython().system({u}'true ')"),
112 (u'if 1:\n an_alias', "if 1:\n get_ipython().system({u}'true ')"),
113 # Weird one
113 # Weird one
114 (u'if 1:\n !!true', "if 1:\n get_ipython().magic({u}'sx true')"),
114 (u'if 1:\n !!true', "if 1:\n get_ipython().magic({u}'sx true')"),
115
115
116 # Even with m_l_s on, autocall is off even with special chars
116 # Even with m_l_s on, autocall is off even with special chars
117 ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
117 ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
118 ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
118 ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
119 ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
119 ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
120 ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
120 ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
121 # What about !!
121 # What about !!
122 ]])
122 ]])
123
123
124 # Objects which are instances of IPyAutocall are *always* autocalled
124 # Objects which are instances of IPyAutocall are *always* autocalled
125 autocallable = Autocallable()
125 autocallable = Autocallable()
126 ip.user_ns['autocallable'] = autocallable
126 ip.user_ns['autocallable'] = autocallable
127
127
128 # auto
128 # auto
129 ip.magic('autocall 0')
129 ip.magic('autocall 0')
130 # Only explicit escapes or instances of IPyAutocallable should get
130 # Only explicit escapes or instances of IPyAutocallable should get
131 # expanded
131 # expanded
132 run([
132 run([
133 ('len "abc"', 'len "abc"'),
133 ('len "abc"', 'len "abc"'),
134 ('autocallable', 'autocallable()'),
134 ('autocallable', 'autocallable()'),
135 # Don't add extra brackets (gh-1117)
136 ('autocallable()', 'autocallable ()'),
135 (",list 1 2 3", 'list("1", "2", "3")'),
137 (",list 1 2 3", 'list("1", "2", "3")'),
136 (";list 1 2 3", 'list("1 2 3")'),
138 (";list 1 2 3", 'list("1 2 3")'),
137 ("/len range(1,4)", 'len(range(1,4))'),
139 ("/len range(1,4)", 'len(range(1,4))'),
138 ])
140 ])
139 ip.magic('autocall 1')
141 ip.magic('autocall 1')
140 run([
142 run([
141 (",list 1 2 3", 'list("1", "2", "3")'),
143 (",list 1 2 3", 'list("1", "2", "3")'),
142 (";list 1 2 3", 'list("1 2 3")'),
144 (";list 1 2 3", 'list("1 2 3")'),
143 ("/len range(1,4)", 'len(range(1,4))'),
145 ("/len range(1,4)", 'len(range(1,4))'),
144 ('len "abc"', 'len("abc")'),
146 ('len "abc"', 'len("abc")'),
145 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
147 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
146 # Autocall is turned off if first arg is [] and the object
148 # Autocall is turned off if first arg is [] and the object
147 # is both callable and indexable. Like so:
149 # is both callable and indexable. Like so:
148 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
150 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
149 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
151 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
150 ('call_idx 1', 'call_idx(1)'),
152 ('call_idx 1', 'call_idx(1)'),
151 ('len', 'len '), # only at 2 does it auto-call on single args
153 ('len', 'len '), # only at 2 does it auto-call on single args
152 ])
154 ])
153 ip.magic('autocall 2')
155 ip.magic('autocall 2')
154 run([
156 run([
155 (",list 1 2 3", 'list("1", "2", "3")'),
157 (",list 1 2 3", 'list("1", "2", "3")'),
156 (";list 1 2 3", 'list("1 2 3")'),
158 (";list 1 2 3", 'list("1 2 3")'),
157 ("/len range(1,4)", 'len(range(1,4))'),
159 ("/len range(1,4)", 'len(range(1,4))'),
158 ('len "abc"', 'len("abc")'),
160 ('len "abc"', 'len("abc")'),
159 ('len "abc";', 'len("abc");'),
161 ('len "abc";', 'len("abc");'),
160 ('len [1,2]', 'len([1,2])'),
162 ('len [1,2]', 'len([1,2])'),
161 ('call_idx [1]', 'call_idx [1]'),
163 ('call_idx [1]', 'call_idx [1]'),
162 ('call_idx 1', 'call_idx(1)'),
164 ('call_idx 1', 'call_idx(1)'),
163 # This is what's different:
165 # This is what's different:
164 ('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
165 ])
167 ])
166 ip.magic('autocall 1')
168 ip.magic('autocall 1')
167
169
168 nt.assert_equals(failures, [])
170 nt.assert_equals(failures, [])
General Comments 0
You need to be logged in to leave comments. Login now