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