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