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