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