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