##// END OF EJS Templates
Merge pull request #8593 from minrk/new-config...
Thomas Kluyver -
r21511:506ed73a merge
parent child Browse files
Show More
@@ -1,760 +1,762 b''
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.core import completer
16 from IPython.core import completer
17 from IPython.external.decorators import knownfailureif
17 from IPython.external.decorators import knownfailureif
18 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
18 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
19 from IPython.utils.generics import complete_object
19 from IPython.utils.generics import complete_object
20 from IPython.utils import py3compat
20 from IPython.utils import py3compat
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 pairs = [ ('abc','abc'),
39 pairs = [ ('abc','abc'),
40 (' abc',r'\ abc'),
40 (' abc',r'\ abc'),
41 ('a bc',r'a\ bc'),
41 ('a bc',r'a\ bc'),
42 ('a bc',r'a\ \ bc'),
42 ('a bc',r'a\ \ bc'),
43 (' bc',r'\ \ bc'),
43 (' bc',r'\ \ bc'),
44 ]
44 ]
45 # On posix, we also protect parens and other special characters
45 # On posix, we also protect parens and other special characters
46 if sys.platform != 'win32':
46 if sys.platform != 'win32':
47 pairs.extend( [('a(bc',r'a\(bc'),
47 pairs.extend( [('a(bc',r'a\(bc'),
48 ('a)bc',r'a\)bc'),
48 ('a)bc',r'a\)bc'),
49 ('a( )bc',r'a\(\ \)bc'),
49 ('a( )bc',r'a\(\ \)bc'),
50 ('a[1]bc', r'a\[1\]bc'),
50 ('a[1]bc', r'a\[1\]bc'),
51 ('a{1}bc', r'a\{1\}bc'),
51 ('a{1}bc', r'a\{1\}bc'),
52 ('a#bc', r'a\#bc'),
52 ('a#bc', r'a\#bc'),
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|bc', r'a\|bc'),
56 ('a|bc', r'a\|bc'),
57 ('a;bc', r'a\;bc'),
57 ('a;bc', r'a\;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 ] )
64 ] )
65 # run the actual tests
65 # run the actual tests
66 for s1, s2 in pairs:
66 for s1, s2 in pairs:
67 s1p = completer.protect_filename(s1)
67 s1p = completer.protect_filename(s1)
68 nt.assert_equal(s1p, s2)
68 nt.assert_equal(s1p, s2)
69
69
70
70
71 def check_line_split(splitter, test_specs):
71 def check_line_split(splitter, test_specs):
72 for part1, part2, split in test_specs:
72 for part1, part2, split in test_specs:
73 cursor_pos = len(part1)
73 cursor_pos = len(part1)
74 line = part1+part2
74 line = part1+part2
75 out = splitter.split_line(line, cursor_pos)
75 out = splitter.split_line(line, cursor_pos)
76 nt.assert_equal(out, split)
76 nt.assert_equal(out, split)
77
77
78
78
79 def test_line_split():
79 def test_line_split():
80 """Basic line splitter test with default specs."""
80 """Basic line splitter test with default specs."""
81 sp = completer.CompletionSplitter()
81 sp = completer.CompletionSplitter()
82 # The format of the test specs is: part1, part2, expected answer. Parts 1
82 # The format of the test specs is: part1, part2, expected answer. Parts 1
83 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
83 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
84 # was at the end of part1. So an empty part2 represents someone hitting
84 # was at the end of part1. So an empty part2 represents someone hitting
85 # tab at the end of the line, the most common case.
85 # tab at the end of the line, the most common case.
86 t = [('run some/scrip', '', 'some/scrip'),
86 t = [('run some/scrip', '', 'some/scrip'),
87 ('run scripts/er', 'ror.py foo', 'scripts/er'),
87 ('run scripts/er', 'ror.py foo', 'scripts/er'),
88 ('echo $HOM', '', 'HOM'),
88 ('echo $HOM', '', 'HOM'),
89 ('print sys.pa', '', 'sys.pa'),
89 ('print sys.pa', '', 'sys.pa'),
90 ('print(sys.pa', '', 'sys.pa'),
90 ('print(sys.pa', '', 'sys.pa'),
91 ("execfile('scripts/er", '', 'scripts/er'),
91 ("execfile('scripts/er", '', 'scripts/er'),
92 ('a[x.', '', 'x.'),
92 ('a[x.', '', 'x.'),
93 ('a[x.', 'y', 'x.'),
93 ('a[x.', 'y', 'x.'),
94 ('cd "some_file/', '', 'some_file/'),
94 ('cd "some_file/', '', 'some_file/'),
95 ]
95 ]
96 check_line_split(sp, t)
96 check_line_split(sp, t)
97 # Ensure splitting works OK with unicode by re-running the tests with
97 # Ensure splitting works OK with unicode by re-running the tests with
98 # all inputs turned into unicode
98 # all inputs turned into unicode
99 check_line_split(sp, [ map(unicode_type, p) for p in t] )
99 check_line_split(sp, [ map(unicode_type, p) for p in t] )
100
100
101
101
102 def test_custom_completion_error():
102 def test_custom_completion_error():
103 """Test that errors from custom attribute completers are silenced."""
103 """Test that errors from custom attribute completers are silenced."""
104 ip = get_ipython()
104 ip = get_ipython()
105 class A(object): pass
105 class A(object): pass
106 ip.user_ns['a'] = A()
106 ip.user_ns['a'] = A()
107
107
108 @complete_object.when_type(A)
108 @complete_object.when_type(A)
109 def complete_A(a, existing_completions):
109 def complete_A(a, existing_completions):
110 raise TypeError("this should be silenced")
110 raise TypeError("this should be silenced")
111
111
112 ip.complete("a.")
112 ip.complete("a.")
113
113
114
114
115 def test_unicode_completions():
115 def test_unicode_completions():
116 ip = get_ipython()
116 ip = get_ipython()
117 # Some strings that trigger different types of completion. Check them both
117 # Some strings that trigger different types of completion. Check them both
118 # in str and unicode forms
118 # in str and unicode forms
119 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
119 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
120 for t in s + list(map(unicode_type, s)):
120 for t in s + list(map(unicode_type, s)):
121 # We don't need to check exact completion values (they may change
121 # We don't need to check exact completion values (they may change
122 # depending on the state of the namespace, but at least no exceptions
122 # depending on the state of the namespace, but at least no exceptions
123 # should be thrown and the return value should be a pair of text, list
123 # should be thrown and the return value should be a pair of text, list
124 # values.
124 # values.
125 text, matches = ip.complete(t)
125 text, matches = ip.complete(t)
126 nt.assert_true(isinstance(text, string_types))
126 nt.assert_true(isinstance(text, string_types))
127 nt.assert_true(isinstance(matches, list))
127 nt.assert_true(isinstance(matches, list))
128
128
129 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
129 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
130 def test_latex_completions():
130 def test_latex_completions():
131 from IPython.core.latex_symbols import latex_symbols
131 from IPython.core.latex_symbols import latex_symbols
132 import random
132 import random
133 ip = get_ipython()
133 ip = get_ipython()
134 # Test some random unicode symbols
134 # Test some random unicode symbols
135 keys = random.sample(latex_symbols.keys(), 10)
135 keys = random.sample(latex_symbols.keys(), 10)
136 for k in keys:
136 for k in keys:
137 text, matches = ip.complete(k)
137 text, matches = ip.complete(k)
138 nt.assert_equal(len(matches),1)
138 nt.assert_equal(len(matches),1)
139 nt.assert_equal(text, k)
139 nt.assert_equal(text, k)
140 nt.assert_equal(matches[0], latex_symbols[k])
140 nt.assert_equal(matches[0], latex_symbols[k])
141 # Test a more complex line
141 # Test a more complex line
142 text, matches = ip.complete(u'print(\\alpha')
142 text, matches = ip.complete(u'print(\\alpha')
143 nt.assert_equals(text, u'\\alpha')
143 nt.assert_equals(text, u'\\alpha')
144 nt.assert_equals(matches[0], latex_symbols['\\alpha'])
144 nt.assert_equals(matches[0], latex_symbols['\\alpha'])
145 # Test multiple matching latex symbols
145 # Test multiple matching latex symbols
146 text, matches = ip.complete(u'\\al')
146 text, matches = ip.complete(u'\\al')
147 nt.assert_in('\\alpha', matches)
147 nt.assert_in('\\alpha', matches)
148 nt.assert_in('\\aleph', matches)
148 nt.assert_in('\\aleph', matches)
149
149
150
150
151
151
152
152
153 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
153 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
154 def test_back_latex_completion():
154 def test_back_latex_completion():
155 ip = get_ipython()
155 ip = get_ipython()
156
156
157 # do not return more than 1 matches fro \beta, only the latex one.
157 # do not return more than 1 matches fro \beta, only the latex one.
158 name, matches = ip.complete('\\Ξ²')
158 name, matches = ip.complete('\\Ξ²')
159 nt.assert_equal(len(matches), 1)
159 nt.assert_equal(len(matches), 1)
160 nt.assert_equal(matches[0], '\\beta')
160 nt.assert_equal(matches[0], '\\beta')
161
161
162 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
162 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
163 def test_back_unicode_completion():
163 def test_back_unicode_completion():
164 ip = get_ipython()
164 ip = get_ipython()
165
165
166 name, matches = ip.complete('\\β…€')
166 name, matches = ip.complete('\\β…€')
167 nt.assert_equal(len(matches), 1)
167 nt.assert_equal(len(matches), 1)
168 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
168 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
169
169
170
170
171 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
171 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
172 def test_forward_unicode_completion():
172 def test_forward_unicode_completion():
173 ip = get_ipython()
173 ip = get_ipython()
174
174
175 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
175 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
176 nt.assert_equal(len(matches), 1)
176 nt.assert_equal(len(matches), 1)
177 nt.assert_equal(matches[0], 'β…€')
177 nt.assert_equal(matches[0], 'β…€')
178
178
179 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
179 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
180 def test_no_ascii_back_completion():
180 def test_no_ascii_back_completion():
181 ip = get_ipython()
181 ip = get_ipython()
182 with TemporaryWorkingDirectory(): # Avoid any filename completions
182 with TemporaryWorkingDirectory(): # Avoid any filename completions
183 # single ascii letter that don't have yet completions
183 # single ascii letter that don't have yet completions
184 for letter in 'fjqyJMQVWY' :
184 for letter in 'fjqyJMQVWY' :
185 name, matches = ip.complete('\\'+letter)
185 name, matches = ip.complete('\\'+letter)
186 nt.assert_equal(matches, [])
186 nt.assert_equal(matches, [])
187
187
188
188
189
189
190
190
191 class CompletionSplitterTestCase(unittest.TestCase):
191 class CompletionSplitterTestCase(unittest.TestCase):
192 def setUp(self):
192 def setUp(self):
193 self.sp = completer.CompletionSplitter()
193 self.sp = completer.CompletionSplitter()
194
194
195 def test_delim_setting(self):
195 def test_delim_setting(self):
196 self.sp.delims = ' '
196 self.sp.delims = ' '
197 nt.assert_equal(self.sp.delims, ' ')
197 nt.assert_equal(self.sp.delims, ' ')
198 nt.assert_equal(self.sp._delim_expr, '[\ ]')
198 nt.assert_equal(self.sp._delim_expr, '[\ ]')
199
199
200 def test_spaces(self):
200 def test_spaces(self):
201 """Test with only spaces as split chars."""
201 """Test with only spaces as split chars."""
202 self.sp.delims = ' '
202 self.sp.delims = ' '
203 t = [('foo', '', 'foo'),
203 t = [('foo', '', 'foo'),
204 ('run foo', '', 'foo'),
204 ('run foo', '', 'foo'),
205 ('run foo', 'bar', 'foo'),
205 ('run foo', 'bar', 'foo'),
206 ]
206 ]
207 check_line_split(self.sp, t)
207 check_line_split(self.sp, t)
208
208
209
209
210 def test_has_open_quotes1():
210 def test_has_open_quotes1():
211 for s in ["'", "'''", "'hi' '"]:
211 for s in ["'", "'''", "'hi' '"]:
212 nt.assert_equal(completer.has_open_quotes(s), "'")
212 nt.assert_equal(completer.has_open_quotes(s), "'")
213
213
214
214
215 def test_has_open_quotes2():
215 def test_has_open_quotes2():
216 for s in ['"', '"""', '"hi" "']:
216 for s in ['"', '"""', '"hi" "']:
217 nt.assert_equal(completer.has_open_quotes(s), '"')
217 nt.assert_equal(completer.has_open_quotes(s), '"')
218
218
219
219
220 def test_has_open_quotes3():
220 def test_has_open_quotes3():
221 for s in ["''", "''' '''", "'hi' 'ipython'"]:
221 for s in ["''", "''' '''", "'hi' 'ipython'"]:
222 nt.assert_false(completer.has_open_quotes(s))
222 nt.assert_false(completer.has_open_quotes(s))
223
223
224
224
225 def test_has_open_quotes4():
225 def test_has_open_quotes4():
226 for s in ['""', '""" """', '"hi" "ipython"']:
226 for s in ['""', '""" """', '"hi" "ipython"']:
227 nt.assert_false(completer.has_open_quotes(s))
227 nt.assert_false(completer.has_open_quotes(s))
228
228
229
229
230 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
230 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
231 def test_abspath_file_completions():
231 def test_abspath_file_completions():
232 ip = get_ipython()
232 ip = get_ipython()
233 with TemporaryDirectory() as tmpdir:
233 with TemporaryDirectory() as tmpdir:
234 prefix = os.path.join(tmpdir, 'foo')
234 prefix = os.path.join(tmpdir, 'foo')
235 suffixes = ['1', '2']
235 suffixes = ['1', '2']
236 names = [prefix+s for s in suffixes]
236 names = [prefix+s for s in suffixes]
237 for n in names:
237 for n in names:
238 open(n, 'w').close()
238 open(n, 'w').close()
239
239
240 # Check simple completion
240 # Check simple completion
241 c = ip.complete(prefix)[1]
241 c = ip.complete(prefix)[1]
242 nt.assert_equal(c, names)
242 nt.assert_equal(c, names)
243
243
244 # Now check with a function call
244 # Now check with a function call
245 cmd = 'a = f("%s' % prefix
245 cmd = 'a = f("%s' % prefix
246 c = ip.complete(prefix, cmd)[1]
246 c = ip.complete(prefix, cmd)[1]
247 comp = [prefix+s for s in suffixes]
247 comp = [prefix+s for s in suffixes]
248 nt.assert_equal(c, comp)
248 nt.assert_equal(c, comp)
249
249
250
250
251 def test_local_file_completions():
251 def test_local_file_completions():
252 ip = get_ipython()
252 ip = get_ipython()
253 with TemporaryWorkingDirectory():
253 with TemporaryWorkingDirectory():
254 prefix = './foo'
254 prefix = './foo'
255 suffixes = ['1', '2']
255 suffixes = ['1', '2']
256 names = [prefix+s for s in suffixes]
256 names = [prefix+s for s in suffixes]
257 for n in names:
257 for n in names:
258 open(n, 'w').close()
258 open(n, 'w').close()
259
259
260 # Check simple completion
260 # Check simple completion
261 c = ip.complete(prefix)[1]
261 c = ip.complete(prefix)[1]
262 nt.assert_equal(c, names)
262 nt.assert_equal(c, names)
263
263
264 # Now check with a function call
264 # Now check with a function call
265 cmd = 'a = f("%s' % prefix
265 cmd = 'a = f("%s' % prefix
266 c = ip.complete(prefix, cmd)[1]
266 c = ip.complete(prefix, cmd)[1]
267 comp = [prefix+s for s in suffixes]
267 comp = [prefix+s for s in suffixes]
268 nt.assert_equal(c, comp)
268 nt.assert_equal(c, comp)
269
269
270
270
271 def test_greedy_completions():
271 def test_greedy_completions():
272 ip = get_ipython()
272 ip = get_ipython()
273 ip.ex('a=list(range(5))')
273 ip.ex('a=list(range(5))')
274 _,c = ip.complete('.',line='a[0].')
274 _,c = ip.complete('.',line='a[0].')
275 nt.assert_false('a[0].real' in c,
275 nt.assert_false('a[0].real' in c,
276 "Shouldn't have completed on a[0]: %s"%c)
276 "Shouldn't have completed on a[0]: %s"%c)
277 with greedy_completion():
277 with greedy_completion():
278 _,c = ip.complete('.',line='a[0].')
278 _,c = ip.complete('.',line='a[0].')
279 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
279 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
280
280
281
281
282 def test_omit__names():
282 def test_omit__names():
283 # also happens to test IPCompleter as a configurable
283 # also happens to test IPCompleter as a configurable
284 ip = get_ipython()
284 ip = get_ipython()
285 ip._hidden_attr = 1
285 ip._hidden_attr = 1
286 ip._x = {}
286 ip._x = {}
287 c = ip.Completer
287 c = ip.Completer
288 ip.ex('ip=get_ipython()')
288 ip.ex('ip=get_ipython()')
289 cfg = Config()
289 cfg = Config()
290 cfg.IPCompleter.omit__names = 0
290 cfg.IPCompleter.omit__names = 0
291 c.update_config(cfg)
291 c.update_config(cfg)
292 s,matches = c.complete('ip.')
292 s,matches = c.complete('ip.')
293 nt.assert_in('ip.__str__', matches)
293 nt.assert_in('ip.__str__', matches)
294 nt.assert_in('ip._hidden_attr', matches)
294 nt.assert_in('ip._hidden_attr', matches)
295 cfg = Config()
295 cfg.IPCompleter.omit__names = 1
296 cfg.IPCompleter.omit__names = 1
296 c.update_config(cfg)
297 c.update_config(cfg)
297 s,matches = c.complete('ip.')
298 s,matches = c.complete('ip.')
298 nt.assert_not_in('ip.__str__', matches)
299 nt.assert_not_in('ip.__str__', matches)
299 nt.assert_in('ip._hidden_attr', matches)
300 nt.assert_in('ip._hidden_attr', matches)
301 cfg = Config()
300 cfg.IPCompleter.omit__names = 2
302 cfg.IPCompleter.omit__names = 2
301 c.update_config(cfg)
303 c.update_config(cfg)
302 s,matches = c.complete('ip.')
304 s,matches = c.complete('ip.')
303 nt.assert_not_in('ip.__str__', matches)
305 nt.assert_not_in('ip.__str__', matches)
304 nt.assert_not_in('ip._hidden_attr', matches)
306 nt.assert_not_in('ip._hidden_attr', matches)
305 s,matches = c.complete('ip._x.')
307 s,matches = c.complete('ip._x.')
306 nt.assert_in('ip._x.keys', matches)
308 nt.assert_in('ip._x.keys', matches)
307 del ip._hidden_attr
309 del ip._hidden_attr
308
310
309
311
310 def test_limit_to__all__False_ok():
312 def test_limit_to__all__False_ok():
311 ip = get_ipython()
313 ip = get_ipython()
312 c = ip.Completer
314 c = ip.Completer
313 ip.ex('class D: x=24')
315 ip.ex('class D: x=24')
314 ip.ex('d=D()')
316 ip.ex('d=D()')
315 cfg = Config()
317 cfg = Config()
316 cfg.IPCompleter.limit_to__all__ = False
318 cfg.IPCompleter.limit_to__all__ = False
317 c.update_config(cfg)
319 c.update_config(cfg)
318 s, matches = c.complete('d.')
320 s, matches = c.complete('d.')
319 nt.assert_in('d.x', matches)
321 nt.assert_in('d.x', matches)
320
322
321
323
322 def test_limit_to__all__True_ok():
324 def test_limit_to__all__True_ok():
323 ip = get_ipython()
325 ip = get_ipython()
324 c = ip.Completer
326 c = ip.Completer
325 ip.ex('class D: x=24')
327 ip.ex('class D: x=24')
326 ip.ex('d=D()')
328 ip.ex('d=D()')
327 ip.ex("d.__all__=['z']")
329 ip.ex("d.__all__=['z']")
328 cfg = Config()
330 cfg = Config()
329 cfg.IPCompleter.limit_to__all__ = True
331 cfg.IPCompleter.limit_to__all__ = True
330 c.update_config(cfg)
332 c.update_config(cfg)
331 s, matches = c.complete('d.')
333 s, matches = c.complete('d.')
332 nt.assert_in('d.z', matches)
334 nt.assert_in('d.z', matches)
333 nt.assert_not_in('d.x', matches)
335 nt.assert_not_in('d.x', matches)
334
336
335
337
336 def test_get__all__entries_ok():
338 def test_get__all__entries_ok():
337 class A(object):
339 class A(object):
338 __all__ = ['x', 1]
340 __all__ = ['x', 1]
339 words = completer.get__all__entries(A())
341 words = completer.get__all__entries(A())
340 nt.assert_equal(words, ['x'])
342 nt.assert_equal(words, ['x'])
341
343
342
344
343 def test_get__all__entries_no__all__ok():
345 def test_get__all__entries_no__all__ok():
344 class A(object):
346 class A(object):
345 pass
347 pass
346 words = completer.get__all__entries(A())
348 words = completer.get__all__entries(A())
347 nt.assert_equal(words, [])
349 nt.assert_equal(words, [])
348
350
349
351
350 def test_func_kw_completions():
352 def test_func_kw_completions():
351 ip = get_ipython()
353 ip = get_ipython()
352 c = ip.Completer
354 c = ip.Completer
353 ip.ex('def myfunc(a=1,b=2): return a+b')
355 ip.ex('def myfunc(a=1,b=2): return a+b')
354 s, matches = c.complete(None, 'myfunc(1,b')
356 s, matches = c.complete(None, 'myfunc(1,b')
355 nt.assert_in('b=', matches)
357 nt.assert_in('b=', matches)
356 # Simulate completing with cursor right after b (pos==10):
358 # Simulate completing with cursor right after b (pos==10):
357 s, matches = c.complete(None, 'myfunc(1,b)', 10)
359 s, matches = c.complete(None, 'myfunc(1,b)', 10)
358 nt.assert_in('b=', matches)
360 nt.assert_in('b=', matches)
359 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
361 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
360 nt.assert_in('b=', matches)
362 nt.assert_in('b=', matches)
361 #builtin function
363 #builtin function
362 s, matches = c.complete(None, 'min(k, k')
364 s, matches = c.complete(None, 'min(k, k')
363 nt.assert_in('key=', matches)
365 nt.assert_in('key=', matches)
364
366
365
367
366 def test_default_arguments_from_docstring():
368 def test_default_arguments_from_docstring():
367 doc = min.__doc__
369 doc = min.__doc__
368 ip = get_ipython()
370 ip = get_ipython()
369 c = ip.Completer
371 c = ip.Completer
370 kwd = c._default_arguments_from_docstring(
372 kwd = c._default_arguments_from_docstring(
371 'min(iterable[, key=func]) -> value')
373 'min(iterable[, key=func]) -> value')
372 nt.assert_equal(kwd, ['key'])
374 nt.assert_equal(kwd, ['key'])
373 #with cython type etc
375 #with cython type etc
374 kwd = c._default_arguments_from_docstring(
376 kwd = c._default_arguments_from_docstring(
375 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
377 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
376 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
378 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
377 #white spaces
379 #white spaces
378 kwd = c._default_arguments_from_docstring(
380 kwd = c._default_arguments_from_docstring(
379 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
381 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
380 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
382 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
381
383
382 def test_line_magics():
384 def test_line_magics():
383 ip = get_ipython()
385 ip = get_ipython()
384 c = ip.Completer
386 c = ip.Completer
385 s, matches = c.complete(None, 'lsmag')
387 s, matches = c.complete(None, 'lsmag')
386 nt.assert_in('%lsmagic', matches)
388 nt.assert_in('%lsmagic', matches)
387 s, matches = c.complete(None, '%lsmag')
389 s, matches = c.complete(None, '%lsmag')
388 nt.assert_in('%lsmagic', matches)
390 nt.assert_in('%lsmagic', matches)
389
391
390
392
391 def test_cell_magics():
393 def test_cell_magics():
392 from IPython.core.magic import register_cell_magic
394 from IPython.core.magic import register_cell_magic
393
395
394 @register_cell_magic
396 @register_cell_magic
395 def _foo_cellm(line, cell):
397 def _foo_cellm(line, cell):
396 pass
398 pass
397
399
398 ip = get_ipython()
400 ip = get_ipython()
399 c = ip.Completer
401 c = ip.Completer
400
402
401 s, matches = c.complete(None, '_foo_ce')
403 s, matches = c.complete(None, '_foo_ce')
402 nt.assert_in('%%_foo_cellm', matches)
404 nt.assert_in('%%_foo_cellm', matches)
403 s, matches = c.complete(None, '%%_foo_ce')
405 s, matches = c.complete(None, '%%_foo_ce')
404 nt.assert_in('%%_foo_cellm', matches)
406 nt.assert_in('%%_foo_cellm', matches)
405
407
406
408
407 def test_line_cell_magics():
409 def test_line_cell_magics():
408 from IPython.core.magic import register_line_cell_magic
410 from IPython.core.magic import register_line_cell_magic
409
411
410 @register_line_cell_magic
412 @register_line_cell_magic
411 def _bar_cellm(line, cell):
413 def _bar_cellm(line, cell):
412 pass
414 pass
413
415
414 ip = get_ipython()
416 ip = get_ipython()
415 c = ip.Completer
417 c = ip.Completer
416
418
417 # The policy here is trickier, see comments in completion code. The
419 # The policy here is trickier, see comments in completion code. The
418 # returned values depend on whether the user passes %% or not explicitly,
420 # returned values depend on whether the user passes %% or not explicitly,
419 # and this will show a difference if the same name is both a line and cell
421 # and this will show a difference if the same name is both a line and cell
420 # magic.
422 # magic.
421 s, matches = c.complete(None, '_bar_ce')
423 s, matches = c.complete(None, '_bar_ce')
422 nt.assert_in('%_bar_cellm', matches)
424 nt.assert_in('%_bar_cellm', matches)
423 nt.assert_in('%%_bar_cellm', matches)
425 nt.assert_in('%%_bar_cellm', matches)
424 s, matches = c.complete(None, '%_bar_ce')
426 s, matches = c.complete(None, '%_bar_ce')
425 nt.assert_in('%_bar_cellm', matches)
427 nt.assert_in('%_bar_cellm', matches)
426 nt.assert_in('%%_bar_cellm', matches)
428 nt.assert_in('%%_bar_cellm', matches)
427 s, matches = c.complete(None, '%%_bar_ce')
429 s, matches = c.complete(None, '%%_bar_ce')
428 nt.assert_not_in('%_bar_cellm', matches)
430 nt.assert_not_in('%_bar_cellm', matches)
429 nt.assert_in('%%_bar_cellm', matches)
431 nt.assert_in('%%_bar_cellm', matches)
430
432
431
433
432 def test_magic_completion_order():
434 def test_magic_completion_order():
433
435
434 ip = get_ipython()
436 ip = get_ipython()
435 c = ip.Completer
437 c = ip.Completer
436
438
437 # Test ordering of magics and non-magics with the same name
439 # Test ordering of magics and non-magics with the same name
438 # We want the non-magic first
440 # We want the non-magic first
439
441
440 # Before importing matplotlib, there should only be one option:
442 # Before importing matplotlib, there should only be one option:
441
443
442 text, matches = c.complete('mat')
444 text, matches = c.complete('mat')
443 nt.assert_equal(matches, ["%matplotlib"])
445 nt.assert_equal(matches, ["%matplotlib"])
444
446
445
447
446 ip.run_cell("matplotlib = 1") # introduce name into namespace
448 ip.run_cell("matplotlib = 1") # introduce name into namespace
447
449
448 # After the import, there should be two options, ordered like this:
450 # After the import, there should be two options, ordered like this:
449 text, matches = c.complete('mat')
451 text, matches = c.complete('mat')
450 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
452 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
451
453
452
454
453 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
455 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
454
456
455 # Order of user variable and line and cell magics with same name:
457 # Order of user variable and line and cell magics with same name:
456 text, matches = c.complete('timeit')
458 text, matches = c.complete('timeit')
457 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
459 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
458
460
459
461
460 def test_dict_key_completion_string():
462 def test_dict_key_completion_string():
461 """Test dictionary key completion for string keys"""
463 """Test dictionary key completion for string keys"""
462 ip = get_ipython()
464 ip = get_ipython()
463 complete = ip.Completer.complete
465 complete = ip.Completer.complete
464
466
465 ip.user_ns['d'] = {'abc': None}
467 ip.user_ns['d'] = {'abc': None}
466
468
467 # check completion at different stages
469 # check completion at different stages
468 _, matches = complete(line_buffer="d[")
470 _, matches = complete(line_buffer="d[")
469 nt.assert_in("'abc'", matches)
471 nt.assert_in("'abc'", matches)
470 nt.assert_not_in("'abc']", matches)
472 nt.assert_not_in("'abc']", matches)
471
473
472 _, matches = complete(line_buffer="d['")
474 _, matches = complete(line_buffer="d['")
473 nt.assert_in("abc", matches)
475 nt.assert_in("abc", matches)
474 nt.assert_not_in("abc']", matches)
476 nt.assert_not_in("abc']", matches)
475
477
476 _, matches = complete(line_buffer="d['a")
478 _, matches = complete(line_buffer="d['a")
477 nt.assert_in("abc", matches)
479 nt.assert_in("abc", matches)
478 nt.assert_not_in("abc']", matches)
480 nt.assert_not_in("abc']", matches)
479
481
480 # check use of different quoting
482 # check use of different quoting
481 _, matches = complete(line_buffer="d[\"")
483 _, matches = complete(line_buffer="d[\"")
482 nt.assert_in("abc", matches)
484 nt.assert_in("abc", matches)
483 nt.assert_not_in('abc\"]', matches)
485 nt.assert_not_in('abc\"]', matches)
484
486
485 _, matches = complete(line_buffer="d[\"a")
487 _, matches = complete(line_buffer="d[\"a")
486 nt.assert_in("abc", matches)
488 nt.assert_in("abc", matches)
487 nt.assert_not_in('abc\"]', matches)
489 nt.assert_not_in('abc\"]', matches)
488
490
489 # check sensitivity to following context
491 # check sensitivity to following context
490 _, matches = complete(line_buffer="d[]", cursor_pos=2)
492 _, matches = complete(line_buffer="d[]", cursor_pos=2)
491 nt.assert_in("'abc'", matches)
493 nt.assert_in("'abc'", matches)
492
494
493 _, matches = complete(line_buffer="d['']", cursor_pos=3)
495 _, matches = complete(line_buffer="d['']", cursor_pos=3)
494 nt.assert_in("abc", matches)
496 nt.assert_in("abc", matches)
495 nt.assert_not_in("abc'", matches)
497 nt.assert_not_in("abc'", matches)
496 nt.assert_not_in("abc']", matches)
498 nt.assert_not_in("abc']", matches)
497
499
498 # check multiple solutions are correctly returned and that noise is not
500 # check multiple solutions are correctly returned and that noise is not
499 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
501 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
500 5: None}
502 5: None}
501
503
502 _, matches = complete(line_buffer="d['a")
504 _, matches = complete(line_buffer="d['a")
503 nt.assert_in("abc", matches)
505 nt.assert_in("abc", matches)
504 nt.assert_in("abd", matches)
506 nt.assert_in("abd", matches)
505 nt.assert_not_in("bad", matches)
507 nt.assert_not_in("bad", matches)
506 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
508 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
507
509
508 # check escaping and whitespace
510 # check escaping and whitespace
509 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
511 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
510 _, matches = complete(line_buffer="d['a")
512 _, matches = complete(line_buffer="d['a")
511 nt.assert_in("a\\nb", matches)
513 nt.assert_in("a\\nb", matches)
512 nt.assert_in("a\\'b", matches)
514 nt.assert_in("a\\'b", matches)
513 nt.assert_in("a\"b", matches)
515 nt.assert_in("a\"b", matches)
514 nt.assert_in("a word", matches)
516 nt.assert_in("a word", matches)
515 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
517 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
516
518
517 # - can complete on non-initial word of the string
519 # - can complete on non-initial word of the string
518 _, matches = complete(line_buffer="d['a w")
520 _, matches = complete(line_buffer="d['a w")
519 nt.assert_in("word", matches)
521 nt.assert_in("word", matches)
520
522
521 # - understands quote escaping
523 # - understands quote escaping
522 _, matches = complete(line_buffer="d['a\\'")
524 _, matches = complete(line_buffer="d['a\\'")
523 nt.assert_in("b", matches)
525 nt.assert_in("b", matches)
524
526
525 # - default quoting should work like repr
527 # - default quoting should work like repr
526 _, matches = complete(line_buffer="d[")
528 _, matches = complete(line_buffer="d[")
527 nt.assert_in("\"a'b\"", matches)
529 nt.assert_in("\"a'b\"", matches)
528
530
529 # - when opening quote with ", possible to match with unescaped apostrophe
531 # - when opening quote with ", possible to match with unescaped apostrophe
530 _, matches = complete(line_buffer="d[\"a'")
532 _, matches = complete(line_buffer="d[\"a'")
531 nt.assert_in("b", matches)
533 nt.assert_in("b", matches)
532
534
533 # need to not split at delims that readline won't split at
535 # need to not split at delims that readline won't split at
534 if '-' not in ip.Completer.splitter.delims:
536 if '-' not in ip.Completer.splitter.delims:
535 ip.user_ns['d'] = {'before-after': None}
537 ip.user_ns['d'] = {'before-after': None}
536 _, matches = complete(line_buffer="d['before-af")
538 _, matches = complete(line_buffer="d['before-af")
537 nt.assert_in('before-after', matches)
539 nt.assert_in('before-after', matches)
538
540
539 def test_dict_key_completion_contexts():
541 def test_dict_key_completion_contexts():
540 """Test expression contexts in which dict key completion occurs"""
542 """Test expression contexts in which dict key completion occurs"""
541 ip = get_ipython()
543 ip = get_ipython()
542 complete = ip.Completer.complete
544 complete = ip.Completer.complete
543 d = {'abc': None}
545 d = {'abc': None}
544 ip.user_ns['d'] = d
546 ip.user_ns['d'] = d
545
547
546 class C:
548 class C:
547 data = d
549 data = d
548 ip.user_ns['C'] = C
550 ip.user_ns['C'] = C
549 ip.user_ns['get'] = lambda: d
551 ip.user_ns['get'] = lambda: d
550
552
551 def assert_no_completion(**kwargs):
553 def assert_no_completion(**kwargs):
552 _, matches = complete(**kwargs)
554 _, matches = complete(**kwargs)
553 nt.assert_not_in('abc', matches)
555 nt.assert_not_in('abc', matches)
554 nt.assert_not_in('abc\'', matches)
556 nt.assert_not_in('abc\'', matches)
555 nt.assert_not_in('abc\']', matches)
557 nt.assert_not_in('abc\']', matches)
556 nt.assert_not_in('\'abc\'', matches)
558 nt.assert_not_in('\'abc\'', matches)
557 nt.assert_not_in('\'abc\']', matches)
559 nt.assert_not_in('\'abc\']', matches)
558
560
559 def assert_completion(**kwargs):
561 def assert_completion(**kwargs):
560 _, matches = complete(**kwargs)
562 _, matches = complete(**kwargs)
561 nt.assert_in("'abc'", matches)
563 nt.assert_in("'abc'", matches)
562 nt.assert_not_in("'abc']", matches)
564 nt.assert_not_in("'abc']", matches)
563
565
564 # no completion after string closed, even if reopened
566 # no completion after string closed, even if reopened
565 assert_no_completion(line_buffer="d['a'")
567 assert_no_completion(line_buffer="d['a'")
566 assert_no_completion(line_buffer="d[\"a\"")
568 assert_no_completion(line_buffer="d[\"a\"")
567 assert_no_completion(line_buffer="d['a' + ")
569 assert_no_completion(line_buffer="d['a' + ")
568 assert_no_completion(line_buffer="d['a' + '")
570 assert_no_completion(line_buffer="d['a' + '")
569
571
570 # completion in non-trivial expressions
572 # completion in non-trivial expressions
571 assert_completion(line_buffer="+ d[")
573 assert_completion(line_buffer="+ d[")
572 assert_completion(line_buffer="(d[")
574 assert_completion(line_buffer="(d[")
573 assert_completion(line_buffer="C.data[")
575 assert_completion(line_buffer="C.data[")
574
576
575 # greedy flag
577 # greedy flag
576 def assert_completion(**kwargs):
578 def assert_completion(**kwargs):
577 _, matches = complete(**kwargs)
579 _, matches = complete(**kwargs)
578 nt.assert_in("get()['abc']", matches)
580 nt.assert_in("get()['abc']", matches)
579
581
580 assert_no_completion(line_buffer="get()[")
582 assert_no_completion(line_buffer="get()[")
581 with greedy_completion():
583 with greedy_completion():
582 assert_completion(line_buffer="get()[")
584 assert_completion(line_buffer="get()[")
583 assert_completion(line_buffer="get()['")
585 assert_completion(line_buffer="get()['")
584 assert_completion(line_buffer="get()['a")
586 assert_completion(line_buffer="get()['a")
585 assert_completion(line_buffer="get()['ab")
587 assert_completion(line_buffer="get()['ab")
586 assert_completion(line_buffer="get()['abc")
588 assert_completion(line_buffer="get()['abc")
587
589
588
590
589
591
590 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
592 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
591 def test_dict_key_completion_bytes():
593 def test_dict_key_completion_bytes():
592 """Test handling of bytes in dict key completion"""
594 """Test handling of bytes in dict key completion"""
593 ip = get_ipython()
595 ip = get_ipython()
594 complete = ip.Completer.complete
596 complete = ip.Completer.complete
595
597
596 ip.user_ns['d'] = {'abc': None, b'abd': None}
598 ip.user_ns['d'] = {'abc': None, b'abd': None}
597
599
598 _, matches = complete(line_buffer="d[")
600 _, matches = complete(line_buffer="d[")
599 nt.assert_in("'abc'", matches)
601 nt.assert_in("'abc'", matches)
600 nt.assert_in("b'abd'", matches)
602 nt.assert_in("b'abd'", matches)
601
603
602 if False: # not currently implemented
604 if False: # not currently implemented
603 _, matches = complete(line_buffer="d[b")
605 _, matches = complete(line_buffer="d[b")
604 nt.assert_in("b'abd'", matches)
606 nt.assert_in("b'abd'", matches)
605 nt.assert_not_in("b'abc'", matches)
607 nt.assert_not_in("b'abc'", matches)
606
608
607 _, matches = complete(line_buffer="d[b'")
609 _, matches = complete(line_buffer="d[b'")
608 nt.assert_in("abd", matches)
610 nt.assert_in("abd", matches)
609 nt.assert_not_in("abc", matches)
611 nt.assert_not_in("abc", matches)
610
612
611 _, matches = complete(line_buffer="d[B'")
613 _, matches = complete(line_buffer="d[B'")
612 nt.assert_in("abd", matches)
614 nt.assert_in("abd", matches)
613 nt.assert_not_in("abc", matches)
615 nt.assert_not_in("abc", matches)
614
616
615 _, matches = complete(line_buffer="d['")
617 _, matches = complete(line_buffer="d['")
616 nt.assert_in("abc", matches)
618 nt.assert_in("abc", matches)
617 nt.assert_not_in("abd", matches)
619 nt.assert_not_in("abd", matches)
618
620
619
621
620 @dec.onlyif(sys.version_info[0] < 3, 'This test only applies in Py<3')
622 @dec.onlyif(sys.version_info[0] < 3, 'This test only applies in Py<3')
621 def test_dict_key_completion_unicode_py2():
623 def test_dict_key_completion_unicode_py2():
622 """Test handling of unicode in dict key completion"""
624 """Test handling of unicode in dict key completion"""
623 ip = get_ipython()
625 ip = get_ipython()
624 complete = ip.Completer.complete
626 complete = ip.Completer.complete
625
627
626 ip.user_ns['d'] = {u'abc': None,
628 ip.user_ns['d'] = {u'abc': None,
627 u'a\u05d0b': None}
629 u'a\u05d0b': None}
628
630
629 _, matches = complete(line_buffer="d[")
631 _, matches = complete(line_buffer="d[")
630 nt.assert_in("u'abc'", matches)
632 nt.assert_in("u'abc'", matches)
631 nt.assert_in("u'a\\u05d0b'", matches)
633 nt.assert_in("u'a\\u05d0b'", matches)
632
634
633 _, matches = complete(line_buffer="d['a")
635 _, matches = complete(line_buffer="d['a")
634 nt.assert_in("abc", matches)
636 nt.assert_in("abc", matches)
635 nt.assert_not_in("a\\u05d0b", matches)
637 nt.assert_not_in("a\\u05d0b", matches)
636
638
637 _, matches = complete(line_buffer="d[u'a")
639 _, matches = complete(line_buffer="d[u'a")
638 nt.assert_in("abc", matches)
640 nt.assert_in("abc", matches)
639 nt.assert_in("a\\u05d0b", matches)
641 nt.assert_in("a\\u05d0b", matches)
640
642
641 _, matches = complete(line_buffer="d[U'a")
643 _, matches = complete(line_buffer="d[U'a")
642 nt.assert_in("abc", matches)
644 nt.assert_in("abc", matches)
643 nt.assert_in("a\\u05d0b", matches)
645 nt.assert_in("a\\u05d0b", matches)
644
646
645 # query using escape
647 # query using escape
646 _, matches = complete(line_buffer=u"d[u'a\\u05d0")
648 _, matches = complete(line_buffer=u"d[u'a\\u05d0")
647 nt.assert_in("u05d0b", matches) # tokenized after \\
649 nt.assert_in("u05d0b", matches) # tokenized after \\
648
650
649 # query using character
651 # query using character
650 _, matches = complete(line_buffer=u"d[u'a\u05d0")
652 _, matches = complete(line_buffer=u"d[u'a\u05d0")
651 nt.assert_in(u"a\u05d0b", matches)
653 nt.assert_in(u"a\u05d0b", matches)
652
654
653 with greedy_completion():
655 with greedy_completion():
654 _, matches = complete(line_buffer="d[")
656 _, matches = complete(line_buffer="d[")
655 nt.assert_in("d[u'abc']", matches)
657 nt.assert_in("d[u'abc']", matches)
656 nt.assert_in("d[u'a\\u05d0b']", matches)
658 nt.assert_in("d[u'a\\u05d0b']", matches)
657
659
658 _, matches = complete(line_buffer="d['a")
660 _, matches = complete(line_buffer="d['a")
659 nt.assert_in("d['abc']", matches)
661 nt.assert_in("d['abc']", matches)
660 nt.assert_not_in("d[u'a\\u05d0b']", matches)
662 nt.assert_not_in("d[u'a\\u05d0b']", matches)
661
663
662 _, matches = complete(line_buffer="d[u'a")
664 _, matches = complete(line_buffer="d[u'a")
663 nt.assert_in("d[u'abc']", matches)
665 nt.assert_in("d[u'abc']", matches)
664 nt.assert_in("d[u'a\\u05d0b']", matches)
666 nt.assert_in("d[u'a\\u05d0b']", matches)
665
667
666 _, matches = complete(line_buffer="d[U'a")
668 _, matches = complete(line_buffer="d[U'a")
667 nt.assert_in("d[U'abc']", matches)
669 nt.assert_in("d[U'abc']", matches)
668 nt.assert_in("d[U'a\\u05d0b']", matches)
670 nt.assert_in("d[U'a\\u05d0b']", matches)
669
671
670 # query using escape
672 # query using escape
671 _, matches = complete(line_buffer=u"d[u'a\\u05d0")
673 _, matches = complete(line_buffer=u"d[u'a\\u05d0")
672 nt.assert_in("d[u'a\\u05d0b']", matches) # tokenized after \\
674 nt.assert_in("d[u'a\\u05d0b']", matches) # tokenized after \\
673
675
674 # query using character
676 # query using character
675 _, matches = complete(line_buffer=u"d[u'a\u05d0")
677 _, matches = complete(line_buffer=u"d[u'a\u05d0")
676 nt.assert_in(u"d[u'a\u05d0b']", matches)
678 nt.assert_in(u"d[u'a\u05d0b']", matches)
677
679
678
680
679 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
681 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
680 def test_dict_key_completion_unicode_py3():
682 def test_dict_key_completion_unicode_py3():
681 """Test handling of unicode in dict key completion"""
683 """Test handling of unicode in dict key completion"""
682 ip = get_ipython()
684 ip = get_ipython()
683 complete = ip.Completer.complete
685 complete = ip.Completer.complete
684
686
685 ip.user_ns['d'] = {u'a\u05d0': None}
687 ip.user_ns['d'] = {u'a\u05d0': None}
686
688
687 # query using escape
689 # query using escape
688 _, matches = complete(line_buffer="d['a\\u05d0")
690 _, matches = complete(line_buffer="d['a\\u05d0")
689 nt.assert_in("u05d0", matches) # tokenized after \\
691 nt.assert_in("u05d0", matches) # tokenized after \\
690
692
691 # query using character
693 # query using character
692 _, matches = complete(line_buffer="d['a\u05d0")
694 _, matches = complete(line_buffer="d['a\u05d0")
693 nt.assert_in(u"a\u05d0", matches)
695 nt.assert_in(u"a\u05d0", matches)
694
696
695 with greedy_completion():
697 with greedy_completion():
696 # query using escape
698 # query using escape
697 _, matches = complete(line_buffer="d['a\\u05d0")
699 _, matches = complete(line_buffer="d['a\\u05d0")
698 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
700 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
699
701
700 # query using character
702 # query using character
701 _, matches = complete(line_buffer="d['a\u05d0")
703 _, matches = complete(line_buffer="d['a\u05d0")
702 nt.assert_in(u"d['a\u05d0']", matches)
704 nt.assert_in(u"d['a\u05d0']", matches)
703
705
704
706
705
707
706 @dec.skip_without('numpy')
708 @dec.skip_without('numpy')
707 def test_struct_array_key_completion():
709 def test_struct_array_key_completion():
708 """Test dict key completion applies to numpy struct arrays"""
710 """Test dict key completion applies to numpy struct arrays"""
709 import numpy
711 import numpy
710 ip = get_ipython()
712 ip = get_ipython()
711 complete = ip.Completer.complete
713 complete = ip.Completer.complete
712 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
714 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
713 _, matches = complete(line_buffer="d['")
715 _, matches = complete(line_buffer="d['")
714 nt.assert_in("hello", matches)
716 nt.assert_in("hello", matches)
715 nt.assert_in("world", matches)
717 nt.assert_in("world", matches)
716 # complete on the numpy struct itself
718 # complete on the numpy struct itself
717 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
719 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
718 ('my_data', '>f4', 5)])
720 ('my_data', '>f4', 5)])
719 x = numpy.zeros(2, dtype=dt)
721 x = numpy.zeros(2, dtype=dt)
720 ip.user_ns['d'] = x[1]
722 ip.user_ns['d'] = x[1]
721 _, matches = complete(line_buffer="d['")
723 _, matches = complete(line_buffer="d['")
722 nt.assert_in("my_head", matches)
724 nt.assert_in("my_head", matches)
723 nt.assert_in("my_data", matches)
725 nt.assert_in("my_data", matches)
724 # complete on a nested level
726 # complete on a nested level
725 with greedy_completion():
727 with greedy_completion():
726 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
728 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
727 _, matches = complete(line_buffer="d[1]['my_head']['")
729 _, matches = complete(line_buffer="d[1]['my_head']['")
728 nt.assert_true(any(["my_dt" in m for m in matches]))
730 nt.assert_true(any(["my_dt" in m for m in matches]))
729 nt.assert_true(any(["my_df" in m for m in matches]))
731 nt.assert_true(any(["my_df" in m for m in matches]))
730
732
731
733
732 @dec.skip_without('pandas')
734 @dec.skip_without('pandas')
733 def test_dataframe_key_completion():
735 def test_dataframe_key_completion():
734 """Test dict key completion applies to pandas DataFrames"""
736 """Test dict key completion applies to pandas DataFrames"""
735 import pandas
737 import pandas
736 ip = get_ipython()
738 ip = get_ipython()
737 complete = ip.Completer.complete
739 complete = ip.Completer.complete
738 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
740 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
739 _, matches = complete(line_buffer="d['")
741 _, matches = complete(line_buffer="d['")
740 nt.assert_in("hello", matches)
742 nt.assert_in("hello", matches)
741 nt.assert_in("world", matches)
743 nt.assert_in("world", matches)
742
744
743
745
744 def test_dict_key_completion_invalids():
746 def test_dict_key_completion_invalids():
745 """Smoke test cases dict key completion can't handle"""
747 """Smoke test cases dict key completion can't handle"""
746 ip = get_ipython()
748 ip = get_ipython()
747 complete = ip.Completer.complete
749 complete = ip.Completer.complete
748
750
749 ip.user_ns['no_getitem'] = None
751 ip.user_ns['no_getitem'] = None
750 ip.user_ns['no_keys'] = []
752 ip.user_ns['no_keys'] = []
751 ip.user_ns['cant_call_keys'] = dict
753 ip.user_ns['cant_call_keys'] = dict
752 ip.user_ns['empty'] = {}
754 ip.user_ns['empty'] = {}
753 ip.user_ns['d'] = {'abc': 5}
755 ip.user_ns['d'] = {'abc': 5}
754
756
755 _, matches = complete(line_buffer="no_getitem['")
757 _, matches = complete(line_buffer="no_getitem['")
756 _, matches = complete(line_buffer="no_keys['")
758 _, matches = complete(line_buffer="no_keys['")
757 _, matches = complete(line_buffer="cant_call_keys['")
759 _, matches = complete(line_buffer="cant_call_keys['")
758 _, matches = complete(line_buffer="empty['")
760 _, matches = complete(line_buffer="empty['")
759 _, matches = complete(line_buffer="name_error['")
761 _, matches = complete(line_buffer="name_error['")
760 _, matches = complete(line_buffer="d['\\") # incomplete escape
762 _, matches = complete(line_buffer="d['\\") # incomplete escape
General Comments 0
You need to be logged in to leave comments. Login now