##// END OF EJS Templates
Don't fail when completing modules ending with dot....
Matthias Bussonnier -
Show More
@@ -1,347 +1,352 b''
1 1 # encoding: utf-8
2 2 """Implementations for various useful completers.
3 3
4 4 These are all loaded by default by IPython.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-2011 The IPython Development Team.
8 8 #
9 9 # Distributed under the terms of the BSD License.
10 10 #
11 11 # The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 # Stdlib imports
19 19 import glob
20 20 import inspect
21 21 import os
22 22 import re
23 23 import sys
24 24 from importlib import import_module
25 25 from importlib.machinery import all_suffixes
26 26
27 27
28 28 # Third-party imports
29 29 from time import time
30 30 from zipimport import zipimporter
31 31
32 32 # Our own imports
33 33 from IPython.core.completer import expand_user, compress_user
34 34 from IPython.core.error import TryNext
35 35 from IPython.utils._process_common import arg_split
36 36
37 37 # FIXME: this should be pulled in with the right call via the component system
38 38 from IPython import get_ipython
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Globals and constants
42 42 #-----------------------------------------------------------------------------
43 43 _suffixes = all_suffixes()
44 44
45 45 # Time in seconds after which the rootmodules will be stored permanently in the
46 46 # ipython ip.db database (kept in the user's .ipython dir).
47 47 TIMEOUT_STORAGE = 2
48 48
49 49 # Time in seconds after which we give up
50 50 TIMEOUT_GIVEUP = 20
51 51
52 52 # Regular expression for the python import statement
53 53 import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)'
54 54 r'(?P<package>[/\\]__init__)?'
55 55 r'(?P<suffix>%s)$' %
56 56 r'|'.join(re.escape(s) for s in _suffixes))
57 57
58 58 # RE for the ipython %run command (python + ipython scripts)
59 59 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
60 60
61 61 #-----------------------------------------------------------------------------
62 62 # Local utilities
63 63 #-----------------------------------------------------------------------------
64 64
65 65 def module_list(path):
66 66 """
67 67 Return the list containing the names of the modules available in the given
68 68 folder.
69 69 """
70 70 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
71 71 if path == '':
72 72 path = '.'
73 73
74 74 # A few local constants to be used in loops below
75 75 pjoin = os.path.join
76 76
77 77 if os.path.isdir(path):
78 78 # Build a list of all files in the directory and all files
79 79 # in its subdirectories. For performance reasons, do not
80 80 # recurse more than one level into subdirectories.
81 81 files = []
82 82 for root, dirs, nondirs in os.walk(path, followlinks=True):
83 83 subdir = root[len(path)+1:]
84 84 if subdir:
85 85 files.extend(pjoin(subdir, f) for f in nondirs)
86 86 dirs[:] = [] # Do not recurse into additional subdirectories.
87 87 else:
88 88 files.extend(nondirs)
89 89
90 90 else:
91 91 try:
92 92 files = list(zipimporter(path)._files.keys())
93 93 except:
94 94 files = []
95 95
96 96 # Build a list of modules which match the import_re regex.
97 97 modules = []
98 98 for f in files:
99 99 m = import_re.match(f)
100 100 if m:
101 101 modules.append(m.group('name'))
102 102 return list(set(modules))
103 103
104 104
105 105 def get_root_modules():
106 106 """
107 107 Returns a list containing the names of all the modules available in the
108 108 folders of the pythonpath.
109 109
110 110 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
111 111 """
112 112 ip = get_ipython()
113 113 if ip is None:
114 114 # No global shell instance to store cached list of modules.
115 115 # Don't try to scan for modules every time.
116 116 return list(sys.builtin_module_names)
117 117
118 118 rootmodules_cache = ip.db.get('rootmodules_cache', {})
119 119 rootmodules = list(sys.builtin_module_names)
120 120 start_time = time()
121 121 store = False
122 122 for path in sys.path:
123 123 try:
124 124 modules = rootmodules_cache[path]
125 125 except KeyError:
126 126 modules = module_list(path)
127 127 try:
128 128 modules.remove('__init__')
129 129 except ValueError:
130 130 pass
131 131 if path not in ('', '.'): # cwd modules should not be cached
132 132 rootmodules_cache[path] = modules
133 133 if time() - start_time > TIMEOUT_STORAGE and not store:
134 134 store = True
135 135 print("\nCaching the list of root modules, please wait!")
136 136 print("(This will only be done once - type '%rehashx' to "
137 137 "reset cache!)\n")
138 138 sys.stdout.flush()
139 139 if time() - start_time > TIMEOUT_GIVEUP:
140 140 print("This is taking too long, we give up.\n")
141 141 return []
142 142 rootmodules.extend(modules)
143 143 if store:
144 144 ip.db['rootmodules_cache'] = rootmodules_cache
145 145 rootmodules = list(set(rootmodules))
146 146 return rootmodules
147 147
148 148
149 149 def is_importable(module, attr, only_modules):
150 150 if only_modules:
151 151 return inspect.ismodule(getattr(module, attr))
152 152 else:
153 153 return not(attr[:2] == '__' and attr[-2:] == '__')
154 154
155 def try_import(mod, only_modules=False):
155
156 def try_import(mod: str, only_modules=False):
157 """
158 Try to import given module and return list of potential completions.
159 """
160 mod = mod.rstrip('.')
156 161 try:
157 162 m = import_module(mod)
158 163 except:
159 164 return []
160 165
161 166 m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__
162 167
163 168 completions = []
164 169 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
165 170 completions.extend( [attr for attr in dir(m) if
166 171 is_importable(m, attr, only_modules)])
167 172
168 173 completions.extend(getattr(m, '__all__', []))
169 174 if m_is_init:
170 175 completions.extend(module_list(os.path.dirname(m.__file__)))
171 176 completions = {c for c in completions if isinstance(c, str)}
172 177 completions.discard('__init__')
173 178 return list(completions)
174 179
175 180
176 181 #-----------------------------------------------------------------------------
177 182 # Completion-related functions.
178 183 #-----------------------------------------------------------------------------
179 184
180 185 def quick_completer(cmd, completions):
181 186 """ Easily create a trivial completer for a command.
182 187
183 188 Takes either a list of completions, or all completions in string (that will
184 189 be split on whitespace).
185 190
186 191 Example::
187 192
188 193 [d:\ipython]|1> import ipy_completers
189 194 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
190 195 [d:\ipython]|3> foo b<TAB>
191 196 bar baz
192 197 [d:\ipython]|3> foo ba
193 198 """
194 199
195 200 if isinstance(completions, str):
196 201 completions = completions.split()
197 202
198 203 def do_complete(self, event):
199 204 return completions
200 205
201 206 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
202 207
203 208 def module_completion(line):
204 209 """
205 210 Returns a list containing the completion possibilities for an import line.
206 211
207 212 The line looks like this :
208 213 'import xml.d'
209 214 'from xml.dom import'
210 215 """
211 216
212 217 words = line.split(' ')
213 218 nwords = len(words)
214 219
215 220 # from whatever <tab> -> 'import '
216 221 if nwords == 3 and words[0] == 'from':
217 222 return ['import ']
218 223
219 224 # 'from xy<tab>' or 'import xy<tab>'
220 225 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
221 226 if nwords == 1:
222 227 return get_root_modules()
223 228 mod = words[1].split('.')
224 229 if len(mod) < 2:
225 230 return get_root_modules()
226 231 completion_list = try_import('.'.join(mod[:-1]), True)
227 232 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
228 233
229 234 # 'from xyz import abc<tab>'
230 235 if nwords >= 3 and words[0] == 'from':
231 236 mod = words[1]
232 237 return try_import(mod)
233 238
234 239 #-----------------------------------------------------------------------------
235 240 # Completers
236 241 #-----------------------------------------------------------------------------
237 242 # These all have the func(self, event) signature to be used as custom
238 243 # completers
239 244
240 245 def module_completer(self,event):
241 246 """Give completions after user has typed 'import ...' or 'from ...'"""
242 247
243 248 # This works in all versions of python. While 2.5 has
244 249 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
245 250 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
246 251 # of possibly problematic side effects.
247 252 # This search the folders in the sys.path for available modules.
248 253
249 254 return module_completion(event.line)
250 255
251 256 # FIXME: there's a lot of logic common to the run, cd and builtin file
252 257 # completers, that is currently reimplemented in each.
253 258
254 259 def magic_run_completer(self, event):
255 260 """Complete files that end in .py or .ipy or .ipynb for the %run command.
256 261 """
257 262 comps = arg_split(event.line, strict=False)
258 263 # relpath should be the current token that we need to complete.
259 264 if (len(comps) > 1) and (not event.line.endswith(' ')):
260 265 relpath = comps[-1].strip("'\"")
261 266 else:
262 267 relpath = ''
263 268
264 269 #print("\nev=", event) # dbg
265 270 #print("rp=", relpath) # dbg
266 271 #print('comps=', comps) # dbg
267 272
268 273 lglob = glob.glob
269 274 isdir = os.path.isdir
270 275 relpath, tilde_expand, tilde_val = expand_user(relpath)
271 276
272 277 # Find if the user has already typed the first filename, after which we
273 278 # should complete on all files, since after the first one other files may
274 279 # be arguments to the input script.
275 280
276 281 if any(magic_run_re.match(c) for c in comps):
277 282 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
278 283 for f in lglob(relpath+'*')]
279 284 else:
280 285 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
281 286 pys = [f.replace('\\','/')
282 287 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
283 288 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
284 289
285 290 matches = dirs + pys
286 291
287 292 #print('run comp:', dirs+pys) # dbg
288 293 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
289 294
290 295
291 296 def cd_completer(self, event):
292 297 """Completer function for cd, which only returns directories."""
293 298 ip = get_ipython()
294 299 relpath = event.symbol
295 300
296 301 #print(event) # dbg
297 302 if event.line.endswith('-b') or ' -b ' in event.line:
298 303 # return only bookmark completions
299 304 bkms = self.db.get('bookmarks', None)
300 305 if bkms:
301 306 return bkms.keys()
302 307 else:
303 308 return []
304 309
305 310 if event.symbol == '-':
306 311 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
307 312 # jump in directory history by number
308 313 fmt = '-%0' + width_dh +'d [%s]'
309 314 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
310 315 if len(ents) > 1:
311 316 return ents
312 317 return []
313 318
314 319 if event.symbol.startswith('--'):
315 320 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
316 321
317 322 # Expand ~ in path and normalize directory separators.
318 323 relpath, tilde_expand, tilde_val = expand_user(relpath)
319 324 relpath = relpath.replace('\\','/')
320 325
321 326 found = []
322 327 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
323 328 if os.path.isdir(f)]:
324 329 if ' ' in d:
325 330 # we don't want to deal with any of that, complex code
326 331 # for this is elsewhere
327 332 raise TryNext
328 333
329 334 found.append(d)
330 335
331 336 if not found:
332 337 if os.path.isdir(relpath):
333 338 return [compress_user(relpath, tilde_expand, tilde_val)]
334 339
335 340 # if no completions so far, try bookmarks
336 341 bks = self.db.get('bookmarks',{})
337 342 bkmatches = [s for s in bks if s.startswith(event.symbol)]
338 343 if bkmatches:
339 344 return bkmatches
340 345
341 346 raise TryNext
342 347
343 348 return [compress_user(p, tilde_expand, tilde_val) for p in found]
344 349
345 350 def reset_completer(self, event):
346 351 "A completer for %reset magic"
347 352 return '-f -s in out array dhist'.split()
@@ -1,738 +1,746 b''
1 1 # encoding: utf-8
2 2 """Tests for the IPython tab-completion machinery."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import os
8 8 import sys
9 9 import unittest
10 10
11 11 from contextlib import contextmanager
12 12
13 13 import nose.tools as nt
14 14
15 15 from traitlets.config.loader import Config
16 16 from IPython import get_ipython
17 17 from IPython.core import completer
18 18 from IPython.external.decorators import knownfailureif
19 19 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
20 20 from IPython.utils.generics import complete_object
21 21 from IPython.testing import decorators as dec
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Test functions
25 25 #-----------------------------------------------------------------------------
26 26
27 27 @contextmanager
28 28 def greedy_completion():
29 29 ip = get_ipython()
30 30 greedy_original = ip.Completer.greedy
31 31 try:
32 32 ip.Completer.greedy = True
33 33 yield
34 34 finally:
35 35 ip.Completer.greedy = greedy_original
36 36
37 37 def test_protect_filename():
38 38 if sys.platform == 'win32':
39 39 pairs = [('abc','abc'),
40 40 (' abc','" abc"'),
41 41 ('a bc','"a bc"'),
42 42 ('a bc','"a bc"'),
43 43 (' bc','" bc"'),
44 44 ]
45 45 else:
46 46 pairs = [('abc','abc'),
47 47 (' abc',r'\ abc'),
48 48 ('a bc',r'a\ bc'),
49 49 ('a bc',r'a\ \ bc'),
50 50 (' bc',r'\ \ bc'),
51 51 # On posix, we also protect parens and other special characters.
52 52 ('a(bc',r'a\(bc'),
53 53 ('a)bc',r'a\)bc'),
54 54 ('a( )bc',r'a\(\ \)bc'),
55 55 ('a[1]bc', r'a\[1\]bc'),
56 56 ('a{1}bc', r'a\{1\}bc'),
57 57 ('a#bc', r'a\#bc'),
58 58 ('a?bc', r'a\?bc'),
59 59 ('a=bc', r'a\=bc'),
60 60 ('a\\bc', r'a\\bc'),
61 61 ('a|bc', r'a\|bc'),
62 62 ('a;bc', r'a\;bc'),
63 63 ('a:bc', r'a\:bc'),
64 64 ("a'bc", r"a\'bc"),
65 65 ('a*bc', r'a\*bc'),
66 66 ('a"bc', r'a\"bc'),
67 67 ('a^bc', r'a\^bc'),
68 68 ('a&bc', r'a\&bc'),
69 69 ]
70 70 # run the actual tests
71 71 for s1, s2 in pairs:
72 72 s1p = completer.protect_filename(s1)
73 73 nt.assert_equal(s1p, s2)
74 74
75 75
76 76 def check_line_split(splitter, test_specs):
77 77 for part1, part2, split in test_specs:
78 78 cursor_pos = len(part1)
79 79 line = part1+part2
80 80 out = splitter.split_line(line, cursor_pos)
81 81 nt.assert_equal(out, split)
82 82
83 83
84 84 def test_line_split():
85 85 """Basic line splitter test with default specs."""
86 86 sp = completer.CompletionSplitter()
87 87 # The format of the test specs is: part1, part2, expected answer. Parts 1
88 88 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
89 89 # was at the end of part1. So an empty part2 represents someone hitting
90 90 # tab at the end of the line, the most common case.
91 91 t = [('run some/scrip', '', 'some/scrip'),
92 92 ('run scripts/er', 'ror.py foo', 'scripts/er'),
93 93 ('echo $HOM', '', 'HOM'),
94 94 ('print sys.pa', '', 'sys.pa'),
95 95 ('print(sys.pa', '', 'sys.pa'),
96 96 ("execfile('scripts/er", '', 'scripts/er'),
97 97 ('a[x.', '', 'x.'),
98 98 ('a[x.', 'y', 'x.'),
99 99 ('cd "some_file/', '', 'some_file/'),
100 100 ]
101 101 check_line_split(sp, t)
102 102 # Ensure splitting works OK with unicode by re-running the tests with
103 103 # all inputs turned into unicode
104 104 check_line_split(sp, [ map(str, p) for p in t] )
105 105
106 106
107 107 def test_custom_completion_error():
108 108 """Test that errors from custom attribute completers are silenced."""
109 109 ip = get_ipython()
110 110 class A(object): pass
111 111 ip.user_ns['a'] = A()
112 112
113 113 @complete_object.when_type(A)
114 114 def complete_A(a, existing_completions):
115 115 raise TypeError("this should be silenced")
116 116
117 117 ip.complete("a.")
118 118
119 119
120 120 def test_unicode_completions():
121 121 ip = get_ipython()
122 122 # Some strings that trigger different types of completion. Check them both
123 123 # in str and unicode forms
124 124 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
125 125 for t in s + list(map(str, s)):
126 126 # We don't need to check exact completion values (they may change
127 127 # depending on the state of the namespace, but at least no exceptions
128 128 # should be thrown and the return value should be a pair of text, list
129 129 # values.
130 130 text, matches = ip.complete(t)
131 131 nt.assert_true(isinstance(text, str))
132 132 nt.assert_true(isinstance(matches, list))
133 133
134 134 def test_latex_completions():
135 135 from IPython.core.latex_symbols import latex_symbols
136 136 import random
137 137 ip = get_ipython()
138 138 # Test some random unicode symbols
139 139 keys = random.sample(latex_symbols.keys(), 10)
140 140 for k in keys:
141 141 text, matches = ip.complete(k)
142 142 nt.assert_equal(len(matches),1)
143 143 nt.assert_equal(text, k)
144 144 nt.assert_equal(matches[0], latex_symbols[k])
145 145 # Test a more complex line
146 146 text, matches = ip.complete(u'print(\\alpha')
147 147 nt.assert_equal(text, u'\\alpha')
148 148 nt.assert_equal(matches[0], latex_symbols['\\alpha'])
149 149 # Test multiple matching latex symbols
150 150 text, matches = ip.complete(u'\\al')
151 151 nt.assert_in('\\alpha', matches)
152 152 nt.assert_in('\\aleph', matches)
153 153
154 154
155 155
156 156
157 157 def test_back_latex_completion():
158 158 ip = get_ipython()
159 159
160 160 # do not return more than 1 matches fro \beta, only the latex one.
161 161 name, matches = ip.complete('\\Ξ²')
162 162 nt.assert_equal(len(matches), 1)
163 163 nt.assert_equal(matches[0], '\\beta')
164 164
165 165 def test_back_unicode_completion():
166 166 ip = get_ipython()
167 167
168 168 name, matches = ip.complete('\\β…€')
169 169 nt.assert_equal(len(matches), 1)
170 170 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
171 171
172 172
173 173 def test_forward_unicode_completion():
174 174 ip = get_ipython()
175 175
176 176 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
177 177 nt.assert_equal(len(matches), 1)
178 178 nt.assert_equal(matches[0], 'β…€')
179 179
180 180 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
181 181 def test_no_ascii_back_completion():
182 182 ip = get_ipython()
183 183 with TemporaryWorkingDirectory(): # Avoid any filename completions
184 184 # single ascii letter that don't have yet completions
185 185 for letter in 'jJ' :
186 186 name, matches = ip.complete('\\'+letter)
187 187 nt.assert_equal(matches, [])
188 188
189 189
190 190
191 191
192 192 class CompletionSplitterTestCase(unittest.TestCase):
193 193 def setUp(self):
194 194 self.sp = completer.CompletionSplitter()
195 195
196 196 def test_delim_setting(self):
197 197 self.sp.delims = ' '
198 198 nt.assert_equal(self.sp.delims, ' ')
199 199 nt.assert_equal(self.sp._delim_expr, '[\ ]')
200 200
201 201 def test_spaces(self):
202 202 """Test with only spaces as split chars."""
203 203 self.sp.delims = ' '
204 204 t = [('foo', '', 'foo'),
205 205 ('run foo', '', 'foo'),
206 206 ('run foo', 'bar', 'foo'),
207 207 ]
208 208 check_line_split(self.sp, t)
209 209
210 210
211 211 def test_has_open_quotes1():
212 212 for s in ["'", "'''", "'hi' '"]:
213 213 nt.assert_equal(completer.has_open_quotes(s), "'")
214 214
215 215
216 216 def test_has_open_quotes2():
217 217 for s in ['"', '"""', '"hi" "']:
218 218 nt.assert_equal(completer.has_open_quotes(s), '"')
219 219
220 220
221 221 def test_has_open_quotes3():
222 222 for s in ["''", "''' '''", "'hi' 'ipython'"]:
223 223 nt.assert_false(completer.has_open_quotes(s))
224 224
225 225
226 226 def test_has_open_quotes4():
227 227 for s in ['""', '""" """', '"hi" "ipython"']:
228 228 nt.assert_false(completer.has_open_quotes(s))
229 229
230 230
231 231 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
232 232 def test_abspath_file_completions():
233 233 ip = get_ipython()
234 234 with TemporaryDirectory() as tmpdir:
235 235 prefix = os.path.join(tmpdir, 'foo')
236 236 suffixes = ['1', '2']
237 237 names = [prefix+s for s in suffixes]
238 238 for n in names:
239 239 open(n, 'w').close()
240 240
241 241 # Check simple completion
242 242 c = ip.complete(prefix)[1]
243 243 nt.assert_equal(c, names)
244 244
245 245 # Now check with a function call
246 246 cmd = 'a = f("%s' % prefix
247 247 c = ip.complete(prefix, cmd)[1]
248 248 comp = [prefix+s for s in suffixes]
249 249 nt.assert_equal(c, comp)
250 250
251 251
252 252 def test_local_file_completions():
253 253 ip = get_ipython()
254 254 with TemporaryWorkingDirectory():
255 255 prefix = './foo'
256 256 suffixes = ['1', '2']
257 257 names = [prefix+s for s in suffixes]
258 258 for n in names:
259 259 open(n, 'w').close()
260 260
261 261 # Check simple completion
262 262 c = ip.complete(prefix)[1]
263 263 nt.assert_equal(c, names)
264 264
265 265 # Now check with a function call
266 266 cmd = 'a = f("%s' % prefix
267 267 c = ip.complete(prefix, cmd)[1]
268 268 comp = set(prefix+s for s in suffixes)
269 269 nt.assert_true(comp.issubset(set(c)))
270 270
271 271
272 272 def test_greedy_completions():
273 273 ip = get_ipython()
274 274 ip.ex('a=list(range(5))')
275 275 _,c = ip.complete('.',line='a[0].')
276 276 nt.assert_false('.real' in c,
277 277 "Shouldn't have completed on a[0]: %s"%c)
278 278 with greedy_completion():
279 279 def _(line, cursor_pos, expect, message):
280 280 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
281 281 nt.assert_in(expect, c, message%c)
282 282
283 283 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s"
284 284 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s"
285 285
286 286 if sys.version_info > (3,4):
287 287 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s"
288 288
289 289
290 290
291 291 def test_omit__names():
292 292 # also happens to test IPCompleter as a configurable
293 293 ip = get_ipython()
294 294 ip._hidden_attr = 1
295 295 ip._x = {}
296 296 c = ip.Completer
297 297 ip.ex('ip=get_ipython()')
298 298 cfg = Config()
299 299 cfg.IPCompleter.omit__names = 0
300 300 c.update_config(cfg)
301 301 s,matches = c.complete('ip.')
302 302 nt.assert_in('ip.__str__', matches)
303 303 nt.assert_in('ip._hidden_attr', matches)
304 304 cfg = Config()
305 305 cfg.IPCompleter.omit__names = 1
306 306 c.update_config(cfg)
307 307 s,matches = c.complete('ip.')
308 308 nt.assert_not_in('ip.__str__', matches)
309 309 nt.assert_in('ip._hidden_attr', matches)
310 310 cfg = Config()
311 311 cfg.IPCompleter.omit__names = 2
312 312 c.update_config(cfg)
313 313 s,matches = c.complete('ip.')
314 314 nt.assert_not_in('ip.__str__', matches)
315 315 nt.assert_not_in('ip._hidden_attr', matches)
316 316 s,matches = c.complete('ip._x.')
317 317 nt.assert_in('ip._x.keys', matches)
318 318 del ip._hidden_attr
319 319
320 320
321 321 def test_limit_to__all__False_ok():
322 322 ip = get_ipython()
323 323 c = ip.Completer
324 324 ip.ex('class D: x=24')
325 325 ip.ex('d=D()')
326 326 cfg = Config()
327 327 cfg.IPCompleter.limit_to__all__ = False
328 328 c.update_config(cfg)
329 329 s, matches = c.complete('d.')
330 330 nt.assert_in('d.x', matches)
331 331
332 332
333 333 def test_get__all__entries_ok():
334 334 class A(object):
335 335 __all__ = ['x', 1]
336 336 words = completer.get__all__entries(A())
337 337 nt.assert_equal(words, ['x'])
338 338
339 339
340 340 def test_get__all__entries_no__all__ok():
341 341 class A(object):
342 342 pass
343 343 words = completer.get__all__entries(A())
344 344 nt.assert_equal(words, [])
345 345
346 346
347 347 def test_func_kw_completions():
348 348 ip = get_ipython()
349 349 c = ip.Completer
350 350 ip.ex('def myfunc(a=1,b=2): return a+b')
351 351 s, matches = c.complete(None, 'myfunc(1,b')
352 352 nt.assert_in('b=', matches)
353 353 # Simulate completing with cursor right after b (pos==10):
354 354 s, matches = c.complete(None, 'myfunc(1,b)', 10)
355 355 nt.assert_in('b=', matches)
356 356 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
357 357 nt.assert_in('b=', matches)
358 358 #builtin function
359 359 s, matches = c.complete(None, 'min(k, k')
360 360 nt.assert_in('key=', matches)
361 361
362 362
363 363 def test_default_arguments_from_docstring():
364 364 ip = get_ipython()
365 365 c = ip.Completer
366 366 kwd = c._default_arguments_from_docstring(
367 367 'min(iterable[, key=func]) -> value')
368 368 nt.assert_equal(kwd, ['key'])
369 369 #with cython type etc
370 370 kwd = c._default_arguments_from_docstring(
371 371 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
372 372 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
373 373 #white spaces
374 374 kwd = c._default_arguments_from_docstring(
375 375 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
376 376 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
377 377
378 378 def test_line_magics():
379 379 ip = get_ipython()
380 380 c = ip.Completer
381 381 s, matches = c.complete(None, 'lsmag')
382 382 nt.assert_in('%lsmagic', matches)
383 383 s, matches = c.complete(None, '%lsmag')
384 384 nt.assert_in('%lsmagic', matches)
385 385
386 386
387 387 def test_cell_magics():
388 388 from IPython.core.magic import register_cell_magic
389 389
390 390 @register_cell_magic
391 391 def _foo_cellm(line, cell):
392 392 pass
393 393
394 394 ip = get_ipython()
395 395 c = ip.Completer
396 396
397 397 s, matches = c.complete(None, '_foo_ce')
398 398 nt.assert_in('%%_foo_cellm', matches)
399 399 s, matches = c.complete(None, '%%_foo_ce')
400 400 nt.assert_in('%%_foo_cellm', matches)
401 401
402 402
403 403 def test_line_cell_magics():
404 404 from IPython.core.magic import register_line_cell_magic
405 405
406 406 @register_line_cell_magic
407 407 def _bar_cellm(line, cell):
408 408 pass
409 409
410 410 ip = get_ipython()
411 411 c = ip.Completer
412 412
413 413 # The policy here is trickier, see comments in completion code. The
414 414 # returned values depend on whether the user passes %% or not explicitly,
415 415 # and this will show a difference if the same name is both a line and cell
416 416 # magic.
417 417 s, matches = c.complete(None, '_bar_ce')
418 418 nt.assert_in('%_bar_cellm', matches)
419 419 nt.assert_in('%%_bar_cellm', matches)
420 420 s, matches = c.complete(None, '%_bar_ce')
421 421 nt.assert_in('%_bar_cellm', matches)
422 422 nt.assert_in('%%_bar_cellm', matches)
423 423 s, matches = c.complete(None, '%%_bar_ce')
424 424 nt.assert_not_in('%_bar_cellm', matches)
425 425 nt.assert_in('%%_bar_cellm', matches)
426 426
427 427
428 428 def test_magic_completion_order():
429 429
430 430 ip = get_ipython()
431 431 c = ip.Completer
432 432
433 433 # Test ordering of magics and non-magics with the same name
434 434 # We want the non-magic first
435 435
436 436 # Before importing matplotlib, there should only be one option:
437 437
438 438 text, matches = c.complete('mat')
439 439 nt.assert_equal(matches, ["%matplotlib"])
440 440
441 441
442 442 ip.run_cell("matplotlib = 1") # introduce name into namespace
443 443
444 444 # After the import, there should be two options, ordered like this:
445 445 text, matches = c.complete('mat')
446 446 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
447 447
448 448
449 449 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
450 450
451 451 # Order of user variable and line and cell magics with same name:
452 452 text, matches = c.complete('timeit')
453 453 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
454 454
455 455
456 456 def test_dict_key_completion_string():
457 457 """Test dictionary key completion for string keys"""
458 458 ip = get_ipython()
459 459 complete = ip.Completer.complete
460 460
461 461 ip.user_ns['d'] = {'abc': None}
462 462
463 463 # check completion at different stages
464 464 _, matches = complete(line_buffer="d[")
465 465 nt.assert_in("'abc'", matches)
466 466 nt.assert_not_in("'abc']", matches)
467 467
468 468 _, matches = complete(line_buffer="d['")
469 469 nt.assert_in("abc", matches)
470 470 nt.assert_not_in("abc']", matches)
471 471
472 472 _, matches = complete(line_buffer="d['a")
473 473 nt.assert_in("abc", matches)
474 474 nt.assert_not_in("abc']", matches)
475 475
476 476 # check use of different quoting
477 477 _, matches = complete(line_buffer="d[\"")
478 478 nt.assert_in("abc", matches)
479 479 nt.assert_not_in('abc\"]', matches)
480 480
481 481 _, matches = complete(line_buffer="d[\"a")
482 482 nt.assert_in("abc", matches)
483 483 nt.assert_not_in('abc\"]', matches)
484 484
485 485 # check sensitivity to following context
486 486 _, matches = complete(line_buffer="d[]", cursor_pos=2)
487 487 nt.assert_in("'abc'", matches)
488 488
489 489 _, matches = complete(line_buffer="d['']", cursor_pos=3)
490 490 nt.assert_in("abc", matches)
491 491 nt.assert_not_in("abc'", matches)
492 492 nt.assert_not_in("abc']", matches)
493 493
494 494 # check multiple solutions are correctly returned and that noise is not
495 495 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
496 496 5: None}
497 497
498 498 _, matches = complete(line_buffer="d['a")
499 499 nt.assert_in("abc", matches)
500 500 nt.assert_in("abd", matches)
501 501 nt.assert_not_in("bad", matches)
502 502 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
503 503
504 504 # check escaping and whitespace
505 505 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
506 506 _, matches = complete(line_buffer="d['a")
507 507 nt.assert_in("a\\nb", matches)
508 508 nt.assert_in("a\\'b", matches)
509 509 nt.assert_in("a\"b", matches)
510 510 nt.assert_in("a word", matches)
511 511 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
512 512
513 513 # - can complete on non-initial word of the string
514 514 _, matches = complete(line_buffer="d['a w")
515 515 nt.assert_in("word", matches)
516 516
517 517 # - understands quote escaping
518 518 _, matches = complete(line_buffer="d['a\\'")
519 519 nt.assert_in("b", matches)
520 520
521 521 # - default quoting should work like repr
522 522 _, matches = complete(line_buffer="d[")
523 523 nt.assert_in("\"a'b\"", matches)
524 524
525 525 # - when opening quote with ", possible to match with unescaped apostrophe
526 526 _, matches = complete(line_buffer="d[\"a'")
527 527 nt.assert_in("b", matches)
528 528
529 529 # need to not split at delims that readline won't split at
530 530 if '-' not in ip.Completer.splitter.delims:
531 531 ip.user_ns['d'] = {'before-after': None}
532 532 _, matches = complete(line_buffer="d['before-af")
533 533 nt.assert_in('before-after', matches)
534 534
535 535 def test_dict_key_completion_contexts():
536 536 """Test expression contexts in which dict key completion occurs"""
537 537 ip = get_ipython()
538 538 complete = ip.Completer.complete
539 539 d = {'abc': None}
540 540 ip.user_ns['d'] = d
541 541
542 542 class C:
543 543 data = d
544 544 ip.user_ns['C'] = C
545 545 ip.user_ns['get'] = lambda: d
546 546
547 547 def assert_no_completion(**kwargs):
548 548 _, matches = complete(**kwargs)
549 549 nt.assert_not_in('abc', matches)
550 550 nt.assert_not_in('abc\'', matches)
551 551 nt.assert_not_in('abc\']', matches)
552 552 nt.assert_not_in('\'abc\'', matches)
553 553 nt.assert_not_in('\'abc\']', matches)
554 554
555 555 def assert_completion(**kwargs):
556 556 _, matches = complete(**kwargs)
557 557 nt.assert_in("'abc'", matches)
558 558 nt.assert_not_in("'abc']", matches)
559 559
560 560 # no completion after string closed, even if reopened
561 561 assert_no_completion(line_buffer="d['a'")
562 562 assert_no_completion(line_buffer="d[\"a\"")
563 563 assert_no_completion(line_buffer="d['a' + ")
564 564 assert_no_completion(line_buffer="d['a' + '")
565 565
566 566 # completion in non-trivial expressions
567 567 assert_completion(line_buffer="+ d[")
568 568 assert_completion(line_buffer="(d[")
569 569 assert_completion(line_buffer="C.data[")
570 570
571 571 # greedy flag
572 572 def assert_completion(**kwargs):
573 573 _, matches = complete(**kwargs)
574 574 nt.assert_in("get()['abc']", matches)
575 575
576 576 assert_no_completion(line_buffer="get()[")
577 577 with greedy_completion():
578 578 assert_completion(line_buffer="get()[")
579 579 assert_completion(line_buffer="get()['")
580 580 assert_completion(line_buffer="get()['a")
581 581 assert_completion(line_buffer="get()['ab")
582 582 assert_completion(line_buffer="get()['abc")
583 583
584 584
585 585
586 586 def test_dict_key_completion_bytes():
587 587 """Test handling of bytes in dict key completion"""
588 588 ip = get_ipython()
589 589 complete = ip.Completer.complete
590 590
591 591 ip.user_ns['d'] = {'abc': None, b'abd': None}
592 592
593 593 _, matches = complete(line_buffer="d[")
594 594 nt.assert_in("'abc'", matches)
595 595 nt.assert_in("b'abd'", matches)
596 596
597 597 if False: # not currently implemented
598 598 _, matches = complete(line_buffer="d[b")
599 599 nt.assert_in("b'abd'", matches)
600 600 nt.assert_not_in("b'abc'", matches)
601 601
602 602 _, matches = complete(line_buffer="d[b'")
603 603 nt.assert_in("abd", matches)
604 604 nt.assert_not_in("abc", matches)
605 605
606 606 _, matches = complete(line_buffer="d[B'")
607 607 nt.assert_in("abd", matches)
608 608 nt.assert_not_in("abc", matches)
609 609
610 610 _, matches = complete(line_buffer="d['")
611 611 nt.assert_in("abc", matches)
612 612 nt.assert_not_in("abd", matches)
613 613
614 614
615 615 def test_dict_key_completion_unicode_py3():
616 616 """Test handling of unicode in dict key completion"""
617 617 ip = get_ipython()
618 618 complete = ip.Completer.complete
619 619
620 620 ip.user_ns['d'] = {u'a\u05d0': None}
621 621
622 622 # query using escape
623 623 if sys.platform != 'win32':
624 624 # Known failure on Windows
625 625 _, matches = complete(line_buffer="d['a\\u05d0")
626 626 nt.assert_in("u05d0", matches) # tokenized after \\
627 627
628 628 # query using character
629 629 _, matches = complete(line_buffer="d['a\u05d0")
630 630 nt.assert_in(u"a\u05d0", matches)
631 631
632 632 with greedy_completion():
633 633 # query using escape
634 634 _, matches = complete(line_buffer="d['a\\u05d0")
635 635 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
636 636
637 637 # query using character
638 638 _, matches = complete(line_buffer="d['a\u05d0")
639 639 nt.assert_in(u"d['a\u05d0']", matches)
640 640
641 641
642 642
643 643 @dec.skip_without('numpy')
644 644 def test_struct_array_key_completion():
645 645 """Test dict key completion applies to numpy struct arrays"""
646 646 import numpy
647 647 ip = get_ipython()
648 648 complete = ip.Completer.complete
649 649 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
650 650 _, matches = complete(line_buffer="d['")
651 651 nt.assert_in("hello", matches)
652 652 nt.assert_in("world", matches)
653 653 # complete on the numpy struct itself
654 654 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
655 655 ('my_data', '>f4', 5)])
656 656 x = numpy.zeros(2, dtype=dt)
657 657 ip.user_ns['d'] = x[1]
658 658 _, matches = complete(line_buffer="d['")
659 659 nt.assert_in("my_head", matches)
660 660 nt.assert_in("my_data", matches)
661 661 # complete on a nested level
662 662 with greedy_completion():
663 663 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
664 664 _, matches = complete(line_buffer="d[1]['my_head']['")
665 665 nt.assert_true(any(["my_dt" in m for m in matches]))
666 666 nt.assert_true(any(["my_df" in m for m in matches]))
667 667
668 668
669 669 @dec.skip_without('pandas')
670 670 def test_dataframe_key_completion():
671 671 """Test dict key completion applies to pandas DataFrames"""
672 672 import pandas
673 673 ip = get_ipython()
674 674 complete = ip.Completer.complete
675 675 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
676 676 _, matches = complete(line_buffer="d['")
677 677 nt.assert_in("hello", matches)
678 678 nt.assert_in("world", matches)
679 679
680 680
681 681 def test_dict_key_completion_invalids():
682 682 """Smoke test cases dict key completion can't handle"""
683 683 ip = get_ipython()
684 684 complete = ip.Completer.complete
685 685
686 686 ip.user_ns['no_getitem'] = None
687 687 ip.user_ns['no_keys'] = []
688 688 ip.user_ns['cant_call_keys'] = dict
689 689 ip.user_ns['empty'] = {}
690 690 ip.user_ns['d'] = {'abc': 5}
691 691
692 692 _, matches = complete(line_buffer="no_getitem['")
693 693 _, matches = complete(line_buffer="no_keys['")
694 694 _, matches = complete(line_buffer="cant_call_keys['")
695 695 _, matches = complete(line_buffer="empty['")
696 696 _, matches = complete(line_buffer="name_error['")
697 697 _, matches = complete(line_buffer="d['\\") # incomplete escape
698 698
699 699 class KeyCompletable(object):
700 700 def __init__(self, things=()):
701 701 self.things = things
702 702
703 703 def _ipython_key_completions_(self):
704 704 return list(self.things)
705 705
706 706 def test_object_key_completion():
707 707 ip = get_ipython()
708 708 ip.user_ns['key_completable'] = KeyCompletable(['qwerty', 'qwick'])
709 709
710 710 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
711 711 nt.assert_in('qwerty', matches)
712 712 nt.assert_in('qwick', matches)
713 713
714 714
715 def test_tryimport():
716 """
717 Test that try-import don't crash on trailing dot, and import modules before
718 """
719 from IPython.core.completerlib import try_import
720 assert(try_import("IPython."))
721
722
715 723 def test_aimport_module_completer():
716 724 ip = get_ipython()
717 725 _, matches = ip.complete('i', '%aimport i')
718 726 nt.assert_in('io', matches)
719 727 nt.assert_not_in('int', matches)
720 728
721 729 def test_nested_import_module_completer():
722 730 ip = get_ipython()
723 731 _, matches = ip.complete(None, 'import IPython.co', 17)
724 732 nt.assert_in('IPython.core', matches)
725 733 nt.assert_not_in('import IPython.core', matches)
726 734 nt.assert_not_in('IPython.display', matches)
727 735
728 736 def test_import_module_completer():
729 737 ip = get_ipython()
730 738 _, matches = ip.complete('i', 'import i')
731 739 nt.assert_in('io', matches)
732 740 nt.assert_not_in('int', matches)
733 741
734 742 def test_from_module_completer():
735 743 ip = get_ipython()
736 744 _, matches = ip.complete('B', 'from io import B', 16)
737 745 nt.assert_in('BytesIO', matches)
738 746 nt.assert_not_in('BaseException', matches)
General Comments 0
You need to be logged in to leave comments. Login now