##// END OF EJS Templates
Merge pull request #13350 from Kojoley/remove-parso-and-jedi-xfails...
Matthias Bussonnier -
r27200:341d8139 merge
parent child Browse files
Show More
@@ -1,1280 +1,1263 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 pytest
8 import pytest
9 import sys
9 import sys
10 import textwrap
10 import textwrap
11 import unittest
11 import unittest
12
12
13 from contextlib import contextmanager
13 from contextlib import contextmanager
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.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.testing import decorators as dec
20 from IPython.testing import decorators as dec
21
21
22 from IPython.core.completer import (
22 from IPython.core.completer import (
23 Completion,
23 Completion,
24 provisionalcompleter,
24 provisionalcompleter,
25 match_dict_keys,
25 match_dict_keys,
26 _deduplicate_completions,
26 _deduplicate_completions,
27 )
27 )
28
28
29 if sys.version_info >= (3, 10):
30 import jedi
31 from pkg_resources import parse_version
32
33 # Requires https://github.com/davidhalter/jedi/pull/1795
34 jedi_issue = parse_version(jedi.__version__) <= parse_version("0.18.0")
35 else:
36 jedi_issue = False
37
38 # -----------------------------------------------------------------------------
29 # -----------------------------------------------------------------------------
39 # Test functions
30 # Test functions
40 # -----------------------------------------------------------------------------
31 # -----------------------------------------------------------------------------
41
32
42 def recompute_unicode_ranges():
33 def recompute_unicode_ranges():
43 """
34 """
44 utility to recompute the largest unicode range without any characters
35 utility to recompute the largest unicode range without any characters
45
36
46 use to recompute the gap in the global _UNICODE_RANGES of completer.py
37 use to recompute the gap in the global _UNICODE_RANGES of completer.py
47 """
38 """
48 import itertools
39 import itertools
49 import unicodedata
40 import unicodedata
50 valid = []
41 valid = []
51 for c in range(0,0x10FFFF + 1):
42 for c in range(0,0x10FFFF + 1):
52 try:
43 try:
53 unicodedata.name(chr(c))
44 unicodedata.name(chr(c))
54 except ValueError:
45 except ValueError:
55 continue
46 continue
56 valid.append(c)
47 valid.append(c)
57
48
58 def ranges(i):
49 def ranges(i):
59 for a, b in itertools.groupby(enumerate(i), lambda pair: pair[1] - pair[0]):
50 for a, b in itertools.groupby(enumerate(i), lambda pair: pair[1] - pair[0]):
60 b = list(b)
51 b = list(b)
61 yield b[0][1], b[-1][1]
52 yield b[0][1], b[-1][1]
62
53
63 rg = list(ranges(valid))
54 rg = list(ranges(valid))
64 lens = []
55 lens = []
65 gap_lens = []
56 gap_lens = []
66 pstart, pstop = 0,0
57 pstart, pstop = 0,0
67 for start, stop in rg:
58 for start, stop in rg:
68 lens.append(stop-start)
59 lens.append(stop-start)
69 gap_lens.append((start - pstop, hex(pstop), hex(start), f'{round((start - pstop)/0xe01f0*100)}%'))
60 gap_lens.append((start - pstop, hex(pstop), hex(start), f'{round((start - pstop)/0xe01f0*100)}%'))
70 pstart, pstop = start, stop
61 pstart, pstop = start, stop
71
62
72 return sorted(gap_lens)[-1]
63 return sorted(gap_lens)[-1]
73
64
74
65
75
66
76 def test_unicode_range():
67 def test_unicode_range():
77 """
68 """
78 Test that the ranges we test for unicode names give the same number of
69 Test that the ranges we test for unicode names give the same number of
79 results than testing the full length.
70 results than testing the full length.
80 """
71 """
81 from IPython.core.completer import _unicode_name_compute, _UNICODE_RANGES
72 from IPython.core.completer import _unicode_name_compute, _UNICODE_RANGES
82
73
83 expected_list = _unicode_name_compute([(0, 0x110000)])
74 expected_list = _unicode_name_compute([(0, 0x110000)])
84 test = _unicode_name_compute(_UNICODE_RANGES)
75 test = _unicode_name_compute(_UNICODE_RANGES)
85 len_exp = len(expected_list)
76 len_exp = len(expected_list)
86 len_test = len(test)
77 len_test = len(test)
87
78
88 # do not inline the len() or on error pytest will try to print the 130 000 +
79 # do not inline the len() or on error pytest will try to print the 130 000 +
89 # elements.
80 # elements.
90 message = None
81 message = None
91 if len_exp != len_test or len_exp > 131808:
82 if len_exp != len_test or len_exp > 131808:
92 size, start, stop, prct = recompute_unicode_ranges()
83 size, start, stop, prct = recompute_unicode_ranges()
93 message = f"""_UNICODE_RANGES likely wrong and need updating. This is
84 message = f"""_UNICODE_RANGES likely wrong and need updating. This is
94 likely due to a new release of Python. We've find that the biggest gap
85 likely due to a new release of Python. We've find that the biggest gap
95 in unicode characters has reduces in size to be {size} characters
86 in unicode characters has reduces in size to be {size} characters
96 ({prct}), from {start}, to {stop}. In completer.py likely update to
87 ({prct}), from {start}, to {stop}. In completer.py likely update to
97
88
98 _UNICODE_RANGES = [(32, {start}), ({stop}, 0xe01f0)]
89 _UNICODE_RANGES = [(32, {start}), ({stop}, 0xe01f0)]
99
90
100 And update the assertion below to use
91 And update the assertion below to use
101
92
102 len_exp <= {len_exp}
93 len_exp <= {len_exp}
103 """
94 """
104 assert len_exp == len_test, message
95 assert len_exp == len_test, message
105
96
106 # fail if new unicode symbols have been added.
97 # fail if new unicode symbols have been added.
107 assert len_exp <= 138552, message
98 assert len_exp <= 138552, message
108
99
109
100
110 @contextmanager
101 @contextmanager
111 def greedy_completion():
102 def greedy_completion():
112 ip = get_ipython()
103 ip = get_ipython()
113 greedy_original = ip.Completer.greedy
104 greedy_original = ip.Completer.greedy
114 try:
105 try:
115 ip.Completer.greedy = True
106 ip.Completer.greedy = True
116 yield
107 yield
117 finally:
108 finally:
118 ip.Completer.greedy = greedy_original
109 ip.Completer.greedy = greedy_original
119
110
120
111
121 def test_protect_filename():
112 def test_protect_filename():
122 if sys.platform == "win32":
113 if sys.platform == "win32":
123 pairs = [
114 pairs = [
124 ("abc", "abc"),
115 ("abc", "abc"),
125 (" abc", '" abc"'),
116 (" abc", '" abc"'),
126 ("a bc", '"a bc"'),
117 ("a bc", '"a bc"'),
127 ("a bc", '"a bc"'),
118 ("a bc", '"a bc"'),
128 (" bc", '" bc"'),
119 (" bc", '" bc"'),
129 ]
120 ]
130 else:
121 else:
131 pairs = [
122 pairs = [
132 ("abc", "abc"),
123 ("abc", "abc"),
133 (" abc", r"\ abc"),
124 (" abc", r"\ abc"),
134 ("a bc", r"a\ bc"),
125 ("a bc", r"a\ bc"),
135 ("a bc", r"a\ \ bc"),
126 ("a bc", r"a\ \ bc"),
136 (" bc", r"\ \ bc"),
127 (" bc", r"\ \ bc"),
137 # On posix, we also protect parens and other special characters.
128 # On posix, we also protect parens and other special characters.
138 ("a(bc", r"a\(bc"),
129 ("a(bc", r"a\(bc"),
139 ("a)bc", r"a\)bc"),
130 ("a)bc", r"a\)bc"),
140 ("a( )bc", r"a\(\ \)bc"),
131 ("a( )bc", r"a\(\ \)bc"),
141 ("a[1]bc", r"a\[1\]bc"),
132 ("a[1]bc", r"a\[1\]bc"),
142 ("a{1}bc", r"a\{1\}bc"),
133 ("a{1}bc", r"a\{1\}bc"),
143 ("a#bc", r"a\#bc"),
134 ("a#bc", r"a\#bc"),
144 ("a?bc", r"a\?bc"),
135 ("a?bc", r"a\?bc"),
145 ("a=bc", r"a\=bc"),
136 ("a=bc", r"a\=bc"),
146 ("a\\bc", r"a\\bc"),
137 ("a\\bc", r"a\\bc"),
147 ("a|bc", r"a\|bc"),
138 ("a|bc", r"a\|bc"),
148 ("a;bc", r"a\;bc"),
139 ("a;bc", r"a\;bc"),
149 ("a:bc", r"a\:bc"),
140 ("a:bc", r"a\:bc"),
150 ("a'bc", r"a\'bc"),
141 ("a'bc", r"a\'bc"),
151 ("a*bc", r"a\*bc"),
142 ("a*bc", r"a\*bc"),
152 ('a"bc', r"a\"bc"),
143 ('a"bc', r"a\"bc"),
153 ("a^bc", r"a\^bc"),
144 ("a^bc", r"a\^bc"),
154 ("a&bc", r"a\&bc"),
145 ("a&bc", r"a\&bc"),
155 ]
146 ]
156 # run the actual tests
147 # run the actual tests
157 for s1, s2 in pairs:
148 for s1, s2 in pairs:
158 s1p = completer.protect_filename(s1)
149 s1p = completer.protect_filename(s1)
159 assert s1p == s2
150 assert s1p == s2
160
151
161
152
162 def check_line_split(splitter, test_specs):
153 def check_line_split(splitter, test_specs):
163 for part1, part2, split in test_specs:
154 for part1, part2, split in test_specs:
164 cursor_pos = len(part1)
155 cursor_pos = len(part1)
165 line = part1 + part2
156 line = part1 + part2
166 out = splitter.split_line(line, cursor_pos)
157 out = splitter.split_line(line, cursor_pos)
167 assert out == split
158 assert out == split
168
159
169
160
170 def test_line_split():
161 def test_line_split():
171 """Basic line splitter test with default specs."""
162 """Basic line splitter test with default specs."""
172 sp = completer.CompletionSplitter()
163 sp = completer.CompletionSplitter()
173 # The format of the test specs is: part1, part2, expected answer. Parts 1
164 # The format of the test specs is: part1, part2, expected answer. Parts 1
174 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
165 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
175 # was at the end of part1. So an empty part2 represents someone hitting
166 # was at the end of part1. So an empty part2 represents someone hitting
176 # tab at the end of the line, the most common case.
167 # tab at the end of the line, the most common case.
177 t = [
168 t = [
178 ("run some/scrip", "", "some/scrip"),
169 ("run some/scrip", "", "some/scrip"),
179 ("run scripts/er", "ror.py foo", "scripts/er"),
170 ("run scripts/er", "ror.py foo", "scripts/er"),
180 ("echo $HOM", "", "HOM"),
171 ("echo $HOM", "", "HOM"),
181 ("print sys.pa", "", "sys.pa"),
172 ("print sys.pa", "", "sys.pa"),
182 ("print(sys.pa", "", "sys.pa"),
173 ("print(sys.pa", "", "sys.pa"),
183 ("execfile('scripts/er", "", "scripts/er"),
174 ("execfile('scripts/er", "", "scripts/er"),
184 ("a[x.", "", "x."),
175 ("a[x.", "", "x."),
185 ("a[x.", "y", "x."),
176 ("a[x.", "y", "x."),
186 ('cd "some_file/', "", "some_file/"),
177 ('cd "some_file/', "", "some_file/"),
187 ]
178 ]
188 check_line_split(sp, t)
179 check_line_split(sp, t)
189 # Ensure splitting works OK with unicode by re-running the tests with
180 # Ensure splitting works OK with unicode by re-running the tests with
190 # all inputs turned into unicode
181 # all inputs turned into unicode
191 check_line_split(sp, [map(str, p) for p in t])
182 check_line_split(sp, [map(str, p) for p in t])
192
183
193
184
194 class NamedInstanceClass:
185 class NamedInstanceClass:
195 instances = {}
186 instances = {}
196
187
197 def __init__(self, name):
188 def __init__(self, name):
198 self.instances[name] = self
189 self.instances[name] = self
199
190
200 @classmethod
191 @classmethod
201 def _ipython_key_completions_(cls):
192 def _ipython_key_completions_(cls):
202 return cls.instances.keys()
193 return cls.instances.keys()
203
194
204
195
205 class KeyCompletable:
196 class KeyCompletable:
206 def __init__(self, things=()):
197 def __init__(self, things=()):
207 self.things = things
198 self.things = things
208
199
209 def _ipython_key_completions_(self):
200 def _ipython_key_completions_(self):
210 return list(self.things)
201 return list(self.things)
211
202
212
203
213 @pytest.mark.xfail(
214 sys.version_info >= (3, 11),
215 reason="parso does not support 3.11 yet",
216 raises=NotImplementedError,
217 )
218 class TestCompleter(unittest.TestCase):
204 class TestCompleter(unittest.TestCase):
219 def setUp(self):
205 def setUp(self):
220 """
206 """
221 We want to silence all PendingDeprecationWarning when testing the completer
207 We want to silence all PendingDeprecationWarning when testing the completer
222 """
208 """
223 self._assertwarns = self.assertWarns(PendingDeprecationWarning)
209 self._assertwarns = self.assertWarns(PendingDeprecationWarning)
224 self._assertwarns.__enter__()
210 self._assertwarns.__enter__()
225
211
226 def tearDown(self):
212 def tearDown(self):
227 try:
213 try:
228 self._assertwarns.__exit__(None, None, None)
214 self._assertwarns.__exit__(None, None, None)
229 except AssertionError:
215 except AssertionError:
230 pass
216 pass
231
217
232 def test_custom_completion_error(self):
218 def test_custom_completion_error(self):
233 """Test that errors from custom attribute completers are silenced."""
219 """Test that errors from custom attribute completers are silenced."""
234 ip = get_ipython()
220 ip = get_ipython()
235
221
236 class A:
222 class A:
237 pass
223 pass
238
224
239 ip.user_ns["x"] = A()
225 ip.user_ns["x"] = A()
240
226
241 @complete_object.register(A)
227 @complete_object.register(A)
242 def complete_A(a, existing_completions):
228 def complete_A(a, existing_completions):
243 raise TypeError("this should be silenced")
229 raise TypeError("this should be silenced")
244
230
245 ip.complete("x.")
231 ip.complete("x.")
246
232
247 def test_custom_completion_ordering(self):
233 def test_custom_completion_ordering(self):
248 """Test that errors from custom attribute completers are silenced."""
234 """Test that errors from custom attribute completers are silenced."""
249 ip = get_ipython()
235 ip = get_ipython()
250
236
251 _, matches = ip.complete('in')
237 _, matches = ip.complete('in')
252 assert matches.index('input') < matches.index('int')
238 assert matches.index('input') < matches.index('int')
253
239
254 def complete_example(a):
240 def complete_example(a):
255 return ['example2', 'example1']
241 return ['example2', 'example1']
256
242
257 ip.Completer.custom_completers.add_re('ex*', complete_example)
243 ip.Completer.custom_completers.add_re('ex*', complete_example)
258 _, matches = ip.complete('ex')
244 _, matches = ip.complete('ex')
259 assert matches.index('example2') < matches.index('example1')
245 assert matches.index('example2') < matches.index('example1')
260
246
261 def test_unicode_completions(self):
247 def test_unicode_completions(self):
262 ip = get_ipython()
248 ip = get_ipython()
263 # Some strings that trigger different types of completion. Check them both
249 # Some strings that trigger different types of completion. Check them both
264 # in str and unicode forms
250 # in str and unicode forms
265 s = ["ru", "%ru", "cd /", "floa", "float(x)/"]
251 s = ["ru", "%ru", "cd /", "floa", "float(x)/"]
266 for t in s + list(map(str, s)):
252 for t in s + list(map(str, s)):
267 # We don't need to check exact completion values (they may change
253 # We don't need to check exact completion values (they may change
268 # depending on the state of the namespace, but at least no exceptions
254 # depending on the state of the namespace, but at least no exceptions
269 # should be thrown and the return value should be a pair of text, list
255 # should be thrown and the return value should be a pair of text, list
270 # values.
256 # values.
271 text, matches = ip.complete(t)
257 text, matches = ip.complete(t)
272 self.assertIsInstance(text, str)
258 self.assertIsInstance(text, str)
273 self.assertIsInstance(matches, list)
259 self.assertIsInstance(matches, list)
274
260
275 def test_latex_completions(self):
261 def test_latex_completions(self):
276 from IPython.core.latex_symbols import latex_symbols
262 from IPython.core.latex_symbols import latex_symbols
277 import random
263 import random
278
264
279 ip = get_ipython()
265 ip = get_ipython()
280 # Test some random unicode symbols
266 # Test some random unicode symbols
281 keys = random.sample(sorted(latex_symbols), 10)
267 keys = random.sample(sorted(latex_symbols), 10)
282 for k in keys:
268 for k in keys:
283 text, matches = ip.complete(k)
269 text, matches = ip.complete(k)
284 self.assertEqual(text, k)
270 self.assertEqual(text, k)
285 self.assertEqual(matches, [latex_symbols[k]])
271 self.assertEqual(matches, [latex_symbols[k]])
286 # Test a more complex line
272 # Test a more complex line
287 text, matches = ip.complete("print(\\alpha")
273 text, matches = ip.complete("print(\\alpha")
288 self.assertEqual(text, "\\alpha")
274 self.assertEqual(text, "\\alpha")
289 self.assertEqual(matches[0], latex_symbols["\\alpha"])
275 self.assertEqual(matches[0], latex_symbols["\\alpha"])
290 # Test multiple matching latex symbols
276 # Test multiple matching latex symbols
291 text, matches = ip.complete("\\al")
277 text, matches = ip.complete("\\al")
292 self.assertIn("\\alpha", matches)
278 self.assertIn("\\alpha", matches)
293 self.assertIn("\\aleph", matches)
279 self.assertIn("\\aleph", matches)
294
280
295 def test_latex_no_results(self):
281 def test_latex_no_results(self):
296 """
282 """
297 forward latex should really return nothing in either field if nothing is found.
283 forward latex should really return nothing in either field if nothing is found.
298 """
284 """
299 ip = get_ipython()
285 ip = get_ipython()
300 text, matches = ip.Completer.latex_matches("\\really_i_should_match_nothing")
286 text, matches = ip.Completer.latex_matches("\\really_i_should_match_nothing")
301 self.assertEqual(text, "")
287 self.assertEqual(text, "")
302 self.assertEqual(matches, ())
288 self.assertEqual(matches, ())
303
289
304 def test_back_latex_completion(self):
290 def test_back_latex_completion(self):
305 ip = get_ipython()
291 ip = get_ipython()
306
292
307 # do not return more than 1 matches for \beta, only the latex one.
293 # do not return more than 1 matches for \beta, only the latex one.
308 name, matches = ip.complete("\\Ξ²")
294 name, matches = ip.complete("\\Ξ²")
309 self.assertEqual(matches, ["\\beta"])
295 self.assertEqual(matches, ["\\beta"])
310
296
311 def test_back_unicode_completion(self):
297 def test_back_unicode_completion(self):
312 ip = get_ipython()
298 ip = get_ipython()
313
299
314 name, matches = ip.complete("\\β…€")
300 name, matches = ip.complete("\\β…€")
315 self.assertEqual(matches, ("\\ROMAN NUMERAL FIVE",))
301 self.assertEqual(matches, ("\\ROMAN NUMERAL FIVE",))
316
302
317 def test_forward_unicode_completion(self):
303 def test_forward_unicode_completion(self):
318 ip = get_ipython()
304 ip = get_ipython()
319
305
320 name, matches = ip.complete("\\ROMAN NUMERAL FIVE")
306 name, matches = ip.complete("\\ROMAN NUMERAL FIVE")
321 self.assertEqual(matches, ["β…€"]) # This is not a V
307 self.assertEqual(matches, ["β…€"]) # This is not a V
322 self.assertEqual(matches, ["\u2164"]) # same as above but explicit.
308 self.assertEqual(matches, ["\u2164"]) # same as above but explicit.
323
309
324 def test_delim_setting(self):
310 def test_delim_setting(self):
325 sp = completer.CompletionSplitter()
311 sp = completer.CompletionSplitter()
326 sp.delims = " "
312 sp.delims = " "
327 self.assertEqual(sp.delims, " ")
313 self.assertEqual(sp.delims, " ")
328 self.assertEqual(sp._delim_expr, r"[\ ]")
314 self.assertEqual(sp._delim_expr, r"[\ ]")
329
315
330 def test_spaces(self):
316 def test_spaces(self):
331 """Test with only spaces as split chars."""
317 """Test with only spaces as split chars."""
332 sp = completer.CompletionSplitter()
318 sp = completer.CompletionSplitter()
333 sp.delims = " "
319 sp.delims = " "
334 t = [("foo", "", "foo"), ("run foo", "", "foo"), ("run foo", "bar", "foo")]
320 t = [("foo", "", "foo"), ("run foo", "", "foo"), ("run foo", "bar", "foo")]
335 check_line_split(sp, t)
321 check_line_split(sp, t)
336
322
337 def test_has_open_quotes1(self):
323 def test_has_open_quotes1(self):
338 for s in ["'", "'''", "'hi' '"]:
324 for s in ["'", "'''", "'hi' '"]:
339 self.assertEqual(completer.has_open_quotes(s), "'")
325 self.assertEqual(completer.has_open_quotes(s), "'")
340
326
341 def test_has_open_quotes2(self):
327 def test_has_open_quotes2(self):
342 for s in ['"', '"""', '"hi" "']:
328 for s in ['"', '"""', '"hi" "']:
343 self.assertEqual(completer.has_open_quotes(s), '"')
329 self.assertEqual(completer.has_open_quotes(s), '"')
344
330
345 def test_has_open_quotes3(self):
331 def test_has_open_quotes3(self):
346 for s in ["''", "''' '''", "'hi' 'ipython'"]:
332 for s in ["''", "''' '''", "'hi' 'ipython'"]:
347 self.assertFalse(completer.has_open_quotes(s))
333 self.assertFalse(completer.has_open_quotes(s))
348
334
349 def test_has_open_quotes4(self):
335 def test_has_open_quotes4(self):
350 for s in ['""', '""" """', '"hi" "ipython"']:
336 for s in ['""', '""" """', '"hi" "ipython"']:
351 self.assertFalse(completer.has_open_quotes(s))
337 self.assertFalse(completer.has_open_quotes(s))
352
338
353 @pytest.mark.xfail(
339 @pytest.mark.xfail(
354 sys.platform == "win32", reason="abspath completions fail on Windows"
340 sys.platform == "win32", reason="abspath completions fail on Windows"
355 )
341 )
356 def test_abspath_file_completions(self):
342 def test_abspath_file_completions(self):
357 ip = get_ipython()
343 ip = get_ipython()
358 with TemporaryDirectory() as tmpdir:
344 with TemporaryDirectory() as tmpdir:
359 prefix = os.path.join(tmpdir, "foo")
345 prefix = os.path.join(tmpdir, "foo")
360 suffixes = ["1", "2"]
346 suffixes = ["1", "2"]
361 names = [prefix + s for s in suffixes]
347 names = [prefix + s for s in suffixes]
362 for n in names:
348 for n in names:
363 open(n, "w").close()
349 open(n, "w").close()
364
350
365 # Check simple completion
351 # Check simple completion
366 c = ip.complete(prefix)[1]
352 c = ip.complete(prefix)[1]
367 self.assertEqual(c, names)
353 self.assertEqual(c, names)
368
354
369 # Now check with a function call
355 # Now check with a function call
370 cmd = 'a = f("%s' % prefix
356 cmd = 'a = f("%s' % prefix
371 c = ip.complete(prefix, cmd)[1]
357 c = ip.complete(prefix, cmd)[1]
372 comp = [prefix + s for s in suffixes]
358 comp = [prefix + s for s in suffixes]
373 self.assertEqual(c, comp)
359 self.assertEqual(c, comp)
374
360
375 def test_local_file_completions(self):
361 def test_local_file_completions(self):
376 ip = get_ipython()
362 ip = get_ipython()
377 with TemporaryWorkingDirectory():
363 with TemporaryWorkingDirectory():
378 prefix = "./foo"
364 prefix = "./foo"
379 suffixes = ["1", "2"]
365 suffixes = ["1", "2"]
380 names = [prefix + s for s in suffixes]
366 names = [prefix + s for s in suffixes]
381 for n in names:
367 for n in names:
382 open(n, "w").close()
368 open(n, "w").close()
383
369
384 # Check simple completion
370 # Check simple completion
385 c = ip.complete(prefix)[1]
371 c = ip.complete(prefix)[1]
386 self.assertEqual(c, names)
372 self.assertEqual(c, names)
387
373
388 # Now check with a function call
374 # Now check with a function call
389 cmd = 'a = f("%s' % prefix
375 cmd = 'a = f("%s' % prefix
390 c = ip.complete(prefix, cmd)[1]
376 c = ip.complete(prefix, cmd)[1]
391 comp = {prefix + s for s in suffixes}
377 comp = {prefix + s for s in suffixes}
392 self.assertTrue(comp.issubset(set(c)))
378 self.assertTrue(comp.issubset(set(c)))
393
379
394 def test_quoted_file_completions(self):
380 def test_quoted_file_completions(self):
395 ip = get_ipython()
381 ip = get_ipython()
396 with TemporaryWorkingDirectory():
382 with TemporaryWorkingDirectory():
397 name = "foo'bar"
383 name = "foo'bar"
398 open(name, "w").close()
384 open(name, "w").close()
399
385
400 # Don't escape Windows
386 # Don't escape Windows
401 escaped = name if sys.platform == "win32" else "foo\\'bar"
387 escaped = name if sys.platform == "win32" else "foo\\'bar"
402
388
403 # Single quote matches embedded single quote
389 # Single quote matches embedded single quote
404 text = "open('foo"
390 text = "open('foo"
405 c = ip.Completer._complete(
391 c = ip.Completer._complete(
406 cursor_line=0, cursor_pos=len(text), full_text=text
392 cursor_line=0, cursor_pos=len(text), full_text=text
407 )[1]
393 )[1]
408 self.assertEqual(c, [escaped])
394 self.assertEqual(c, [escaped])
409
395
410 # Double quote requires no escape
396 # Double quote requires no escape
411 text = 'open("foo'
397 text = 'open("foo'
412 c = ip.Completer._complete(
398 c = ip.Completer._complete(
413 cursor_line=0, cursor_pos=len(text), full_text=text
399 cursor_line=0, cursor_pos=len(text), full_text=text
414 )[1]
400 )[1]
415 self.assertEqual(c, [name])
401 self.assertEqual(c, [name])
416
402
417 # No quote requires an escape
403 # No quote requires an escape
418 text = "%ls foo"
404 text = "%ls foo"
419 c = ip.Completer._complete(
405 c = ip.Completer._complete(
420 cursor_line=0, cursor_pos=len(text), full_text=text
406 cursor_line=0, cursor_pos=len(text), full_text=text
421 )[1]
407 )[1]
422 self.assertEqual(c, [escaped])
408 self.assertEqual(c, [escaped])
423
409
424 def test_all_completions_dups(self):
410 def test_all_completions_dups(self):
425 """
411 """
426 Make sure the output of `IPCompleter.all_completions` does not have
412 Make sure the output of `IPCompleter.all_completions` does not have
427 duplicated prefixes.
413 duplicated prefixes.
428 """
414 """
429 ip = get_ipython()
415 ip = get_ipython()
430 c = ip.Completer
416 c = ip.Completer
431 ip.ex("class TestClass():\n\ta=1\n\ta1=2")
417 ip.ex("class TestClass():\n\ta=1\n\ta1=2")
432 for jedi_status in [True, False]:
418 for jedi_status in [True, False]:
433 with provisionalcompleter():
419 with provisionalcompleter():
434 ip.Completer.use_jedi = jedi_status
420 ip.Completer.use_jedi = jedi_status
435 matches = c.all_completions("TestCl")
421 matches = c.all_completions("TestCl")
436 assert matches == ['TestClass'], jedi_status
422 assert matches == ['TestClass'], jedi_status
437 matches = c.all_completions("TestClass.")
423 matches = c.all_completions("TestClass.")
438 if jedi_status and jedi_issue:
439 continue
440 assert len(matches) > 2, jedi_status
424 assert len(matches) > 2, jedi_status
441 matches = c.all_completions("TestClass.a")
425 matches = c.all_completions("TestClass.a")
442 assert matches == ['TestClass.a', 'TestClass.a1'], jedi_status
426 assert matches == ['TestClass.a', 'TestClass.a1'], jedi_status
443
427
444 def test_jedi(self):
428 def test_jedi(self):
445 """
429 """
446 A couple of issue we had with Jedi
430 A couple of issue we had with Jedi
447 """
431 """
448 ip = get_ipython()
432 ip = get_ipython()
449
433
450 def _test_complete(reason, s, comp, start=None, end=None):
434 def _test_complete(reason, s, comp, start=None, end=None):
451 l = len(s)
435 l = len(s)
452 start = start if start is not None else l
436 start = start if start is not None else l
453 end = end if end is not None else l
437 end = end if end is not None else l
454 with provisionalcompleter():
438 with provisionalcompleter():
455 ip.Completer.use_jedi = True
439 ip.Completer.use_jedi = True
456 completions = set(ip.Completer.completions(s, l))
440 completions = set(ip.Completer.completions(s, l))
457 ip.Completer.use_jedi = False
441 ip.Completer.use_jedi = False
458 assert Completion(start, end, comp) in completions, reason
442 assert Completion(start, end, comp) in completions, reason
459
443
460 def _test_not_complete(reason, s, comp):
444 def _test_not_complete(reason, s, comp):
461 l = len(s)
445 l = len(s)
462 with provisionalcompleter():
446 with provisionalcompleter():
463 ip.Completer.use_jedi = True
447 ip.Completer.use_jedi = True
464 completions = set(ip.Completer.completions(s, l))
448 completions = set(ip.Completer.completions(s, l))
465 ip.Completer.use_jedi = False
449 ip.Completer.use_jedi = False
466 assert Completion(l, l, comp) not in completions, reason
450 assert Completion(l, l, comp) not in completions, reason
467
451
468 import jedi
452 import jedi
469
453
470 jedi_version = tuple(int(i) for i in jedi.__version__.split(".")[:3])
454 jedi_version = tuple(int(i) for i in jedi.__version__.split(".")[:3])
471 if jedi_version > (0, 10):
455 if jedi_version > (0, 10):
472 _test_complete("jedi >0.9 should complete and not crash", "a=1;a.", "real")
456 _test_complete("jedi >0.9 should complete and not crash", "a=1;a.", "real")
473 _test_complete("can infer first argument", 'a=(1,"foo");a[0].', "real")
457 _test_complete("can infer first argument", 'a=(1,"foo");a[0].', "real")
474 _test_complete("can infer second argument", 'a=(1,"foo");a[1].', "capitalize")
458 _test_complete("can infer second argument", 'a=(1,"foo");a[1].', "capitalize")
475 _test_complete("cover duplicate completions", "im", "import", 0, 2)
459 _test_complete("cover duplicate completions", "im", "import", 0, 2)
476
460
477 _test_not_complete("does not mix types", 'a=(1,"foo");a[0].', "capitalize")
461 _test_not_complete("does not mix types", 'a=(1,"foo");a[0].', "capitalize")
478
462
479 def test_completion_have_signature(self):
463 def test_completion_have_signature(self):
480 """
464 """
481 Lets make sure jedi is capable of pulling out the signature of the function we are completing.
465 Lets make sure jedi is capable of pulling out the signature of the function we are completing.
482 """
466 """
483 ip = get_ipython()
467 ip = get_ipython()
484 with provisionalcompleter():
468 with provisionalcompleter():
485 ip.Completer.use_jedi = True
469 ip.Completer.use_jedi = True
486 completions = ip.Completer.completions("ope", 3)
470 completions = ip.Completer.completions("ope", 3)
487 c = next(completions) # should be `open`
471 c = next(completions) # should be `open`
488 ip.Completer.use_jedi = False
472 ip.Completer.use_jedi = False
489 assert "file" in c.signature, "Signature of function was not found by completer"
473 assert "file" in c.signature, "Signature of function was not found by completer"
490 assert (
474 assert (
491 "encoding" in c.signature
475 "encoding" in c.signature
492 ), "Signature of function was not found by completer"
476 ), "Signature of function was not found by completer"
493
477
494 @pytest.mark.xfail(jedi_issue, reason="Known failure on jedi<=0.18.0")
495 def test_deduplicate_completions(self):
478 def test_deduplicate_completions(self):
496 """
479 """
497 Test that completions are correctly deduplicated (even if ranges are not the same)
480 Test that completions are correctly deduplicated (even if ranges are not the same)
498 """
481 """
499 ip = get_ipython()
482 ip = get_ipython()
500 ip.ex(
483 ip.ex(
501 textwrap.dedent(
484 textwrap.dedent(
502 """
485 """
503 class Z:
486 class Z:
504 zoo = 1
487 zoo = 1
505 """
488 """
506 )
489 )
507 )
490 )
508 with provisionalcompleter():
491 with provisionalcompleter():
509 ip.Completer.use_jedi = True
492 ip.Completer.use_jedi = True
510 l = list(
493 l = list(
511 _deduplicate_completions("Z.z", ip.Completer.completions("Z.z", 3))
494 _deduplicate_completions("Z.z", ip.Completer.completions("Z.z", 3))
512 )
495 )
513 ip.Completer.use_jedi = False
496 ip.Completer.use_jedi = False
514
497
515 assert len(l) == 1, "Completions (Z.z<tab>) correctly deduplicate: %s " % l
498 assert len(l) == 1, "Completions (Z.z<tab>) correctly deduplicate: %s " % l
516 assert l[0].text == "zoo" # and not `it.accumulate`
499 assert l[0].text == "zoo" # and not `it.accumulate`
517
500
518 def test_greedy_completions(self):
501 def test_greedy_completions(self):
519 """
502 """
520 Test the capability of the Greedy completer.
503 Test the capability of the Greedy completer.
521
504
522 Most of the test here does not really show off the greedy completer, for proof
505 Most of the test here does not really show off the greedy completer, for proof
523 each of the text below now pass with Jedi. The greedy completer is capable of more.
506 each of the text below now pass with Jedi. The greedy completer is capable of more.
524
507
525 See the :any:`test_dict_key_completion_contexts`
508 See the :any:`test_dict_key_completion_contexts`
526
509
527 """
510 """
528 ip = get_ipython()
511 ip = get_ipython()
529 ip.ex("a=list(range(5))")
512 ip.ex("a=list(range(5))")
530 _, c = ip.complete(".", line="a[0].")
513 _, c = ip.complete(".", line="a[0].")
531 self.assertFalse(".real" in c, "Shouldn't have completed on a[0]: %s" % c)
514 self.assertFalse(".real" in c, "Shouldn't have completed on a[0]: %s" % c)
532
515
533 def _(line, cursor_pos, expect, message, completion):
516 def _(line, cursor_pos, expect, message, completion):
534 with greedy_completion(), provisionalcompleter():
517 with greedy_completion(), provisionalcompleter():
535 ip.Completer.use_jedi = False
518 ip.Completer.use_jedi = False
536 _, c = ip.complete(".", line=line, cursor_pos=cursor_pos)
519 _, c = ip.complete(".", line=line, cursor_pos=cursor_pos)
537 self.assertIn(expect, c, message % c)
520 self.assertIn(expect, c, message % c)
538
521
539 ip.Completer.use_jedi = True
522 ip.Completer.use_jedi = True
540 with provisionalcompleter():
523 with provisionalcompleter():
541 completions = ip.Completer.completions(line, cursor_pos)
524 completions = ip.Completer.completions(line, cursor_pos)
542 self.assertIn(completion, completions)
525 self.assertIn(completion, completions)
543
526
544 with provisionalcompleter():
527 with provisionalcompleter():
545 _(
528 _(
546 "a[0].",
529 "a[0].",
547 5,
530 5,
548 "a[0].real",
531 "a[0].real",
549 "Should have completed on a[0].: %s",
532 "Should have completed on a[0].: %s",
550 Completion(5, 5, "real"),
533 Completion(5, 5, "real"),
551 )
534 )
552 _(
535 _(
553 "a[0].r",
536 "a[0].r",
554 6,
537 6,
555 "a[0].real",
538 "a[0].real",
556 "Should have completed on a[0].r: %s",
539 "Should have completed on a[0].r: %s",
557 Completion(5, 6, "real"),
540 Completion(5, 6, "real"),
558 )
541 )
559
542
560 _(
543 _(
561 "a[0].from_",
544 "a[0].from_",
562 10,
545 10,
563 "a[0].from_bytes",
546 "a[0].from_bytes",
564 "Should have completed on a[0].from_: %s",
547 "Should have completed on a[0].from_: %s",
565 Completion(5, 10, "from_bytes"),
548 Completion(5, 10, "from_bytes"),
566 )
549 )
567
550
568 def test_omit__names(self):
551 def test_omit__names(self):
569 # also happens to test IPCompleter as a configurable
552 # also happens to test IPCompleter as a configurable
570 ip = get_ipython()
553 ip = get_ipython()
571 ip._hidden_attr = 1
554 ip._hidden_attr = 1
572 ip._x = {}
555 ip._x = {}
573 c = ip.Completer
556 c = ip.Completer
574 ip.ex("ip=get_ipython()")
557 ip.ex("ip=get_ipython()")
575 cfg = Config()
558 cfg = Config()
576 cfg.IPCompleter.omit__names = 0
559 cfg.IPCompleter.omit__names = 0
577 c.update_config(cfg)
560 c.update_config(cfg)
578 with provisionalcompleter():
561 with provisionalcompleter():
579 c.use_jedi = False
562 c.use_jedi = False
580 s, matches = c.complete("ip.")
563 s, matches = c.complete("ip.")
581 self.assertIn("ip.__str__", matches)
564 self.assertIn("ip.__str__", matches)
582 self.assertIn("ip._hidden_attr", matches)
565 self.assertIn("ip._hidden_attr", matches)
583
566
584 # c.use_jedi = True
567 # c.use_jedi = True
585 # completions = set(c.completions('ip.', 3))
568 # completions = set(c.completions('ip.', 3))
586 # self.assertIn(Completion(3, 3, '__str__'), completions)
569 # self.assertIn(Completion(3, 3, '__str__'), completions)
587 # self.assertIn(Completion(3,3, "_hidden_attr"), completions)
570 # self.assertIn(Completion(3,3, "_hidden_attr"), completions)
588
571
589 cfg = Config()
572 cfg = Config()
590 cfg.IPCompleter.omit__names = 1
573 cfg.IPCompleter.omit__names = 1
591 c.update_config(cfg)
574 c.update_config(cfg)
592 with provisionalcompleter():
575 with provisionalcompleter():
593 c.use_jedi = False
576 c.use_jedi = False
594 s, matches = c.complete("ip.")
577 s, matches = c.complete("ip.")
595 self.assertNotIn("ip.__str__", matches)
578 self.assertNotIn("ip.__str__", matches)
596 # self.assertIn('ip._hidden_attr', matches)
579 # self.assertIn('ip._hidden_attr', matches)
597
580
598 # c.use_jedi = True
581 # c.use_jedi = True
599 # completions = set(c.completions('ip.', 3))
582 # completions = set(c.completions('ip.', 3))
600 # self.assertNotIn(Completion(3,3,'__str__'), completions)
583 # self.assertNotIn(Completion(3,3,'__str__'), completions)
601 # self.assertIn(Completion(3,3, "_hidden_attr"), completions)
584 # self.assertIn(Completion(3,3, "_hidden_attr"), completions)
602
585
603 cfg = Config()
586 cfg = Config()
604 cfg.IPCompleter.omit__names = 2
587 cfg.IPCompleter.omit__names = 2
605 c.update_config(cfg)
588 c.update_config(cfg)
606 with provisionalcompleter():
589 with provisionalcompleter():
607 c.use_jedi = False
590 c.use_jedi = False
608 s, matches = c.complete("ip.")
591 s, matches = c.complete("ip.")
609 self.assertNotIn("ip.__str__", matches)
592 self.assertNotIn("ip.__str__", matches)
610 self.assertNotIn("ip._hidden_attr", matches)
593 self.assertNotIn("ip._hidden_attr", matches)
611
594
612 # c.use_jedi = True
595 # c.use_jedi = True
613 # completions = set(c.completions('ip.', 3))
596 # completions = set(c.completions('ip.', 3))
614 # self.assertNotIn(Completion(3,3,'__str__'), completions)
597 # self.assertNotIn(Completion(3,3,'__str__'), completions)
615 # self.assertNotIn(Completion(3,3, "_hidden_attr"), completions)
598 # self.assertNotIn(Completion(3,3, "_hidden_attr"), completions)
616
599
617 with provisionalcompleter():
600 with provisionalcompleter():
618 c.use_jedi = False
601 c.use_jedi = False
619 s, matches = c.complete("ip._x.")
602 s, matches = c.complete("ip._x.")
620 self.assertIn("ip._x.keys", matches)
603 self.assertIn("ip._x.keys", matches)
621
604
622 # c.use_jedi = True
605 # c.use_jedi = True
623 # completions = set(c.completions('ip._x.', 6))
606 # completions = set(c.completions('ip._x.', 6))
624 # self.assertIn(Completion(6,6, "keys"), completions)
607 # self.assertIn(Completion(6,6, "keys"), completions)
625
608
626 del ip._hidden_attr
609 del ip._hidden_attr
627 del ip._x
610 del ip._x
628
611
629 def test_limit_to__all__False_ok(self):
612 def test_limit_to__all__False_ok(self):
630 """
613 """
631 Limit to all is deprecated, once we remove it this test can go away.
614 Limit to all is deprecated, once we remove it this test can go away.
632 """
615 """
633 ip = get_ipython()
616 ip = get_ipython()
634 c = ip.Completer
617 c = ip.Completer
635 c.use_jedi = False
618 c.use_jedi = False
636 ip.ex("class D: x=24")
619 ip.ex("class D: x=24")
637 ip.ex("d=D()")
620 ip.ex("d=D()")
638 cfg = Config()
621 cfg = Config()
639 cfg.IPCompleter.limit_to__all__ = False
622 cfg.IPCompleter.limit_to__all__ = False
640 c.update_config(cfg)
623 c.update_config(cfg)
641 s, matches = c.complete("d.")
624 s, matches = c.complete("d.")
642 self.assertIn("d.x", matches)
625 self.assertIn("d.x", matches)
643
626
644 def test_get__all__entries_ok(self):
627 def test_get__all__entries_ok(self):
645 class A:
628 class A:
646 __all__ = ["x", 1]
629 __all__ = ["x", 1]
647
630
648 words = completer.get__all__entries(A())
631 words = completer.get__all__entries(A())
649 self.assertEqual(words, ["x"])
632 self.assertEqual(words, ["x"])
650
633
651 def test_get__all__entries_no__all__ok(self):
634 def test_get__all__entries_no__all__ok(self):
652 class A:
635 class A:
653 pass
636 pass
654
637
655 words = completer.get__all__entries(A())
638 words = completer.get__all__entries(A())
656 self.assertEqual(words, [])
639 self.assertEqual(words, [])
657
640
658 def test_func_kw_completions(self):
641 def test_func_kw_completions(self):
659 ip = get_ipython()
642 ip = get_ipython()
660 c = ip.Completer
643 c = ip.Completer
661 c.use_jedi = False
644 c.use_jedi = False
662 ip.ex("def myfunc(a=1,b=2): return a+b")
645 ip.ex("def myfunc(a=1,b=2): return a+b")
663 s, matches = c.complete(None, "myfunc(1,b")
646 s, matches = c.complete(None, "myfunc(1,b")
664 self.assertIn("b=", matches)
647 self.assertIn("b=", matches)
665 # Simulate completing with cursor right after b (pos==10):
648 # Simulate completing with cursor right after b (pos==10):
666 s, matches = c.complete(None, "myfunc(1,b)", 10)
649 s, matches = c.complete(None, "myfunc(1,b)", 10)
667 self.assertIn("b=", matches)
650 self.assertIn("b=", matches)
668 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
651 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
669 self.assertIn("b=", matches)
652 self.assertIn("b=", matches)
670 # builtin function
653 # builtin function
671 s, matches = c.complete(None, "min(k, k")
654 s, matches = c.complete(None, "min(k, k")
672 self.assertIn("key=", matches)
655 self.assertIn("key=", matches)
673
656
674 def test_default_arguments_from_docstring(self):
657 def test_default_arguments_from_docstring(self):
675 ip = get_ipython()
658 ip = get_ipython()
676 c = ip.Completer
659 c = ip.Completer
677 kwd = c._default_arguments_from_docstring("min(iterable[, key=func]) -> value")
660 kwd = c._default_arguments_from_docstring("min(iterable[, key=func]) -> value")
678 self.assertEqual(kwd, ["key"])
661 self.assertEqual(kwd, ["key"])
679 # with cython type etc
662 # with cython type etc
680 kwd = c._default_arguments_from_docstring(
663 kwd = c._default_arguments_from_docstring(
681 "Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
664 "Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
682 )
665 )
683 self.assertEqual(kwd, ["ncall", "resume", "nsplit"])
666 self.assertEqual(kwd, ["ncall", "resume", "nsplit"])
684 # white spaces
667 # white spaces
685 kwd = c._default_arguments_from_docstring(
668 kwd = c._default_arguments_from_docstring(
686 "\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
669 "\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
687 )
670 )
688 self.assertEqual(kwd, ["ncall", "resume", "nsplit"])
671 self.assertEqual(kwd, ["ncall", "resume", "nsplit"])
689
672
690 def test_line_magics(self):
673 def test_line_magics(self):
691 ip = get_ipython()
674 ip = get_ipython()
692 c = ip.Completer
675 c = ip.Completer
693 s, matches = c.complete(None, "lsmag")
676 s, matches = c.complete(None, "lsmag")
694 self.assertIn("%lsmagic", matches)
677 self.assertIn("%lsmagic", matches)
695 s, matches = c.complete(None, "%lsmag")
678 s, matches = c.complete(None, "%lsmag")
696 self.assertIn("%lsmagic", matches)
679 self.assertIn("%lsmagic", matches)
697
680
698 def test_cell_magics(self):
681 def test_cell_magics(self):
699 from IPython.core.magic import register_cell_magic
682 from IPython.core.magic import register_cell_magic
700
683
701 @register_cell_magic
684 @register_cell_magic
702 def _foo_cellm(line, cell):
685 def _foo_cellm(line, cell):
703 pass
686 pass
704
687
705 ip = get_ipython()
688 ip = get_ipython()
706 c = ip.Completer
689 c = ip.Completer
707
690
708 s, matches = c.complete(None, "_foo_ce")
691 s, matches = c.complete(None, "_foo_ce")
709 self.assertIn("%%_foo_cellm", matches)
692 self.assertIn("%%_foo_cellm", matches)
710 s, matches = c.complete(None, "%%_foo_ce")
693 s, matches = c.complete(None, "%%_foo_ce")
711 self.assertIn("%%_foo_cellm", matches)
694 self.assertIn("%%_foo_cellm", matches)
712
695
713 def test_line_cell_magics(self):
696 def test_line_cell_magics(self):
714 from IPython.core.magic import register_line_cell_magic
697 from IPython.core.magic import register_line_cell_magic
715
698
716 @register_line_cell_magic
699 @register_line_cell_magic
717 def _bar_cellm(line, cell):
700 def _bar_cellm(line, cell):
718 pass
701 pass
719
702
720 ip = get_ipython()
703 ip = get_ipython()
721 c = ip.Completer
704 c = ip.Completer
722
705
723 # The policy here is trickier, see comments in completion code. The
706 # The policy here is trickier, see comments in completion code. The
724 # returned values depend on whether the user passes %% or not explicitly,
707 # returned values depend on whether the user passes %% or not explicitly,
725 # and this will show a difference if the same name is both a line and cell
708 # and this will show a difference if the same name is both a line and cell
726 # magic.
709 # magic.
727 s, matches = c.complete(None, "_bar_ce")
710 s, matches = c.complete(None, "_bar_ce")
728 self.assertIn("%_bar_cellm", matches)
711 self.assertIn("%_bar_cellm", matches)
729 self.assertIn("%%_bar_cellm", matches)
712 self.assertIn("%%_bar_cellm", matches)
730 s, matches = c.complete(None, "%_bar_ce")
713 s, matches = c.complete(None, "%_bar_ce")
731 self.assertIn("%_bar_cellm", matches)
714 self.assertIn("%_bar_cellm", matches)
732 self.assertIn("%%_bar_cellm", matches)
715 self.assertIn("%%_bar_cellm", matches)
733 s, matches = c.complete(None, "%%_bar_ce")
716 s, matches = c.complete(None, "%%_bar_ce")
734 self.assertNotIn("%_bar_cellm", matches)
717 self.assertNotIn("%_bar_cellm", matches)
735 self.assertIn("%%_bar_cellm", matches)
718 self.assertIn("%%_bar_cellm", matches)
736
719
737 def test_magic_completion_order(self):
720 def test_magic_completion_order(self):
738 ip = get_ipython()
721 ip = get_ipython()
739 c = ip.Completer
722 c = ip.Completer
740
723
741 # Test ordering of line and cell magics.
724 # Test ordering of line and cell magics.
742 text, matches = c.complete("timeit")
725 text, matches = c.complete("timeit")
743 self.assertEqual(matches, ["%timeit", "%%timeit"])
726 self.assertEqual(matches, ["%timeit", "%%timeit"])
744
727
745 def test_magic_completion_shadowing(self):
728 def test_magic_completion_shadowing(self):
746 ip = get_ipython()
729 ip = get_ipython()
747 c = ip.Completer
730 c = ip.Completer
748 c.use_jedi = False
731 c.use_jedi = False
749
732
750 # Before importing matplotlib, %matplotlib magic should be the only option.
733 # Before importing matplotlib, %matplotlib magic should be the only option.
751 text, matches = c.complete("mat")
734 text, matches = c.complete("mat")
752 self.assertEqual(matches, ["%matplotlib"])
735 self.assertEqual(matches, ["%matplotlib"])
753
736
754 # The newly introduced name should shadow the magic.
737 # The newly introduced name should shadow the magic.
755 ip.run_cell("matplotlib = 1")
738 ip.run_cell("matplotlib = 1")
756 text, matches = c.complete("mat")
739 text, matches = c.complete("mat")
757 self.assertEqual(matches, ["matplotlib"])
740 self.assertEqual(matches, ["matplotlib"])
758
741
759 # After removing matplotlib from namespace, the magic should again be
742 # After removing matplotlib from namespace, the magic should again be
760 # the only option.
743 # the only option.
761 del ip.user_ns["matplotlib"]
744 del ip.user_ns["matplotlib"]
762 text, matches = c.complete("mat")
745 text, matches = c.complete("mat")
763 self.assertEqual(matches, ["%matplotlib"])
746 self.assertEqual(matches, ["%matplotlib"])
764
747
765 def test_magic_completion_shadowing_explicit(self):
748 def test_magic_completion_shadowing_explicit(self):
766 """
749 """
767 If the user try to complete a shadowed magic, and explicit % start should
750 If the user try to complete a shadowed magic, and explicit % start should
768 still return the completions.
751 still return the completions.
769 """
752 """
770 ip = get_ipython()
753 ip = get_ipython()
771 c = ip.Completer
754 c = ip.Completer
772
755
773 # Before importing matplotlib, %matplotlib magic should be the only option.
756 # Before importing matplotlib, %matplotlib magic should be the only option.
774 text, matches = c.complete("%mat")
757 text, matches = c.complete("%mat")
775 self.assertEqual(matches, ["%matplotlib"])
758 self.assertEqual(matches, ["%matplotlib"])
776
759
777 ip.run_cell("matplotlib = 1")
760 ip.run_cell("matplotlib = 1")
778
761
779 # After removing matplotlib from namespace, the magic should still be
762 # After removing matplotlib from namespace, the magic should still be
780 # the only option.
763 # the only option.
781 text, matches = c.complete("%mat")
764 text, matches = c.complete("%mat")
782 self.assertEqual(matches, ["%matplotlib"])
765 self.assertEqual(matches, ["%matplotlib"])
783
766
784 def test_magic_config(self):
767 def test_magic_config(self):
785 ip = get_ipython()
768 ip = get_ipython()
786 c = ip.Completer
769 c = ip.Completer
787
770
788 s, matches = c.complete(None, "conf")
771 s, matches = c.complete(None, "conf")
789 self.assertIn("%config", matches)
772 self.assertIn("%config", matches)
790 s, matches = c.complete(None, "conf")
773 s, matches = c.complete(None, "conf")
791 self.assertNotIn("AliasManager", matches)
774 self.assertNotIn("AliasManager", matches)
792 s, matches = c.complete(None, "config ")
775 s, matches = c.complete(None, "config ")
793 self.assertIn("AliasManager", matches)
776 self.assertIn("AliasManager", matches)
794 s, matches = c.complete(None, "%config ")
777 s, matches = c.complete(None, "%config ")
795 self.assertIn("AliasManager", matches)
778 self.assertIn("AliasManager", matches)
796 s, matches = c.complete(None, "config Ali")
779 s, matches = c.complete(None, "config Ali")
797 self.assertListEqual(["AliasManager"], matches)
780 self.assertListEqual(["AliasManager"], matches)
798 s, matches = c.complete(None, "%config Ali")
781 s, matches = c.complete(None, "%config Ali")
799 self.assertListEqual(["AliasManager"], matches)
782 self.assertListEqual(["AliasManager"], matches)
800 s, matches = c.complete(None, "config AliasManager")
783 s, matches = c.complete(None, "config AliasManager")
801 self.assertListEqual(["AliasManager"], matches)
784 self.assertListEqual(["AliasManager"], matches)
802 s, matches = c.complete(None, "%config AliasManager")
785 s, matches = c.complete(None, "%config AliasManager")
803 self.assertListEqual(["AliasManager"], matches)
786 self.assertListEqual(["AliasManager"], matches)
804 s, matches = c.complete(None, "config AliasManager.")
787 s, matches = c.complete(None, "config AliasManager.")
805 self.assertIn("AliasManager.default_aliases", matches)
788 self.assertIn("AliasManager.default_aliases", matches)
806 s, matches = c.complete(None, "%config AliasManager.")
789 s, matches = c.complete(None, "%config AliasManager.")
807 self.assertIn("AliasManager.default_aliases", matches)
790 self.assertIn("AliasManager.default_aliases", matches)
808 s, matches = c.complete(None, "config AliasManager.de")
791 s, matches = c.complete(None, "config AliasManager.de")
809 self.assertListEqual(["AliasManager.default_aliases"], matches)
792 self.assertListEqual(["AliasManager.default_aliases"], matches)
810 s, matches = c.complete(None, "config AliasManager.de")
793 s, matches = c.complete(None, "config AliasManager.de")
811 self.assertListEqual(["AliasManager.default_aliases"], matches)
794 self.assertListEqual(["AliasManager.default_aliases"], matches)
812
795
813 def test_magic_color(self):
796 def test_magic_color(self):
814 ip = get_ipython()
797 ip = get_ipython()
815 c = ip.Completer
798 c = ip.Completer
816
799
817 s, matches = c.complete(None, "colo")
800 s, matches = c.complete(None, "colo")
818 self.assertIn("%colors", matches)
801 self.assertIn("%colors", matches)
819 s, matches = c.complete(None, "colo")
802 s, matches = c.complete(None, "colo")
820 self.assertNotIn("NoColor", matches)
803 self.assertNotIn("NoColor", matches)
821 s, matches = c.complete(None, "%colors") # No trailing space
804 s, matches = c.complete(None, "%colors") # No trailing space
822 self.assertNotIn("NoColor", matches)
805 self.assertNotIn("NoColor", matches)
823 s, matches = c.complete(None, "colors ")
806 s, matches = c.complete(None, "colors ")
824 self.assertIn("NoColor", matches)
807 self.assertIn("NoColor", matches)
825 s, matches = c.complete(None, "%colors ")
808 s, matches = c.complete(None, "%colors ")
826 self.assertIn("NoColor", matches)
809 self.assertIn("NoColor", matches)
827 s, matches = c.complete(None, "colors NoCo")
810 s, matches = c.complete(None, "colors NoCo")
828 self.assertListEqual(["NoColor"], matches)
811 self.assertListEqual(["NoColor"], matches)
829 s, matches = c.complete(None, "%colors NoCo")
812 s, matches = c.complete(None, "%colors NoCo")
830 self.assertListEqual(["NoColor"], matches)
813 self.assertListEqual(["NoColor"], matches)
831
814
832 def test_match_dict_keys(self):
815 def test_match_dict_keys(self):
833 """
816 """
834 Test that match_dict_keys works on a couple of use case does return what
817 Test that match_dict_keys works on a couple of use case does return what
835 expected, and does not crash
818 expected, and does not crash
836 """
819 """
837 delims = " \t\n`!@#$^&*()=+[{]}\\|;:'\",<>?"
820 delims = " \t\n`!@#$^&*()=+[{]}\\|;:'\",<>?"
838
821
839 keys = ["foo", b"far"]
822 keys = ["foo", b"far"]
840 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2, ["far"])
823 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2, ["far"])
841 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2, ["far"])
824 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2, ["far"])
842 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2, ["far"])
825 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2, ["far"])
843 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2, ["far"])
826 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2, ["far"])
844
827
845 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1, ["foo"])
828 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1, ["foo"])
846 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1, ["foo"])
829 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1, ["foo"])
847 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1, ["foo"])
830 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1, ["foo"])
848 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1, ["foo"])
831 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1, ["foo"])
849
832
850 match_dict_keys
833 match_dict_keys
851
834
852 def test_match_dict_keys_tuple(self):
835 def test_match_dict_keys_tuple(self):
853 """
836 """
854 Test that match_dict_keys called with extra prefix works on a couple of use case,
837 Test that match_dict_keys called with extra prefix works on a couple of use case,
855 does return what expected, and does not crash.
838 does return what expected, and does not crash.
856 """
839 """
857 delims = " \t\n`!@#$^&*()=+[{]}\\|;:'\",<>?"
840 delims = " \t\n`!@#$^&*()=+[{]}\\|;:'\",<>?"
858
841
859 keys = [("foo", "bar"), ("foo", "oof"), ("foo", b"bar"), ('other', 'test')]
842 keys = [("foo", "bar"), ("foo", "oof"), ("foo", b"bar"), ('other', 'test')]
860
843
861 # Completion on first key == "foo"
844 # Completion on first key == "foo"
862 assert match_dict_keys(keys, "'", delims=delims, extra_prefix=("foo",)) == ("'", 1, ["bar", "oof"])
845 assert match_dict_keys(keys, "'", delims=delims, extra_prefix=("foo",)) == ("'", 1, ["bar", "oof"])
863 assert match_dict_keys(keys, "\"", delims=delims, extra_prefix=("foo",)) == ("\"", 1, ["bar", "oof"])
846 assert match_dict_keys(keys, "\"", delims=delims, extra_prefix=("foo",)) == ("\"", 1, ["bar", "oof"])
864 assert match_dict_keys(keys, "'o", delims=delims, extra_prefix=("foo",)) == ("'", 1, ["oof"])
847 assert match_dict_keys(keys, "'o", delims=delims, extra_prefix=("foo",)) == ("'", 1, ["oof"])
865 assert match_dict_keys(keys, "\"o", delims=delims, extra_prefix=("foo",)) == ("\"", 1, ["oof"])
848 assert match_dict_keys(keys, "\"o", delims=delims, extra_prefix=("foo",)) == ("\"", 1, ["oof"])
866 assert match_dict_keys(keys, "b'", delims=delims, extra_prefix=("foo",)) == ("'", 2, ["bar"])
849 assert match_dict_keys(keys, "b'", delims=delims, extra_prefix=("foo",)) == ("'", 2, ["bar"])
867 assert match_dict_keys(keys, "b\"", delims=delims, extra_prefix=("foo",)) == ("\"", 2, ["bar"])
850 assert match_dict_keys(keys, "b\"", delims=delims, extra_prefix=("foo",)) == ("\"", 2, ["bar"])
868 assert match_dict_keys(keys, "b'b", delims=delims, extra_prefix=("foo",)) == ("'", 2, ["bar"])
851 assert match_dict_keys(keys, "b'b", delims=delims, extra_prefix=("foo",)) == ("'", 2, ["bar"])
869 assert match_dict_keys(keys, "b\"b", delims=delims, extra_prefix=("foo",)) == ("\"", 2, ["bar"])
852 assert match_dict_keys(keys, "b\"b", delims=delims, extra_prefix=("foo",)) == ("\"", 2, ["bar"])
870
853
871 # No Completion
854 # No Completion
872 assert match_dict_keys(keys, "'", delims=delims, extra_prefix=("no_foo",)) == ("'", 1, [])
855 assert match_dict_keys(keys, "'", delims=delims, extra_prefix=("no_foo",)) == ("'", 1, [])
873 assert match_dict_keys(keys, "'", delims=delims, extra_prefix=("fo",)) == ("'", 1, [])
856 assert match_dict_keys(keys, "'", delims=delims, extra_prefix=("fo",)) == ("'", 1, [])
874
857
875 keys = [('foo1', 'foo2', 'foo3', 'foo4'), ('foo1', 'foo2', 'bar', 'foo4')]
858 keys = [('foo1', 'foo2', 'foo3', 'foo4'), ('foo1', 'foo2', 'bar', 'foo4')]
876 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1',)) == ("'", 1, ["foo2", "foo2"])
859 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1',)) == ("'", 1, ["foo2", "foo2"])
877 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1', 'foo2')) == ("'", 1, ["foo3"])
860 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1', 'foo2')) == ("'", 1, ["foo3"])
878 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1', 'foo2', 'foo3')) == ("'", 1, ["foo4"])
861 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1', 'foo2', 'foo3')) == ("'", 1, ["foo4"])
879 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1', 'foo2', 'foo3', 'foo4')) == ("'", 1, [])
862 assert match_dict_keys(keys, "'foo", delims=delims, extra_prefix=('foo1', 'foo2', 'foo3', 'foo4')) == ("'", 1, [])
880
863
881 def test_dict_key_completion_string(self):
864 def test_dict_key_completion_string(self):
882 """Test dictionary key completion for string keys"""
865 """Test dictionary key completion for string keys"""
883 ip = get_ipython()
866 ip = get_ipython()
884 complete = ip.Completer.complete
867 complete = ip.Completer.complete
885
868
886 ip.user_ns["d"] = {"abc": None}
869 ip.user_ns["d"] = {"abc": None}
887
870
888 # check completion at different stages
871 # check completion at different stages
889 _, matches = complete(line_buffer="d[")
872 _, matches = complete(line_buffer="d[")
890 self.assertIn("'abc'", matches)
873 self.assertIn("'abc'", matches)
891 self.assertNotIn("'abc']", matches)
874 self.assertNotIn("'abc']", matches)
892
875
893 _, matches = complete(line_buffer="d['")
876 _, matches = complete(line_buffer="d['")
894 self.assertIn("abc", matches)
877 self.assertIn("abc", matches)
895 self.assertNotIn("abc']", matches)
878 self.assertNotIn("abc']", matches)
896
879
897 _, matches = complete(line_buffer="d['a")
880 _, matches = complete(line_buffer="d['a")
898 self.assertIn("abc", matches)
881 self.assertIn("abc", matches)
899 self.assertNotIn("abc']", matches)
882 self.assertNotIn("abc']", matches)
900
883
901 # check use of different quoting
884 # check use of different quoting
902 _, matches = complete(line_buffer='d["')
885 _, matches = complete(line_buffer='d["')
903 self.assertIn("abc", matches)
886 self.assertIn("abc", matches)
904 self.assertNotIn('abc"]', matches)
887 self.assertNotIn('abc"]', matches)
905
888
906 _, matches = complete(line_buffer='d["a')
889 _, matches = complete(line_buffer='d["a')
907 self.assertIn("abc", matches)
890 self.assertIn("abc", matches)
908 self.assertNotIn('abc"]', matches)
891 self.assertNotIn('abc"]', matches)
909
892
910 # check sensitivity to following context
893 # check sensitivity to following context
911 _, matches = complete(line_buffer="d[]", cursor_pos=2)
894 _, matches = complete(line_buffer="d[]", cursor_pos=2)
912 self.assertIn("'abc'", matches)
895 self.assertIn("'abc'", matches)
913
896
914 _, matches = complete(line_buffer="d['']", cursor_pos=3)
897 _, matches = complete(line_buffer="d['']", cursor_pos=3)
915 self.assertIn("abc", matches)
898 self.assertIn("abc", matches)
916 self.assertNotIn("abc'", matches)
899 self.assertNotIn("abc'", matches)
917 self.assertNotIn("abc']", matches)
900 self.assertNotIn("abc']", matches)
918
901
919 # check multiple solutions are correctly returned and that noise is not
902 # check multiple solutions are correctly returned and that noise is not
920 ip.user_ns["d"] = {
903 ip.user_ns["d"] = {
921 "abc": None,
904 "abc": None,
922 "abd": None,
905 "abd": None,
923 "bad": None,
906 "bad": None,
924 object(): None,
907 object(): None,
925 5: None,
908 5: None,
926 ("abe", None): None,
909 ("abe", None): None,
927 (None, "abf"): None
910 (None, "abf"): None
928 }
911 }
929
912
930 _, matches = complete(line_buffer="d['a")
913 _, matches = complete(line_buffer="d['a")
931 self.assertIn("abc", matches)
914 self.assertIn("abc", matches)
932 self.assertIn("abd", matches)
915 self.assertIn("abd", matches)
933 self.assertNotIn("bad", matches)
916 self.assertNotIn("bad", matches)
934 self.assertNotIn("abe", matches)
917 self.assertNotIn("abe", matches)
935 self.assertNotIn("abf", matches)
918 self.assertNotIn("abf", matches)
936 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
919 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
937
920
938 # check escaping and whitespace
921 # check escaping and whitespace
939 ip.user_ns["d"] = {"a\nb": None, "a'b": None, 'a"b': None, "a word": None}
922 ip.user_ns["d"] = {"a\nb": None, "a'b": None, 'a"b': None, "a word": None}
940 _, matches = complete(line_buffer="d['a")
923 _, matches = complete(line_buffer="d['a")
941 self.assertIn("a\\nb", matches)
924 self.assertIn("a\\nb", matches)
942 self.assertIn("a\\'b", matches)
925 self.assertIn("a\\'b", matches)
943 self.assertIn('a"b', matches)
926 self.assertIn('a"b', matches)
944 self.assertIn("a word", matches)
927 self.assertIn("a word", matches)
945 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
928 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
946
929
947 # - can complete on non-initial word of the string
930 # - can complete on non-initial word of the string
948 _, matches = complete(line_buffer="d['a w")
931 _, matches = complete(line_buffer="d['a w")
949 self.assertIn("word", matches)
932 self.assertIn("word", matches)
950
933
951 # - understands quote escaping
934 # - understands quote escaping
952 _, matches = complete(line_buffer="d['a\\'")
935 _, matches = complete(line_buffer="d['a\\'")
953 self.assertIn("b", matches)
936 self.assertIn("b", matches)
954
937
955 # - default quoting should work like repr
938 # - default quoting should work like repr
956 _, matches = complete(line_buffer="d[")
939 _, matches = complete(line_buffer="d[")
957 self.assertIn('"a\'b"', matches)
940 self.assertIn('"a\'b"', matches)
958
941
959 # - when opening quote with ", possible to match with unescaped apostrophe
942 # - when opening quote with ", possible to match with unescaped apostrophe
960 _, matches = complete(line_buffer="d[\"a'")
943 _, matches = complete(line_buffer="d[\"a'")
961 self.assertIn("b", matches)
944 self.assertIn("b", matches)
962
945
963 # need to not split at delims that readline won't split at
946 # need to not split at delims that readline won't split at
964 if "-" not in ip.Completer.splitter.delims:
947 if "-" not in ip.Completer.splitter.delims:
965 ip.user_ns["d"] = {"before-after": None}
948 ip.user_ns["d"] = {"before-after": None}
966 _, matches = complete(line_buffer="d['before-af")
949 _, matches = complete(line_buffer="d['before-af")
967 self.assertIn("before-after", matches)
950 self.assertIn("before-after", matches)
968
951
969 # check completion on tuple-of-string keys at different stage - on first key
952 # check completion on tuple-of-string keys at different stage - on first key
970 ip.user_ns["d"] = {('foo', 'bar'): None}
953 ip.user_ns["d"] = {('foo', 'bar'): None}
971 _, matches = complete(line_buffer="d[")
954 _, matches = complete(line_buffer="d[")
972 self.assertIn("'foo'", matches)
955 self.assertIn("'foo'", matches)
973 self.assertNotIn("'foo']", matches)
956 self.assertNotIn("'foo']", matches)
974 self.assertNotIn("'bar'", matches)
957 self.assertNotIn("'bar'", matches)
975 self.assertNotIn("foo", matches)
958 self.assertNotIn("foo", matches)
976 self.assertNotIn("bar", matches)
959 self.assertNotIn("bar", matches)
977
960
978 # - match the prefix
961 # - match the prefix
979 _, matches = complete(line_buffer="d['f")
962 _, matches = complete(line_buffer="d['f")
980 self.assertIn("foo", matches)
963 self.assertIn("foo", matches)
981 self.assertNotIn("foo']", matches)
964 self.assertNotIn("foo']", matches)
982 self.assertNotIn('foo"]', matches)
965 self.assertNotIn('foo"]', matches)
983 _, matches = complete(line_buffer="d['foo")
966 _, matches = complete(line_buffer="d['foo")
984 self.assertIn("foo", matches)
967 self.assertIn("foo", matches)
985
968
986 # - can complete on second key
969 # - can complete on second key
987 _, matches = complete(line_buffer="d['foo', ")
970 _, matches = complete(line_buffer="d['foo', ")
988 self.assertIn("'bar'", matches)
971 self.assertIn("'bar'", matches)
989 _, matches = complete(line_buffer="d['foo', 'b")
972 _, matches = complete(line_buffer="d['foo', 'b")
990 self.assertIn("bar", matches)
973 self.assertIn("bar", matches)
991 self.assertNotIn("foo", matches)
974 self.assertNotIn("foo", matches)
992
975
993 # - does not propose missing keys
976 # - does not propose missing keys
994 _, matches = complete(line_buffer="d['foo', 'f")
977 _, matches = complete(line_buffer="d['foo', 'f")
995 self.assertNotIn("bar", matches)
978 self.assertNotIn("bar", matches)
996 self.assertNotIn("foo", matches)
979 self.assertNotIn("foo", matches)
997
980
998 # check sensitivity to following context
981 # check sensitivity to following context
999 _, matches = complete(line_buffer="d['foo',]", cursor_pos=8)
982 _, matches = complete(line_buffer="d['foo',]", cursor_pos=8)
1000 self.assertIn("'bar'", matches)
983 self.assertIn("'bar'", matches)
1001 self.assertNotIn("bar", matches)
984 self.assertNotIn("bar", matches)
1002 self.assertNotIn("'foo'", matches)
985 self.assertNotIn("'foo'", matches)
1003 self.assertNotIn("foo", matches)
986 self.assertNotIn("foo", matches)
1004
987
1005 _, matches = complete(line_buffer="d['']", cursor_pos=3)
988 _, matches = complete(line_buffer="d['']", cursor_pos=3)
1006 self.assertIn("foo", matches)
989 self.assertIn("foo", matches)
1007 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
990 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
1008
991
1009 _, matches = complete(line_buffer='d[""]', cursor_pos=3)
992 _, matches = complete(line_buffer='d[""]', cursor_pos=3)
1010 self.assertIn("foo", matches)
993 self.assertIn("foo", matches)
1011 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
994 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
1012
995
1013 _, matches = complete(line_buffer='d["foo","]', cursor_pos=9)
996 _, matches = complete(line_buffer='d["foo","]', cursor_pos=9)
1014 self.assertIn("bar", matches)
997 self.assertIn("bar", matches)
1015 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
998 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
1016
999
1017 _, matches = complete(line_buffer='d["foo",]', cursor_pos=8)
1000 _, matches = complete(line_buffer='d["foo",]', cursor_pos=8)
1018 self.assertIn("'bar'", matches)
1001 self.assertIn("'bar'", matches)
1019 self.assertNotIn("bar", matches)
1002 self.assertNotIn("bar", matches)
1020
1003
1021 # Can complete with longer tuple keys
1004 # Can complete with longer tuple keys
1022 ip.user_ns["d"] = {('foo', 'bar', 'foobar'): None}
1005 ip.user_ns["d"] = {('foo', 'bar', 'foobar'): None}
1023
1006
1024 # - can complete second key
1007 # - can complete second key
1025 _, matches = complete(line_buffer="d['foo', 'b")
1008 _, matches = complete(line_buffer="d['foo', 'b")
1026 self.assertIn("bar", matches)
1009 self.assertIn("bar", matches)
1027 self.assertNotIn("foo", matches)
1010 self.assertNotIn("foo", matches)
1028 self.assertNotIn("foobar", matches)
1011 self.assertNotIn("foobar", matches)
1029
1012
1030 # - can complete third key
1013 # - can complete third key
1031 _, matches = complete(line_buffer="d['foo', 'bar', 'fo")
1014 _, matches = complete(line_buffer="d['foo', 'bar', 'fo")
1032 self.assertIn("foobar", matches)
1015 self.assertIn("foobar", matches)
1033 self.assertNotIn("foo", matches)
1016 self.assertNotIn("foo", matches)
1034 self.assertNotIn("bar", matches)
1017 self.assertNotIn("bar", matches)
1035
1018
1036 def test_dict_key_completion_contexts(self):
1019 def test_dict_key_completion_contexts(self):
1037 """Test expression contexts in which dict key completion occurs"""
1020 """Test expression contexts in which dict key completion occurs"""
1038 ip = get_ipython()
1021 ip = get_ipython()
1039 complete = ip.Completer.complete
1022 complete = ip.Completer.complete
1040 d = {"abc": None}
1023 d = {"abc": None}
1041 ip.user_ns["d"] = d
1024 ip.user_ns["d"] = d
1042
1025
1043 class C:
1026 class C:
1044 data = d
1027 data = d
1045
1028
1046 ip.user_ns["C"] = C
1029 ip.user_ns["C"] = C
1047 ip.user_ns["get"] = lambda: d
1030 ip.user_ns["get"] = lambda: d
1048
1031
1049 def assert_no_completion(**kwargs):
1032 def assert_no_completion(**kwargs):
1050 _, matches = complete(**kwargs)
1033 _, matches = complete(**kwargs)
1051 self.assertNotIn("abc", matches)
1034 self.assertNotIn("abc", matches)
1052 self.assertNotIn("abc'", matches)
1035 self.assertNotIn("abc'", matches)
1053 self.assertNotIn("abc']", matches)
1036 self.assertNotIn("abc']", matches)
1054 self.assertNotIn("'abc'", matches)
1037 self.assertNotIn("'abc'", matches)
1055 self.assertNotIn("'abc']", matches)
1038 self.assertNotIn("'abc']", matches)
1056
1039
1057 def assert_completion(**kwargs):
1040 def assert_completion(**kwargs):
1058 _, matches = complete(**kwargs)
1041 _, matches = complete(**kwargs)
1059 self.assertIn("'abc'", matches)
1042 self.assertIn("'abc'", matches)
1060 self.assertNotIn("'abc']", matches)
1043 self.assertNotIn("'abc']", matches)
1061
1044
1062 # no completion after string closed, even if reopened
1045 # no completion after string closed, even if reopened
1063 assert_no_completion(line_buffer="d['a'")
1046 assert_no_completion(line_buffer="d['a'")
1064 assert_no_completion(line_buffer='d["a"')
1047 assert_no_completion(line_buffer='d["a"')
1065 assert_no_completion(line_buffer="d['a' + ")
1048 assert_no_completion(line_buffer="d['a' + ")
1066 assert_no_completion(line_buffer="d['a' + '")
1049 assert_no_completion(line_buffer="d['a' + '")
1067
1050
1068 # completion in non-trivial expressions
1051 # completion in non-trivial expressions
1069 assert_completion(line_buffer="+ d[")
1052 assert_completion(line_buffer="+ d[")
1070 assert_completion(line_buffer="(d[")
1053 assert_completion(line_buffer="(d[")
1071 assert_completion(line_buffer="C.data[")
1054 assert_completion(line_buffer="C.data[")
1072
1055
1073 # greedy flag
1056 # greedy flag
1074 def assert_completion(**kwargs):
1057 def assert_completion(**kwargs):
1075 _, matches = complete(**kwargs)
1058 _, matches = complete(**kwargs)
1076 self.assertIn("get()['abc']", matches)
1059 self.assertIn("get()['abc']", matches)
1077
1060
1078 assert_no_completion(line_buffer="get()[")
1061 assert_no_completion(line_buffer="get()[")
1079 with greedy_completion():
1062 with greedy_completion():
1080 assert_completion(line_buffer="get()[")
1063 assert_completion(line_buffer="get()[")
1081 assert_completion(line_buffer="get()['")
1064 assert_completion(line_buffer="get()['")
1082 assert_completion(line_buffer="get()['a")
1065 assert_completion(line_buffer="get()['a")
1083 assert_completion(line_buffer="get()['ab")
1066 assert_completion(line_buffer="get()['ab")
1084 assert_completion(line_buffer="get()['abc")
1067 assert_completion(line_buffer="get()['abc")
1085
1068
1086 def test_dict_key_completion_bytes(self):
1069 def test_dict_key_completion_bytes(self):
1087 """Test handling of bytes in dict key completion"""
1070 """Test handling of bytes in dict key completion"""
1088 ip = get_ipython()
1071 ip = get_ipython()
1089 complete = ip.Completer.complete
1072 complete = ip.Completer.complete
1090
1073
1091 ip.user_ns["d"] = {"abc": None, b"abd": None}
1074 ip.user_ns["d"] = {"abc": None, b"abd": None}
1092
1075
1093 _, matches = complete(line_buffer="d[")
1076 _, matches = complete(line_buffer="d[")
1094 self.assertIn("'abc'", matches)
1077 self.assertIn("'abc'", matches)
1095 self.assertIn("b'abd'", matches)
1078 self.assertIn("b'abd'", matches)
1096
1079
1097 if False: # not currently implemented
1080 if False: # not currently implemented
1098 _, matches = complete(line_buffer="d[b")
1081 _, matches = complete(line_buffer="d[b")
1099 self.assertIn("b'abd'", matches)
1082 self.assertIn("b'abd'", matches)
1100 self.assertNotIn("b'abc'", matches)
1083 self.assertNotIn("b'abc'", matches)
1101
1084
1102 _, matches = complete(line_buffer="d[b'")
1085 _, matches = complete(line_buffer="d[b'")
1103 self.assertIn("abd", matches)
1086 self.assertIn("abd", matches)
1104 self.assertNotIn("abc", matches)
1087 self.assertNotIn("abc", matches)
1105
1088
1106 _, matches = complete(line_buffer="d[B'")
1089 _, matches = complete(line_buffer="d[B'")
1107 self.assertIn("abd", matches)
1090 self.assertIn("abd", matches)
1108 self.assertNotIn("abc", matches)
1091 self.assertNotIn("abc", matches)
1109
1092
1110 _, matches = complete(line_buffer="d['")
1093 _, matches = complete(line_buffer="d['")
1111 self.assertIn("abc", matches)
1094 self.assertIn("abc", matches)
1112 self.assertNotIn("abd", matches)
1095 self.assertNotIn("abd", matches)
1113
1096
1114 def test_dict_key_completion_unicode_py3(self):
1097 def test_dict_key_completion_unicode_py3(self):
1115 """Test handling of unicode in dict key completion"""
1098 """Test handling of unicode in dict key completion"""
1116 ip = get_ipython()
1099 ip = get_ipython()
1117 complete = ip.Completer.complete
1100 complete = ip.Completer.complete
1118
1101
1119 ip.user_ns["d"] = {"a\u05d0": None}
1102 ip.user_ns["d"] = {"a\u05d0": None}
1120
1103
1121 # query using escape
1104 # query using escape
1122 if sys.platform != "win32":
1105 if sys.platform != "win32":
1123 # Known failure on Windows
1106 # Known failure on Windows
1124 _, matches = complete(line_buffer="d['a\\u05d0")
1107 _, matches = complete(line_buffer="d['a\\u05d0")
1125 self.assertIn("u05d0", matches) # tokenized after \\
1108 self.assertIn("u05d0", matches) # tokenized after \\
1126
1109
1127 # query using character
1110 # query using character
1128 _, matches = complete(line_buffer="d['a\u05d0")
1111 _, matches = complete(line_buffer="d['a\u05d0")
1129 self.assertIn("a\u05d0", matches)
1112 self.assertIn("a\u05d0", matches)
1130
1113
1131 with greedy_completion():
1114 with greedy_completion():
1132 # query using escape
1115 # query using escape
1133 _, matches = complete(line_buffer="d['a\\u05d0")
1116 _, matches = complete(line_buffer="d['a\\u05d0")
1134 self.assertIn("d['a\\u05d0']", matches) # tokenized after \\
1117 self.assertIn("d['a\\u05d0']", matches) # tokenized after \\
1135
1118
1136 # query using character
1119 # query using character
1137 _, matches = complete(line_buffer="d['a\u05d0")
1120 _, matches = complete(line_buffer="d['a\u05d0")
1138 self.assertIn("d['a\u05d0']", matches)
1121 self.assertIn("d['a\u05d0']", matches)
1139
1122
1140 @dec.skip_without("numpy")
1123 @dec.skip_without("numpy")
1141 def test_struct_array_key_completion(self):
1124 def test_struct_array_key_completion(self):
1142 """Test dict key completion applies to numpy struct arrays"""
1125 """Test dict key completion applies to numpy struct arrays"""
1143 import numpy
1126 import numpy
1144
1127
1145 ip = get_ipython()
1128 ip = get_ipython()
1146 complete = ip.Completer.complete
1129 complete = ip.Completer.complete
1147 ip.user_ns["d"] = numpy.array([], dtype=[("hello", "f"), ("world", "f")])
1130 ip.user_ns["d"] = numpy.array([], dtype=[("hello", "f"), ("world", "f")])
1148 _, matches = complete(line_buffer="d['")
1131 _, matches = complete(line_buffer="d['")
1149 self.assertIn("hello", matches)
1132 self.assertIn("hello", matches)
1150 self.assertIn("world", matches)
1133 self.assertIn("world", matches)
1151 # complete on the numpy struct itself
1134 # complete on the numpy struct itself
1152 dt = numpy.dtype(
1135 dt = numpy.dtype(
1153 [("my_head", [("my_dt", ">u4"), ("my_df", ">u4")]), ("my_data", ">f4", 5)]
1136 [("my_head", [("my_dt", ">u4"), ("my_df", ">u4")]), ("my_data", ">f4", 5)]
1154 )
1137 )
1155 x = numpy.zeros(2, dtype=dt)
1138 x = numpy.zeros(2, dtype=dt)
1156 ip.user_ns["d"] = x[1]
1139 ip.user_ns["d"] = x[1]
1157 _, matches = complete(line_buffer="d['")
1140 _, matches = complete(line_buffer="d['")
1158 self.assertIn("my_head", matches)
1141 self.assertIn("my_head", matches)
1159 self.assertIn("my_data", matches)
1142 self.assertIn("my_data", matches)
1160 # complete on a nested level
1143 # complete on a nested level
1161 with greedy_completion():
1144 with greedy_completion():
1162 ip.user_ns["d"] = numpy.zeros(2, dtype=dt)
1145 ip.user_ns["d"] = numpy.zeros(2, dtype=dt)
1163 _, matches = complete(line_buffer="d[1]['my_head']['")
1146 _, matches = complete(line_buffer="d[1]['my_head']['")
1164 self.assertTrue(any(["my_dt" in m for m in matches]))
1147 self.assertTrue(any(["my_dt" in m for m in matches]))
1165 self.assertTrue(any(["my_df" in m for m in matches]))
1148 self.assertTrue(any(["my_df" in m for m in matches]))
1166
1149
1167 @dec.skip_without("pandas")
1150 @dec.skip_without("pandas")
1168 def test_dataframe_key_completion(self):
1151 def test_dataframe_key_completion(self):
1169 """Test dict key completion applies to pandas DataFrames"""
1152 """Test dict key completion applies to pandas DataFrames"""
1170 import pandas
1153 import pandas
1171
1154
1172 ip = get_ipython()
1155 ip = get_ipython()
1173 complete = ip.Completer.complete
1156 complete = ip.Completer.complete
1174 ip.user_ns["d"] = pandas.DataFrame({"hello": [1], "world": [2]})
1157 ip.user_ns["d"] = pandas.DataFrame({"hello": [1], "world": [2]})
1175 _, matches = complete(line_buffer="d['")
1158 _, matches = complete(line_buffer="d['")
1176 self.assertIn("hello", matches)
1159 self.assertIn("hello", matches)
1177 self.assertIn("world", matches)
1160 self.assertIn("world", matches)
1178
1161
1179 def test_dict_key_completion_invalids(self):
1162 def test_dict_key_completion_invalids(self):
1180 """Smoke test cases dict key completion can't handle"""
1163 """Smoke test cases dict key completion can't handle"""
1181 ip = get_ipython()
1164 ip = get_ipython()
1182 complete = ip.Completer.complete
1165 complete = ip.Completer.complete
1183
1166
1184 ip.user_ns["no_getitem"] = None
1167 ip.user_ns["no_getitem"] = None
1185 ip.user_ns["no_keys"] = []
1168 ip.user_ns["no_keys"] = []
1186 ip.user_ns["cant_call_keys"] = dict
1169 ip.user_ns["cant_call_keys"] = dict
1187 ip.user_ns["empty"] = {}
1170 ip.user_ns["empty"] = {}
1188 ip.user_ns["d"] = {"abc": 5}
1171 ip.user_ns["d"] = {"abc": 5}
1189
1172
1190 _, matches = complete(line_buffer="no_getitem['")
1173 _, matches = complete(line_buffer="no_getitem['")
1191 _, matches = complete(line_buffer="no_keys['")
1174 _, matches = complete(line_buffer="no_keys['")
1192 _, matches = complete(line_buffer="cant_call_keys['")
1175 _, matches = complete(line_buffer="cant_call_keys['")
1193 _, matches = complete(line_buffer="empty['")
1176 _, matches = complete(line_buffer="empty['")
1194 _, matches = complete(line_buffer="name_error['")
1177 _, matches = complete(line_buffer="name_error['")
1195 _, matches = complete(line_buffer="d['\\") # incomplete escape
1178 _, matches = complete(line_buffer="d['\\") # incomplete escape
1196
1179
1197 def test_object_key_completion(self):
1180 def test_object_key_completion(self):
1198 ip = get_ipython()
1181 ip = get_ipython()
1199 ip.user_ns["key_completable"] = KeyCompletable(["qwerty", "qwick"])
1182 ip.user_ns["key_completable"] = KeyCompletable(["qwerty", "qwick"])
1200
1183
1201 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
1184 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
1202 self.assertIn("qwerty", matches)
1185 self.assertIn("qwerty", matches)
1203 self.assertIn("qwick", matches)
1186 self.assertIn("qwick", matches)
1204
1187
1205 def test_class_key_completion(self):
1188 def test_class_key_completion(self):
1206 ip = get_ipython()
1189 ip = get_ipython()
1207 NamedInstanceClass("qwerty")
1190 NamedInstanceClass("qwerty")
1208 NamedInstanceClass("qwick")
1191 NamedInstanceClass("qwick")
1209 ip.user_ns["named_instance_class"] = NamedInstanceClass
1192 ip.user_ns["named_instance_class"] = NamedInstanceClass
1210
1193
1211 _, matches = ip.Completer.complete(line_buffer="named_instance_class['qw")
1194 _, matches = ip.Completer.complete(line_buffer="named_instance_class['qw")
1212 self.assertIn("qwerty", matches)
1195 self.assertIn("qwerty", matches)
1213 self.assertIn("qwick", matches)
1196 self.assertIn("qwick", matches)
1214
1197
1215 def test_tryimport(self):
1198 def test_tryimport(self):
1216 """
1199 """
1217 Test that try-import don't crash on trailing dot, and import modules before
1200 Test that try-import don't crash on trailing dot, and import modules before
1218 """
1201 """
1219 from IPython.core.completerlib import try_import
1202 from IPython.core.completerlib import try_import
1220
1203
1221 assert try_import("IPython.")
1204 assert try_import("IPython.")
1222
1205
1223 def test_aimport_module_completer(self):
1206 def test_aimport_module_completer(self):
1224 ip = get_ipython()
1207 ip = get_ipython()
1225 _, matches = ip.complete("i", "%aimport i")
1208 _, matches = ip.complete("i", "%aimport i")
1226 self.assertIn("io", matches)
1209 self.assertIn("io", matches)
1227 self.assertNotIn("int", matches)
1210 self.assertNotIn("int", matches)
1228
1211
1229 def test_nested_import_module_completer(self):
1212 def test_nested_import_module_completer(self):
1230 ip = get_ipython()
1213 ip = get_ipython()
1231 _, matches = ip.complete(None, "import IPython.co", 17)
1214 _, matches = ip.complete(None, "import IPython.co", 17)
1232 self.assertIn("IPython.core", matches)
1215 self.assertIn("IPython.core", matches)
1233 self.assertNotIn("import IPython.core", matches)
1216 self.assertNotIn("import IPython.core", matches)
1234 self.assertNotIn("IPython.display", matches)
1217 self.assertNotIn("IPython.display", matches)
1235
1218
1236 def test_import_module_completer(self):
1219 def test_import_module_completer(self):
1237 ip = get_ipython()
1220 ip = get_ipython()
1238 _, matches = ip.complete("i", "import i")
1221 _, matches = ip.complete("i", "import i")
1239 self.assertIn("io", matches)
1222 self.assertIn("io", matches)
1240 self.assertNotIn("int", matches)
1223 self.assertNotIn("int", matches)
1241
1224
1242 def test_from_module_completer(self):
1225 def test_from_module_completer(self):
1243 ip = get_ipython()
1226 ip = get_ipython()
1244 _, matches = ip.complete("B", "from io import B", 16)
1227 _, matches = ip.complete("B", "from io import B", 16)
1245 self.assertIn("BytesIO", matches)
1228 self.assertIn("BytesIO", matches)
1246 self.assertNotIn("BaseException", matches)
1229 self.assertNotIn("BaseException", matches)
1247
1230
1248 def test_snake_case_completion(self):
1231 def test_snake_case_completion(self):
1249 ip = get_ipython()
1232 ip = get_ipython()
1250 ip.Completer.use_jedi = False
1233 ip.Completer.use_jedi = False
1251 ip.user_ns["some_three"] = 3
1234 ip.user_ns["some_three"] = 3
1252 ip.user_ns["some_four"] = 4
1235 ip.user_ns["some_four"] = 4
1253 _, matches = ip.complete("s_", "print(s_f")
1236 _, matches = ip.complete("s_", "print(s_f")
1254 self.assertIn("some_three", matches)
1237 self.assertIn("some_three", matches)
1255 self.assertIn("some_four", matches)
1238 self.assertIn("some_four", matches)
1256
1239
1257 def test_mix_terms(self):
1240 def test_mix_terms(self):
1258 ip = get_ipython()
1241 ip = get_ipython()
1259 from textwrap import dedent
1242 from textwrap import dedent
1260
1243
1261 ip.Completer.use_jedi = False
1244 ip.Completer.use_jedi = False
1262 ip.ex(
1245 ip.ex(
1263 dedent(
1246 dedent(
1264 """
1247 """
1265 class Test:
1248 class Test:
1266 def meth(self, meth_arg1):
1249 def meth(self, meth_arg1):
1267 print("meth")
1250 print("meth")
1268
1251
1269 def meth_1(self, meth1_arg1, meth1_arg2):
1252 def meth_1(self, meth1_arg1, meth1_arg2):
1270 print("meth1")
1253 print("meth1")
1271
1254
1272 def meth_2(self, meth2_arg1, meth2_arg2):
1255 def meth_2(self, meth2_arg1, meth2_arg2):
1273 print("meth2")
1256 print("meth2")
1274 test = Test()
1257 test = Test()
1275 """
1258 """
1276 )
1259 )
1277 )
1260 )
1278 _, matches = ip.complete(None, "test.meth(")
1261 _, matches = ip.complete(None, "test.meth(")
1279 self.assertIn("meth_arg1=", matches)
1262 self.assertIn("meth_arg1=", matches)
1280 self.assertNotIn("meth2_arg1=", matches)
1263 self.assertNotIn("meth2_arg1=", matches)
General Comments 0
You need to be logged in to leave comments. Login now