##// END OF EJS Templates
remove another py2 only test
Paul Ivanov -
r22962:c05c1799
parent child
Show More
@@ -1,799 +1,739
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for the IPython tab-completion machinery."""
2 """Tests for the IPython tab-completion machinery."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import sys
8 import sys
9 import unittest
9 import unittest
10
10
11 from contextlib import contextmanager
11 from contextlib import contextmanager
12
12
13 import nose.tools as nt
13 import nose.tools as nt
14
14
15 from traitlets.config.loader import Config
15 from traitlets.config.loader import Config
16 from IPython import get_ipython
16 from IPython import get_ipython
17 from IPython.core import completer
17 from IPython.core import completer
18 from IPython.external.decorators import knownfailureif
18 from IPython.external.decorators import knownfailureif
19 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
19 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
20 from IPython.utils.generics import complete_object
20 from IPython.utils.generics import complete_object
21 from IPython.utils.py3compat import string_types, unicode_type
21 from IPython.utils.py3compat import string_types, unicode_type
22 from IPython.testing import decorators as dec
22 from IPython.testing import decorators as dec
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Test functions
25 # Test functions
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 @contextmanager
28 @contextmanager
29 def greedy_completion():
29 def greedy_completion():
30 ip = get_ipython()
30 ip = get_ipython()
31 greedy_original = ip.Completer.greedy
31 greedy_original = ip.Completer.greedy
32 try:
32 try:
33 ip.Completer.greedy = True
33 ip.Completer.greedy = True
34 yield
34 yield
35 finally:
35 finally:
36 ip.Completer.greedy = greedy_original
36 ip.Completer.greedy = greedy_original
37
37
38 def test_protect_filename():
38 def test_protect_filename():
39 if sys.platform == 'win32':
39 if sys.platform == 'win32':
40 pairs = [('abc','abc'),
40 pairs = [('abc','abc'),
41 (' abc','" abc"'),
41 (' abc','" abc"'),
42 ('a bc','"a bc"'),
42 ('a bc','"a bc"'),
43 ('a bc','"a bc"'),
43 ('a bc','"a bc"'),
44 (' bc','" bc"'),
44 (' bc','" bc"'),
45 ]
45 ]
46 else:
46 else:
47 pairs = [('abc','abc'),
47 pairs = [('abc','abc'),
48 (' abc',r'\ abc'),
48 (' abc',r'\ abc'),
49 ('a bc',r'a\ bc'),
49 ('a bc',r'a\ bc'),
50 ('a bc',r'a\ \ bc'),
50 ('a bc',r'a\ \ bc'),
51 (' bc',r'\ \ bc'),
51 (' bc',r'\ \ bc'),
52 # On posix, we also protect parens and other special characters.
52 # On posix, we also protect parens and other special characters.
53 ('a(bc',r'a\(bc'),
53 ('a(bc',r'a\(bc'),
54 ('a)bc',r'a\)bc'),
54 ('a)bc',r'a\)bc'),
55 ('a( )bc',r'a\(\ \)bc'),
55 ('a( )bc',r'a\(\ \)bc'),
56 ('a[1]bc', r'a\[1\]bc'),
56 ('a[1]bc', r'a\[1\]bc'),
57 ('a{1}bc', r'a\{1\}bc'),
57 ('a{1}bc', r'a\{1\}bc'),
58 ('a#bc', r'a\#bc'),
58 ('a#bc', r'a\#bc'),
59 ('a?bc', r'a\?bc'),
59 ('a?bc', r'a\?bc'),
60 ('a=bc', r'a\=bc'),
60 ('a=bc', r'a\=bc'),
61 ('a\\bc', r'a\\bc'),
61 ('a\\bc', r'a\\bc'),
62 ('a|bc', r'a\|bc'),
62 ('a|bc', r'a\|bc'),
63 ('a;bc', r'a\;bc'),
63 ('a;bc', r'a\;bc'),
64 ('a:bc', r'a\:bc'),
64 ('a:bc', r'a\:bc'),
65 ("a'bc", r"a\'bc"),
65 ("a'bc", r"a\'bc"),
66 ('a*bc', r'a\*bc'),
66 ('a*bc', r'a\*bc'),
67 ('a"bc', r'a\"bc'),
67 ('a"bc', r'a\"bc'),
68 ('a^bc', r'a\^bc'),
68 ('a^bc', r'a\^bc'),
69 ('a&bc', r'a\&bc'),
69 ('a&bc', r'a\&bc'),
70 ]
70 ]
71 # run the actual tests
71 # run the actual tests
72 for s1, s2 in pairs:
72 for s1, s2 in pairs:
73 s1p = completer.protect_filename(s1)
73 s1p = completer.protect_filename(s1)
74 nt.assert_equal(s1p, s2)
74 nt.assert_equal(s1p, s2)
75
75
76
76
77 def check_line_split(splitter, test_specs):
77 def check_line_split(splitter, test_specs):
78 for part1, part2, split in test_specs:
78 for part1, part2, split in test_specs:
79 cursor_pos = len(part1)
79 cursor_pos = len(part1)
80 line = part1+part2
80 line = part1+part2
81 out = splitter.split_line(line, cursor_pos)
81 out = splitter.split_line(line, cursor_pos)
82 nt.assert_equal(out, split)
82 nt.assert_equal(out, split)
83
83
84
84
85 def test_line_split():
85 def test_line_split():
86 """Basic line splitter test with default specs."""
86 """Basic line splitter test with default specs."""
87 sp = completer.CompletionSplitter()
87 sp = completer.CompletionSplitter()
88 # The format of the test specs is: part1, part2, expected answer. Parts 1
88 # The format of the test specs is: part1, part2, expected answer. Parts 1
89 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
89 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
90 # was at the end of part1. So an empty part2 represents someone hitting
90 # was at the end of part1. So an empty part2 represents someone hitting
91 # tab at the end of the line, the most common case.
91 # tab at the end of the line, the most common case.
92 t = [('run some/scrip', '', 'some/scrip'),
92 t = [('run some/scrip', '', 'some/scrip'),
93 ('run scripts/er', 'ror.py foo', 'scripts/er'),
93 ('run scripts/er', 'ror.py foo', 'scripts/er'),
94 ('echo $HOM', '', 'HOM'),
94 ('echo $HOM', '', 'HOM'),
95 ('print sys.pa', '', 'sys.pa'),
95 ('print sys.pa', '', 'sys.pa'),
96 ('print(sys.pa', '', 'sys.pa'),
96 ('print(sys.pa', '', 'sys.pa'),
97 ("execfile('scripts/er", '', 'scripts/er'),
97 ("execfile('scripts/er", '', 'scripts/er'),
98 ('a[x.', '', 'x.'),
98 ('a[x.', '', 'x.'),
99 ('a[x.', 'y', 'x.'),
99 ('a[x.', 'y', 'x.'),
100 ('cd "some_file/', '', 'some_file/'),
100 ('cd "some_file/', '', 'some_file/'),
101 ]
101 ]
102 check_line_split(sp, t)
102 check_line_split(sp, t)
103 # Ensure splitting works OK with unicode by re-running the tests with
103 # Ensure splitting works OK with unicode by re-running the tests with
104 # all inputs turned into unicode
104 # all inputs turned into unicode
105 check_line_split(sp, [ map(unicode_type, p) for p in t] )
105 check_line_split(sp, [ map(unicode_type, p) for p in t] )
106
106
107
107
108 def test_custom_completion_error():
108 def test_custom_completion_error():
109 """Test that errors from custom attribute completers are silenced."""
109 """Test that errors from custom attribute completers are silenced."""
110 ip = get_ipython()
110 ip = get_ipython()
111 class A(object): pass
111 class A(object): pass
112 ip.user_ns['a'] = A()
112 ip.user_ns['a'] = A()
113
113
114 @complete_object.when_type(A)
114 @complete_object.when_type(A)
115 def complete_A(a, existing_completions):
115 def complete_A(a, existing_completions):
116 raise TypeError("this should be silenced")
116 raise TypeError("this should be silenced")
117
117
118 ip.complete("a.")
118 ip.complete("a.")
119
119
120
120
121 def test_unicode_completions():
121 def test_unicode_completions():
122 ip = get_ipython()
122 ip = get_ipython()
123 # Some strings that trigger different types of completion. Check them both
123 # Some strings that trigger different types of completion. Check them both
124 # in str and unicode forms
124 # in str and unicode forms
125 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
125 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
126 for t in s + list(map(unicode_type, s)):
126 for t in s + list(map(unicode_type, s)):
127 # We don't need to check exact completion values (they may change
127 # We don't need to check exact completion values (they may change
128 # depending on the state of the namespace, but at least no exceptions
128 # depending on the state of the namespace, but at least no exceptions
129 # should be thrown and the return value should be a pair of text, list
129 # should be thrown and the return value should be a pair of text, list
130 # values.
130 # values.
131 text, matches = ip.complete(t)
131 text, matches = ip.complete(t)
132 nt.assert_true(isinstance(text, string_types))
132 nt.assert_true(isinstance(text, string_types))
133 nt.assert_true(isinstance(matches, list))
133 nt.assert_true(isinstance(matches, list))
134
134
135 def test_latex_completions():
135 def test_latex_completions():
136 from IPython.core.latex_symbols import latex_symbols
136 from IPython.core.latex_symbols import latex_symbols
137 import random
137 import random
138 ip = get_ipython()
138 ip = get_ipython()
139 # Test some random unicode symbols
139 # Test some random unicode symbols
140 keys = random.sample(latex_symbols.keys(), 10)
140 keys = random.sample(latex_symbols.keys(), 10)
141 for k in keys:
141 for k in keys:
142 text, matches = ip.complete(k)
142 text, matches = ip.complete(k)
143 nt.assert_equal(len(matches),1)
143 nt.assert_equal(len(matches),1)
144 nt.assert_equal(text, k)
144 nt.assert_equal(text, k)
145 nt.assert_equal(matches[0], latex_symbols[k])
145 nt.assert_equal(matches[0], latex_symbols[k])
146 # Test a more complex line
146 # Test a more complex line
147 text, matches = ip.complete(u'print(\\alpha')
147 text, matches = ip.complete(u'print(\\alpha')
148 nt.assert_equals(text, u'\\alpha')
148 nt.assert_equals(text, u'\\alpha')
149 nt.assert_equals(matches[0], latex_symbols['\\alpha'])
149 nt.assert_equals(matches[0], latex_symbols['\\alpha'])
150 # Test multiple matching latex symbols
150 # Test multiple matching latex symbols
151 text, matches = ip.complete(u'\\al')
151 text, matches = ip.complete(u'\\al')
152 nt.assert_in('\\alpha', matches)
152 nt.assert_in('\\alpha', matches)
153 nt.assert_in('\\aleph', matches)
153 nt.assert_in('\\aleph', matches)
154
154
155
155
156
156
157
157
158 def test_back_latex_completion():
158 def test_back_latex_completion():
159 ip = get_ipython()
159 ip = get_ipython()
160
160
161 # do not return more than 1 matches fro \beta, only the latex one.
161 # do not return more than 1 matches fro \beta, only the latex one.
162 name, matches = ip.complete('\\β')
162 name, matches = ip.complete('\\β')
163 nt.assert_equal(len(matches), 1)
163 nt.assert_equal(len(matches), 1)
164 nt.assert_equal(matches[0], '\\beta')
164 nt.assert_equal(matches[0], '\\beta')
165
165
166 def test_back_unicode_completion():
166 def test_back_unicode_completion():
167 ip = get_ipython()
167 ip = get_ipython()
168
168
169 name, matches = ip.complete('\\Ⅴ')
169 name, matches = ip.complete('\\Ⅴ')
170 nt.assert_equal(len(matches), 1)
170 nt.assert_equal(len(matches), 1)
171 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
171 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
172
172
173
173
174 def test_forward_unicode_completion():
174 def test_forward_unicode_completion():
175 ip = get_ipython()
175 ip = get_ipython()
176
176
177 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
177 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
178 nt.assert_equal(len(matches), 1)
178 nt.assert_equal(len(matches), 1)
179 nt.assert_equal(matches[0], 'Ⅴ')
179 nt.assert_equal(matches[0], 'Ⅴ')
180
180
181 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
181 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
182 def test_no_ascii_back_completion():
182 def test_no_ascii_back_completion():
183 ip = get_ipython()
183 ip = get_ipython()
184 with TemporaryWorkingDirectory(): # Avoid any filename completions
184 with TemporaryWorkingDirectory(): # Avoid any filename completions
185 # single ascii letter that don't have yet completions
185 # single ascii letter that don't have yet completions
186 for letter in 'jJ' :
186 for letter in 'jJ' :
187 name, matches = ip.complete('\\'+letter)
187 name, matches = ip.complete('\\'+letter)
188 nt.assert_equal(matches, [])
188 nt.assert_equal(matches, [])
189
189
190
190
191
191
192
192
193 class CompletionSplitterTestCase(unittest.TestCase):
193 class CompletionSplitterTestCase(unittest.TestCase):
194 def setUp(self):
194 def setUp(self):
195 self.sp = completer.CompletionSplitter()
195 self.sp = completer.CompletionSplitter()
196
196
197 def test_delim_setting(self):
197 def test_delim_setting(self):
198 self.sp.delims = ' '
198 self.sp.delims = ' '
199 nt.assert_equal(self.sp.delims, ' ')
199 nt.assert_equal(self.sp.delims, ' ')
200 nt.assert_equal(self.sp._delim_expr, '[\ ]')
200 nt.assert_equal(self.sp._delim_expr, '[\ ]')
201
201
202 def test_spaces(self):
202 def test_spaces(self):
203 """Test with only spaces as split chars."""
203 """Test with only spaces as split chars."""
204 self.sp.delims = ' '
204 self.sp.delims = ' '
205 t = [('foo', '', 'foo'),
205 t = [('foo', '', 'foo'),
206 ('run foo', '', 'foo'),
206 ('run foo', '', 'foo'),
207 ('run foo', 'bar', 'foo'),
207 ('run foo', 'bar', 'foo'),
208 ]
208 ]
209 check_line_split(self.sp, t)
209 check_line_split(self.sp, t)
210
210
211
211
212 def test_has_open_quotes1():
212 def test_has_open_quotes1():
213 for s in ["'", "'''", "'hi' '"]:
213 for s in ["'", "'''", "'hi' '"]:
214 nt.assert_equal(completer.has_open_quotes(s), "'")
214 nt.assert_equal(completer.has_open_quotes(s), "'")
215
215
216
216
217 def test_has_open_quotes2():
217 def test_has_open_quotes2():
218 for s in ['"', '"""', '"hi" "']:
218 for s in ['"', '"""', '"hi" "']:
219 nt.assert_equal(completer.has_open_quotes(s), '"')
219 nt.assert_equal(completer.has_open_quotes(s), '"')
220
220
221
221
222 def test_has_open_quotes3():
222 def test_has_open_quotes3():
223 for s in ["''", "''' '''", "'hi' 'ipython'"]:
223 for s in ["''", "''' '''", "'hi' 'ipython'"]:
224 nt.assert_false(completer.has_open_quotes(s))
224 nt.assert_false(completer.has_open_quotes(s))
225
225
226
226
227 def test_has_open_quotes4():
227 def test_has_open_quotes4():
228 for s in ['""', '""" """', '"hi" "ipython"']:
228 for s in ['""', '""" """', '"hi" "ipython"']:
229 nt.assert_false(completer.has_open_quotes(s))
229 nt.assert_false(completer.has_open_quotes(s))
230
230
231
231
232 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
232 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
233 def test_abspath_file_completions():
233 def test_abspath_file_completions():
234 ip = get_ipython()
234 ip = get_ipython()
235 with TemporaryDirectory() as tmpdir:
235 with TemporaryDirectory() as tmpdir:
236 prefix = os.path.join(tmpdir, 'foo')
236 prefix = os.path.join(tmpdir, 'foo')
237 suffixes = ['1', '2']
237 suffixes = ['1', '2']
238 names = [prefix+s for s in suffixes]
238 names = [prefix+s for s in suffixes]
239 for n in names:
239 for n in names:
240 open(n, 'w').close()
240 open(n, 'w').close()
241
241
242 # Check simple completion
242 # Check simple completion
243 c = ip.complete(prefix)[1]
243 c = ip.complete(prefix)[1]
244 nt.assert_equal(c, names)
244 nt.assert_equal(c, names)
245
245
246 # Now check with a function call
246 # Now check with a function call
247 cmd = 'a = f("%s' % prefix
247 cmd = 'a = f("%s' % prefix
248 c = ip.complete(prefix, cmd)[1]
248 c = ip.complete(prefix, cmd)[1]
249 comp = [prefix+s for s in suffixes]
249 comp = [prefix+s for s in suffixes]
250 nt.assert_equal(c, comp)
250 nt.assert_equal(c, comp)
251
251
252
252
253 def test_local_file_completions():
253 def test_local_file_completions():
254 ip = get_ipython()
254 ip = get_ipython()
255 with TemporaryWorkingDirectory():
255 with TemporaryWorkingDirectory():
256 prefix = './foo'
256 prefix = './foo'
257 suffixes = ['1', '2']
257 suffixes = ['1', '2']
258 names = [prefix+s for s in suffixes]
258 names = [prefix+s for s in suffixes]
259 for n in names:
259 for n in names:
260 open(n, 'w').close()
260 open(n, 'w').close()
261
261
262 # Check simple completion
262 # Check simple completion
263 c = ip.complete(prefix)[1]
263 c = ip.complete(prefix)[1]
264 nt.assert_equal(c, names)
264 nt.assert_equal(c, names)
265
265
266 # Now check with a function call
266 # Now check with a function call
267 cmd = 'a = f("%s' % prefix
267 cmd = 'a = f("%s' % prefix
268 c = ip.complete(prefix, cmd)[1]
268 c = ip.complete(prefix, cmd)[1]
269 comp = set(prefix+s for s in suffixes)
269 comp = set(prefix+s for s in suffixes)
270 nt.assert_true(comp.issubset(set(c)))
270 nt.assert_true(comp.issubset(set(c)))
271
271
272
272
273 def test_greedy_completions():
273 def test_greedy_completions():
274 ip = get_ipython()
274 ip = get_ipython()
275 ip.ex('a=list(range(5))')
275 ip.ex('a=list(range(5))')
276 _,c = ip.complete('.',line='a[0].')
276 _,c = ip.complete('.',line='a[0].')
277 nt.assert_false('.real' in c,
277 nt.assert_false('.real' in c,
278 "Shouldn't have completed on a[0]: %s"%c)
278 "Shouldn't have completed on a[0]: %s"%c)
279 with greedy_completion():
279 with greedy_completion():
280 def _(line, cursor_pos, expect, message):
280 def _(line, cursor_pos, expect, message):
281 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
281 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
282 nt.assert_in(expect, c, message%c)
282 nt.assert_in(expect, c, message%c)
283
283
284 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s"
284 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s"
285 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s"
285 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s"
286
286
287 if sys.version_info > (3,4):
287 if sys.version_info > (3,4):
288 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s"
288 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s"
289
289
290
290
291
291
292 def test_omit__names():
292 def test_omit__names():
293 # also happens to test IPCompleter as a configurable
293 # also happens to test IPCompleter as a configurable
294 ip = get_ipython()
294 ip = get_ipython()
295 ip._hidden_attr = 1
295 ip._hidden_attr = 1
296 ip._x = {}
296 ip._x = {}
297 c = ip.Completer
297 c = ip.Completer
298 ip.ex('ip=get_ipython()')
298 ip.ex('ip=get_ipython()')
299 cfg = Config()
299 cfg = Config()
300 cfg.IPCompleter.omit__names = 0
300 cfg.IPCompleter.omit__names = 0
301 c.update_config(cfg)
301 c.update_config(cfg)
302 s,matches = c.complete('ip.')
302 s,matches = c.complete('ip.')
303 nt.assert_in('ip.__str__', matches)
303 nt.assert_in('ip.__str__', matches)
304 nt.assert_in('ip._hidden_attr', matches)
304 nt.assert_in('ip._hidden_attr', matches)
305 cfg = Config()
305 cfg = Config()
306 cfg.IPCompleter.omit__names = 1
306 cfg.IPCompleter.omit__names = 1
307 c.update_config(cfg)
307 c.update_config(cfg)
308 s,matches = c.complete('ip.')
308 s,matches = c.complete('ip.')
309 nt.assert_not_in('ip.__str__', matches)
309 nt.assert_not_in('ip.__str__', matches)
310 nt.assert_in('ip._hidden_attr', matches)
310 nt.assert_in('ip._hidden_attr', matches)
311 cfg = Config()
311 cfg = Config()
312 cfg.IPCompleter.omit__names = 2
312 cfg.IPCompleter.omit__names = 2
313 c.update_config(cfg)
313 c.update_config(cfg)
314 s,matches = c.complete('ip.')
314 s,matches = c.complete('ip.')
315 nt.assert_not_in('ip.__str__', matches)
315 nt.assert_not_in('ip.__str__', matches)
316 nt.assert_not_in('ip._hidden_attr', matches)
316 nt.assert_not_in('ip._hidden_attr', matches)
317 s,matches = c.complete('ip._x.')
317 s,matches = c.complete('ip._x.')
318 nt.assert_in('ip._x.keys', matches)
318 nt.assert_in('ip._x.keys', matches)
319 del ip._hidden_attr
319 del ip._hidden_attr
320
320
321
321
322 def test_limit_to__all__False_ok():
322 def test_limit_to__all__False_ok():
323 ip = get_ipython()
323 ip = get_ipython()
324 c = ip.Completer
324 c = ip.Completer
325 ip.ex('class D: x=24')
325 ip.ex('class D: x=24')
326 ip.ex('d=D()')
326 ip.ex('d=D()')
327 cfg = Config()
327 cfg = Config()
328 cfg.IPCompleter.limit_to__all__ = False
328 cfg.IPCompleter.limit_to__all__ = False
329 c.update_config(cfg)
329 c.update_config(cfg)
330 s, matches = c.complete('d.')
330 s, matches = c.complete('d.')
331 nt.assert_in('d.x', matches)
331 nt.assert_in('d.x', matches)
332
332
333
333
334 def test_get__all__entries_ok():
334 def test_get__all__entries_ok():
335 class A(object):
335 class A(object):
336 __all__ = ['x', 1]
336 __all__ = ['x', 1]
337 words = completer.get__all__entries(A())
337 words = completer.get__all__entries(A())
338 nt.assert_equal(words, ['x'])
338 nt.assert_equal(words, ['x'])
339
339
340
340
341 def test_get__all__entries_no__all__ok():
341 def test_get__all__entries_no__all__ok():
342 class A(object):
342 class A(object):
343 pass
343 pass
344 words = completer.get__all__entries(A())
344 words = completer.get__all__entries(A())
345 nt.assert_equal(words, [])
345 nt.assert_equal(words, [])
346
346
347
347
348 def test_func_kw_completions():
348 def test_func_kw_completions():
349 ip = get_ipython()
349 ip = get_ipython()
350 c = ip.Completer
350 c = ip.Completer
351 ip.ex('def myfunc(a=1,b=2): return a+b')
351 ip.ex('def myfunc(a=1,b=2): return a+b')
352 s, matches = c.complete(None, 'myfunc(1,b')
352 s, matches = c.complete(None, 'myfunc(1,b')
353 nt.assert_in('b=', matches)
353 nt.assert_in('b=', matches)
354 # Simulate completing with cursor right after b (pos==10):
354 # Simulate completing with cursor right after b (pos==10):
355 s, matches = c.complete(None, 'myfunc(1,b)', 10)
355 s, matches = c.complete(None, 'myfunc(1,b)', 10)
356 nt.assert_in('b=', matches)
356 nt.assert_in('b=', matches)
357 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
357 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
358 nt.assert_in('b=', matches)
358 nt.assert_in('b=', matches)
359 #builtin function
359 #builtin function
360 s, matches = c.complete(None, 'min(k, k')
360 s, matches = c.complete(None, 'min(k, k')
361 nt.assert_in('key=', matches)
361 nt.assert_in('key=', matches)
362
362
363
363
364 def test_default_arguments_from_docstring():
364 def test_default_arguments_from_docstring():
365 ip = get_ipython()
365 ip = get_ipython()
366 c = ip.Completer
366 c = ip.Completer
367 kwd = c._default_arguments_from_docstring(
367 kwd = c._default_arguments_from_docstring(
368 'min(iterable[, key=func]) -> value')
368 'min(iterable[, key=func]) -> value')
369 nt.assert_equal(kwd, ['key'])
369 nt.assert_equal(kwd, ['key'])
370 #with cython type etc
370 #with cython type etc
371 kwd = c._default_arguments_from_docstring(
371 kwd = c._default_arguments_from_docstring(
372 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
372 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
373 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
373 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
374 #white spaces
374 #white spaces
375 kwd = c._default_arguments_from_docstring(
375 kwd = c._default_arguments_from_docstring(
376 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
376 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
377 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
377 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
378
378
379 def test_line_magics():
379 def test_line_magics():
380 ip = get_ipython()
380 ip = get_ipython()
381 c = ip.Completer
381 c = ip.Completer
382 s, matches = c.complete(None, 'lsmag')
382 s, matches = c.complete(None, 'lsmag')
383 nt.assert_in('%lsmagic', matches)
383 nt.assert_in('%lsmagic', matches)
384 s, matches = c.complete(None, '%lsmag')
384 s, matches = c.complete(None, '%lsmag')
385 nt.assert_in('%lsmagic', matches)
385 nt.assert_in('%lsmagic', matches)
386
386
387
387
388 def test_cell_magics():
388 def test_cell_magics():
389 from IPython.core.magic import register_cell_magic
389 from IPython.core.magic import register_cell_magic
390
390
391 @register_cell_magic
391 @register_cell_magic
392 def _foo_cellm(line, cell):
392 def _foo_cellm(line, cell):
393 pass
393 pass
394
394
395 ip = get_ipython()
395 ip = get_ipython()
396 c = ip.Completer
396 c = ip.Completer
397
397
398 s, matches = c.complete(None, '_foo_ce')
398 s, matches = c.complete(None, '_foo_ce')
399 nt.assert_in('%%_foo_cellm', matches)
399 nt.assert_in('%%_foo_cellm', matches)
400 s, matches = c.complete(None, '%%_foo_ce')
400 s, matches = c.complete(None, '%%_foo_ce')
401 nt.assert_in('%%_foo_cellm', matches)
401 nt.assert_in('%%_foo_cellm', matches)
402
402
403
403
404 def test_line_cell_magics():
404 def test_line_cell_magics():
405 from IPython.core.magic import register_line_cell_magic
405 from IPython.core.magic import register_line_cell_magic
406
406
407 @register_line_cell_magic
407 @register_line_cell_magic
408 def _bar_cellm(line, cell):
408 def _bar_cellm(line, cell):
409 pass
409 pass
410
410
411 ip = get_ipython()
411 ip = get_ipython()
412 c = ip.Completer
412 c = ip.Completer
413
413
414 # The policy here is trickier, see comments in completion code. The
414 # The policy here is trickier, see comments in completion code. The
415 # returned values depend on whether the user passes %% or not explicitly,
415 # returned values depend on whether the user passes %% or not explicitly,
416 # and this will show a difference if the same name is both a line and cell
416 # and this will show a difference if the same name is both a line and cell
417 # magic.
417 # magic.
418 s, matches = c.complete(None, '_bar_ce')
418 s, matches = c.complete(None, '_bar_ce')
419 nt.assert_in('%_bar_cellm', matches)
419 nt.assert_in('%_bar_cellm', matches)
420 nt.assert_in('%%_bar_cellm', matches)
420 nt.assert_in('%%_bar_cellm', matches)
421 s, matches = c.complete(None, '%_bar_ce')
421 s, matches = c.complete(None, '%_bar_ce')
422 nt.assert_in('%_bar_cellm', matches)
422 nt.assert_in('%_bar_cellm', matches)
423 nt.assert_in('%%_bar_cellm', matches)
423 nt.assert_in('%%_bar_cellm', matches)
424 s, matches = c.complete(None, '%%_bar_ce')
424 s, matches = c.complete(None, '%%_bar_ce')
425 nt.assert_not_in('%_bar_cellm', matches)
425 nt.assert_not_in('%_bar_cellm', matches)
426 nt.assert_in('%%_bar_cellm', matches)
426 nt.assert_in('%%_bar_cellm', matches)
427
427
428
428
429 def test_magic_completion_order():
429 def test_magic_completion_order():
430
430
431 ip = get_ipython()
431 ip = get_ipython()
432 c = ip.Completer
432 c = ip.Completer
433
433
434 # Test ordering of magics and non-magics with the same name
434 # Test ordering of magics and non-magics with the same name
435 # We want the non-magic first
435 # We want the non-magic first
436
436
437 # Before importing matplotlib, there should only be one option:
437 # Before importing matplotlib, there should only be one option:
438
438
439 text, matches = c.complete('mat')
439 text, matches = c.complete('mat')
440 nt.assert_equal(matches, ["%matplotlib"])
440 nt.assert_equal(matches, ["%matplotlib"])
441
441
442
442
443 ip.run_cell("matplotlib = 1") # introduce name into namespace
443 ip.run_cell("matplotlib = 1") # introduce name into namespace
444
444
445 # After the import, there should be two options, ordered like this:
445 # After the import, there should be two options, ordered like this:
446 text, matches = c.complete('mat')
446 text, matches = c.complete('mat')
447 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
447 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
448
448
449
449
450 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
450 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
451
451
452 # Order of user variable and line and cell magics with same name:
452 # Order of user variable and line and cell magics with same name:
453 text, matches = c.complete('timeit')
453 text, matches = c.complete('timeit')
454 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
454 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
455
455
456
456
457 def test_dict_key_completion_string():
457 def test_dict_key_completion_string():
458 """Test dictionary key completion for string keys"""
458 """Test dictionary key completion for string keys"""
459 ip = get_ipython()
459 ip = get_ipython()
460 complete = ip.Completer.complete
460 complete = ip.Completer.complete
461
461
462 ip.user_ns['d'] = {'abc': None}
462 ip.user_ns['d'] = {'abc': None}
463
463
464 # check completion at different stages
464 # check completion at different stages
465 _, matches = complete(line_buffer="d[")
465 _, matches = complete(line_buffer="d[")
466 nt.assert_in("'abc'", matches)
466 nt.assert_in("'abc'", matches)
467 nt.assert_not_in("'abc']", matches)
467 nt.assert_not_in("'abc']", matches)
468
468
469 _, matches = complete(line_buffer="d['")
469 _, matches = complete(line_buffer="d['")
470 nt.assert_in("abc", matches)
470 nt.assert_in("abc", matches)
471 nt.assert_not_in("abc']", matches)
471 nt.assert_not_in("abc']", matches)
472
472
473 _, matches = complete(line_buffer="d['a")
473 _, matches = complete(line_buffer="d['a")
474 nt.assert_in("abc", matches)
474 nt.assert_in("abc", matches)
475 nt.assert_not_in("abc']", matches)
475 nt.assert_not_in("abc']", matches)
476
476
477 # check use of different quoting
477 # check use of different quoting
478 _, matches = complete(line_buffer="d[\"")
478 _, matches = complete(line_buffer="d[\"")
479 nt.assert_in("abc", matches)
479 nt.assert_in("abc", matches)
480 nt.assert_not_in('abc\"]', matches)
480 nt.assert_not_in('abc\"]', matches)
481
481
482 _, matches = complete(line_buffer="d[\"a")
482 _, matches = complete(line_buffer="d[\"a")
483 nt.assert_in("abc", matches)
483 nt.assert_in("abc", matches)
484 nt.assert_not_in('abc\"]', matches)
484 nt.assert_not_in('abc\"]', matches)
485
485
486 # check sensitivity to following context
486 # check sensitivity to following context
487 _, matches = complete(line_buffer="d[]", cursor_pos=2)
487 _, matches = complete(line_buffer="d[]", cursor_pos=2)
488 nt.assert_in("'abc'", matches)
488 nt.assert_in("'abc'", matches)
489
489
490 _, matches = complete(line_buffer="d['']", cursor_pos=3)
490 _, matches = complete(line_buffer="d['']", cursor_pos=3)
491 nt.assert_in("abc", matches)
491 nt.assert_in("abc", matches)
492 nt.assert_not_in("abc'", matches)
492 nt.assert_not_in("abc'", matches)
493 nt.assert_not_in("abc']", matches)
493 nt.assert_not_in("abc']", matches)
494
494
495 # check multiple solutions are correctly returned and that noise is not
495 # check multiple solutions are correctly returned and that noise is not
496 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
496 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
497 5: None}
497 5: None}
498
498
499 _, matches = complete(line_buffer="d['a")
499 _, matches = complete(line_buffer="d['a")
500 nt.assert_in("abc", matches)
500 nt.assert_in("abc", matches)
501 nt.assert_in("abd", matches)
501 nt.assert_in("abd", matches)
502 nt.assert_not_in("bad", matches)
502 nt.assert_not_in("bad", matches)
503 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
503 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
504
504
505 # check escaping and whitespace
505 # check escaping and whitespace
506 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
506 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
507 _, matches = complete(line_buffer="d['a")
507 _, matches = complete(line_buffer="d['a")
508 nt.assert_in("a\\nb", matches)
508 nt.assert_in("a\\nb", matches)
509 nt.assert_in("a\\'b", matches)
509 nt.assert_in("a\\'b", matches)
510 nt.assert_in("a\"b", matches)
510 nt.assert_in("a\"b", matches)
511 nt.assert_in("a word", matches)
511 nt.assert_in("a word", matches)
512 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
512 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
513
513
514 # - can complete on non-initial word of the string
514 # - can complete on non-initial word of the string
515 _, matches = complete(line_buffer="d['a w")
515 _, matches = complete(line_buffer="d['a w")
516 nt.assert_in("word", matches)
516 nt.assert_in("word", matches)
517
517
518 # - understands quote escaping
518 # - understands quote escaping
519 _, matches = complete(line_buffer="d['a\\'")
519 _, matches = complete(line_buffer="d['a\\'")
520 nt.assert_in("b", matches)
520 nt.assert_in("b", matches)
521
521
522 # - default quoting should work like repr
522 # - default quoting should work like repr
523 _, matches = complete(line_buffer="d[")
523 _, matches = complete(line_buffer="d[")
524 nt.assert_in("\"a'b\"", matches)
524 nt.assert_in("\"a'b\"", matches)
525
525
526 # - when opening quote with ", possible to match with unescaped apostrophe
526 # - when opening quote with ", possible to match with unescaped apostrophe
527 _, matches = complete(line_buffer="d[\"a'")
527 _, matches = complete(line_buffer="d[\"a'")
528 nt.assert_in("b", matches)
528 nt.assert_in("b", matches)
529
529
530 # need to not split at delims that readline won't split at
530 # need to not split at delims that readline won't split at
531 if '-' not in ip.Completer.splitter.delims:
531 if '-' not in ip.Completer.splitter.delims:
532 ip.user_ns['d'] = {'before-after': None}
532 ip.user_ns['d'] = {'before-after': None}
533 _, matches = complete(line_buffer="d['before-af")
533 _, matches = complete(line_buffer="d['before-af")
534 nt.assert_in('before-after', matches)
534 nt.assert_in('before-after', matches)
535
535
536 def test_dict_key_completion_contexts():
536 def test_dict_key_completion_contexts():
537 """Test expression contexts in which dict key completion occurs"""
537 """Test expression contexts in which dict key completion occurs"""
538 ip = get_ipython()
538 ip = get_ipython()
539 complete = ip.Completer.complete
539 complete = ip.Completer.complete
540 d = {'abc': None}
540 d = {'abc': None}
541 ip.user_ns['d'] = d
541 ip.user_ns['d'] = d
542
542
543 class C:
543 class C:
544 data = d
544 data = d
545 ip.user_ns['C'] = C
545 ip.user_ns['C'] = C
546 ip.user_ns['get'] = lambda: d
546 ip.user_ns['get'] = lambda: d
547
547
548 def assert_no_completion(**kwargs):
548 def assert_no_completion(**kwargs):
549 _, matches = complete(**kwargs)
549 _, matches = complete(**kwargs)
550 nt.assert_not_in('abc', matches)
550 nt.assert_not_in('abc', matches)
551 nt.assert_not_in('abc\'', matches)
551 nt.assert_not_in('abc\'', matches)
552 nt.assert_not_in('abc\']', matches)
552 nt.assert_not_in('abc\']', matches)
553 nt.assert_not_in('\'abc\'', matches)
553 nt.assert_not_in('\'abc\'', matches)
554 nt.assert_not_in('\'abc\']', matches)
554 nt.assert_not_in('\'abc\']', matches)
555
555
556 def assert_completion(**kwargs):
556 def assert_completion(**kwargs):
557 _, matches = complete(**kwargs)
557 _, matches = complete(**kwargs)
558 nt.assert_in("'abc'", matches)
558 nt.assert_in("'abc'", matches)
559 nt.assert_not_in("'abc']", matches)
559 nt.assert_not_in("'abc']", matches)
560
560
561 # no completion after string closed, even if reopened
561 # no completion after string closed, even if reopened
562 assert_no_completion(line_buffer="d['a'")
562 assert_no_completion(line_buffer="d['a'")
563 assert_no_completion(line_buffer="d[\"a\"")
563 assert_no_completion(line_buffer="d[\"a\"")
564 assert_no_completion(line_buffer="d['a' + ")
564 assert_no_completion(line_buffer="d['a' + ")
565 assert_no_completion(line_buffer="d['a' + '")
565 assert_no_completion(line_buffer="d['a' + '")
566
566
567 # completion in non-trivial expressions
567 # completion in non-trivial expressions
568 assert_completion(line_buffer="+ d[")
568 assert_completion(line_buffer="+ d[")
569 assert_completion(line_buffer="(d[")
569 assert_completion(line_buffer="(d[")
570 assert_completion(line_buffer="C.data[")
570 assert_completion(line_buffer="C.data[")
571
571
572 # greedy flag
572 # greedy flag
573 def assert_completion(**kwargs):
573 def assert_completion(**kwargs):
574 _, matches = complete(**kwargs)
574 _, matches = complete(**kwargs)
575 nt.assert_in("get()['abc']", matches)
575 nt.assert_in("get()['abc']", matches)
576
576
577 assert_no_completion(line_buffer="get()[")
577 assert_no_completion(line_buffer="get()[")
578 with greedy_completion():
578 with greedy_completion():
579 assert_completion(line_buffer="get()[")
579 assert_completion(line_buffer="get()[")
580 assert_completion(line_buffer="get()['")
580 assert_completion(line_buffer="get()['")