##// END OF EJS Templates
Added test_dir2 for the dir2 (bonus) tests...
Tim Couper -
Show More
@@ -0,0 +1,51 b''
1 import nose.tools as nt
2 from IPython.utils.dir2 import dir2
3
4
5 class Base(object):
6 x = 1
7 z = 23
8
9
10 def test_base():
11 res = dir2(Base())
12 assert ('x' in res)
13 assert ('z' in res)
14 assert ('y' not in res)
15 assert ('__class__' in res)
16 nt.assert_equal(res.count('x'), 2) # duplicates
17 nt.assert_equal(res.count('__class__'), 4) # duplicates
18
19 def test_SubClass():
20
21 class SubClass(Base):
22 y = 2
23
24 res = dir2(SubClass())
25 assert ('y' in res)
26 nt.assert_equal(res.count('y'), 2) # duplicates,
27 nt.assert_equal(res.count('x'), 3) # duplicates, but fewer than above!
28
29
30 def test_SubClass_with_trait_names_method():
31
32 class SubClass(Base):
33 y = 2
34 def trait_names(self):
35 return ['t', 'umbrella']
36
37 res = dir2(SubClass())
38 assert('trait_names' in res)
39 assert('umbrella' in res)
40 nt.assert_equal(res.count('t'), 1)
41
42
43 def test_SubClass_with_trait_names_attr():
44 # usecase: trait_names is used in a class describing psychological classification
45
46 class SubClass(Base):
47 y = 2
48 trait_names = 44
49
50 res = dir2(SubClass())
51 assert('trait_names' in res)
@@ -1,915 +1,916 b''
1 """Word completion for IPython.
1 """Word completion for IPython.
2
2
3 This module is a fork of the rlcompleter module in the Python standard
3 This module is a fork of the rlcompleter module in the Python standard
4 library. The original enhancements made to rlcompleter have been sent
4 library. The original enhancements made to rlcompleter have been sent
5 upstream and were accepted as of Python 2.3, but we need a lot more
5 upstream and were accepted as of Python 2.3, but we need a lot more
6 functionality specific to IPython, so this module will continue to live as an
6 functionality specific to IPython, so this module will continue to live as an
7 IPython-specific utility.
7 IPython-specific utility.
8
8
9 Original rlcompleter documentation:
9 Original rlcompleter documentation:
10
10
11 This requires the latest extension to the readline module (the
11 This requires the latest extension to the readline module (the
12 completes keywords, built-ins and globals in __main__; when completing
12 completes keywords, built-ins and globals in __main__; when completing
13 NAME.NAME..., it evaluates (!) the expression up to the last dot and
13 NAME.NAME..., it evaluates (!) the expression up to the last dot and
14 completes its attributes.
14 completes its attributes.
15
15
16 It's very cool to do "import string" type "string.", hit the
16 It's very cool to do "import string" type "string.", hit the
17 completion key (twice), and see the list of names defined by the
17 completion key (twice), and see the list of names defined by the
18 string module!
18 string module!
19
19
20 Tip: to use the tab key as the completion key, call
20 Tip: to use the tab key as the completion key, call
21
21
22 readline.parse_and_bind("tab: complete")
22 readline.parse_and_bind("tab: complete")
23
23
24 Notes:
24 Notes:
25
25
26 - Exceptions raised by the completer function are *ignored* (and
26 - Exceptions raised by the completer function are *ignored* (and
27 generally cause the completion to fail). This is a feature -- since
27 generally cause the completion to fail). This is a feature -- since
28 readline sets the tty device in raw (or cbreak) mode, printing a
28 readline sets the tty device in raw (or cbreak) mode, printing a
29 traceback wouldn't work well without some complicated hoopla to save,
29 traceback wouldn't work well without some complicated hoopla to save,
30 reset and restore the tty state.
30 reset and restore the tty state.
31
31
32 - The evaluation of the NAME.NAME... form may cause arbitrary
32 - The evaluation of the NAME.NAME... form may cause arbitrary
33 application defined code to be executed if an object with a
33 application defined code to be executed if an object with a
34 __getattr__ hook is found. Since it is the responsibility of the
34 __getattr__ hook is found. Since it is the responsibility of the
35 application (or the user) to enable this feature, I consider this an
35 application (or the user) to enable this feature, I consider this an
36 acceptable risk. More complicated expressions (e.g. function calls or
36 acceptable risk. More complicated expressions (e.g. function calls or
37 indexing operations) are *not* evaluated.
37 indexing operations) are *not* evaluated.
38
38
39 - GNU readline is also used by the built-in functions input() and
39 - GNU readline is also used by the built-in functions input() and
40 raw_input(), and thus these also benefit/suffer from the completer
40 raw_input(), and thus these also benefit/suffer from the completer
41 features. Clearly an interactive application can benefit by
41 features. Clearly an interactive application can benefit by
42 specifying its own completer function and using raw_input() for all
42 specifying its own completer function and using raw_input() for all
43 its input.
43 its input.
44
44
45 - When the original stdin is not a tty device, GNU readline is never
45 - When the original stdin is not a tty device, GNU readline is never
46 used, and this module (and the readline module) are silently inactive.
46 used, and this module (and the readline module) are silently inactive.
47 """
47 """
48
48
49 #*****************************************************************************
49 #*****************************************************************************
50 #
50 #
51 # Since this file is essentially a minimally modified copy of the rlcompleter
51 # Since this file is essentially a minimally modified copy of the rlcompleter
52 # module which is part of the standard Python distribution, I assume that the
52 # module which is part of the standard Python distribution, I assume that the
53 # proper procedure is to maintain its copyright as belonging to the Python
53 # proper procedure is to maintain its copyright as belonging to the Python
54 # Software Foundation (in addition to my own, for all new code).
54 # Software Foundation (in addition to my own, for all new code).
55 #
55 #
56 # Copyright (C) 2008-2011 IPython Development Team
56 # Copyright (C) 2008-2011 IPython Development Team
57 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
57 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
58 # Copyright (C) 2001 Python Software Foundation, www.python.org
58 # Copyright (C) 2001 Python Software Foundation, www.python.org
59 #
59 #
60 # Distributed under the terms of the BSD License. The full license is in
60 # Distributed under the terms of the BSD License. The full license is in
61 # the file COPYING, distributed as part of this software.
61 # the file COPYING, distributed as part of this software.
62 #
62 #
63 #*****************************************************************************
63 #*****************************************************************************
64 from __future__ import print_function
64 from __future__ import print_function
65
65
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67 # Imports
67 # Imports
68 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
69
69
70 import __builtin__
70 import __builtin__
71 import __main__
71 import __main__
72 import glob
72 import glob
73 import inspect
73 import inspect
74 import itertools
74 import itertools
75 import keyword
75 import keyword
76 import os
76 import os
77 import re
77 import re
78 import shlex
78 import shlex
79 import sys
79 import sys
80
80
81 from IPython.config.configurable import Configurable
81 from IPython.config.configurable import Configurable
82 from IPython.core.error import TryNext
82 from IPython.core.error import TryNext
83 from IPython.core.prefilter import ESC_MAGIC
83 from IPython.core.prefilter import ESC_MAGIC
84 from IPython.utils import generics
84 from IPython.utils import generics
85 from IPython.utils import io
85 from IPython.utils import io
86 from IPython.utils.dir2 import dir2
86 from IPython.utils.dir2 import dir2
87 from IPython.utils.process import arg_split
87 from IPython.utils.process import arg_split
88 from IPython.utils.traitlets import CBool, Enum
88 from IPython.utils.traitlets import CBool, Enum
89
89
90 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
91 # Globals
91 # Globals
92 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
93
93
94 # Public API
94 # Public API
95 __all__ = ['Completer','IPCompleter']
95 __all__ = ['Completer','IPCompleter']
96
96
97 if sys.platform == 'win32':
97 if sys.platform == 'win32':
98 PROTECTABLES = ' '
98 PROTECTABLES = ' '
99 else:
99 else:
100 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
100 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
101
101
102 #-----------------------------------------------------------------------------
102 #-----------------------------------------------------------------------------
103 # Main functions and classes
103 # Main functions and classes
104 #-----------------------------------------------------------------------------
104 #-----------------------------------------------------------------------------
105
105
106 def has_open_quotes(s):
106 def has_open_quotes(s):
107 """Return whether a string has open quotes.
107 """Return whether a string has open quotes.
108
108
109 This simply counts whether the number of quote characters of either type in
109 This simply counts whether the number of quote characters of either type in
110 the string is odd.
110 the string is odd.
111
111
112 Returns
112 Returns
113 -------
113 -------
114 If there is an open quote, the quote character is returned. Else, return
114 If there is an open quote, the quote character is returned. Else, return
115 False.
115 False.
116 """
116 """
117 # We check " first, then ', so complex cases with nested quotes will get
117 # We check " first, then ', so complex cases with nested quotes will get
118 # the " to take precedence.
118 # the " to take precedence.
119 if s.count('"') % 2:
119 if s.count('"') % 2:
120 return '"'
120 return '"'
121 elif s.count("'") % 2:
121 elif s.count("'") % 2:
122 return "'"
122 return "'"
123 else:
123 else:
124 return False
124 return False
125
125
126
126
127 def protect_filename(s):
127 def protect_filename(s):
128 """Escape a string to protect certain characters."""
128 """Escape a string to protect certain characters."""
129
129
130 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
130 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
131 for ch in s])
131 for ch in s])
132
132
133 def expand_user(path):
133 def expand_user(path):
134 """Expand '~'-style usernames in strings.
134 """Expand '~'-style usernames in strings.
135
135
136 This is similar to :func:`os.path.expanduser`, but it computes and returns
136 This is similar to :func:`os.path.expanduser`, but it computes and returns
137 extra information that will be useful if the input was being used in
137 extra information that will be useful if the input was being used in
138 computing completions, and you wish to return the completions with the
138 computing completions, and you wish to return the completions with the
139 original '~' instead of its expanded value.
139 original '~' instead of its expanded value.
140
140
141 Parameters
141 Parameters
142 ----------
142 ----------
143 path : str
143 path : str
144 String to be expanded. If no ~ is present, the output is the same as the
144 String to be expanded. If no ~ is present, the output is the same as the
145 input.
145 input.
146
146
147 Returns
147 Returns
148 -------
148 -------
149 newpath : str
149 newpath : str
150 Result of ~ expansion in the input path.
150 Result of ~ expansion in the input path.
151 tilde_expand : bool
151 tilde_expand : bool
152 Whether any expansion was performed or not.
152 Whether any expansion was performed or not.
153 tilde_val : str
153 tilde_val : str
154 The value that ~ was replaced with.
154 The value that ~ was replaced with.
155 """
155 """
156 # Default values
156 # Default values
157 tilde_expand = False
157 tilde_expand = False
158 tilde_val = ''
158 tilde_val = ''
159 newpath = path
159 newpath = path
160
160
161 if path.startswith('~'):
161 if path.startswith('~'):
162 tilde_expand = True
162 tilde_expand = True
163 rest = len(path)-1
163 rest = len(path)-1
164 newpath = os.path.expanduser(path)
164 newpath = os.path.expanduser(path)
165 if rest:
165 if rest:
166 tilde_val = newpath[:-rest]
166 tilde_val = newpath[:-rest]
167 else:
167 else:
168 tilde_val = newpath
168 tilde_val = newpath
169
169
170 return newpath, tilde_expand, tilde_val
170 return newpath, tilde_expand, tilde_val
171
171
172
172
173 def compress_user(path, tilde_expand, tilde_val):
173 def compress_user(path, tilde_expand, tilde_val):
174 """Does the opposite of expand_user, with its outputs.
174 """Does the opposite of expand_user, with its outputs.
175 """
175 """
176 if tilde_expand:
176 if tilde_expand:
177 return path.replace(tilde_val, '~')
177 return path.replace(tilde_val, '~')
178 else:
178 else:
179 return path
179 return path
180
180
181 class Bunch(object): pass
181 class Bunch(object): pass
182
182
183 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
183 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
184 GREEDY_DELIMS = ' \r\n'
184 GREEDY_DELIMS = ' \r\n'
185
185
186 class CompletionSplitter(object):
186 class CompletionSplitter(object):
187 """An object to split an input line in a manner similar to readline.
187 """An object to split an input line in a manner similar to readline.
188
188
189 By having our own implementation, we can expose readline-like completion in
189 By having our own implementation, we can expose readline-like completion in
190 a uniform manner to all frontends. This object only needs to be given the
190 a uniform manner to all frontends. This object only needs to be given the
191 line of text to be split and the cursor position on said line, and it
191 line of text to be split and the cursor position on said line, and it
192 returns the 'word' to be completed on at the cursor after splitting the
192 returns the 'word' to be completed on at the cursor after splitting the
193 entire line.
193 entire line.
194
194
195 What characters are used as splitting delimiters can be controlled by
195 What characters are used as splitting delimiters can be controlled by
196 setting the `delims` attribute (this is a property that internally
196 setting the `delims` attribute (this is a property that internally
197 automatically builds the necessary """
197 automatically builds the necessary """
198
198
199 # Private interface
199 # Private interface
200
200
201 # A string of delimiter characters. The default value makes sense for
201 # A string of delimiter characters. The default value makes sense for
202 # IPython's most typical usage patterns.
202 # IPython's most typical usage patterns.
203 _delims = DELIMS
203 _delims = DELIMS
204
204
205 # The expression (a normal string) to be compiled into a regular expression
205 # The expression (a normal string) to be compiled into a regular expression
206 # for actual splitting. We store it as an attribute mostly for ease of
206 # for actual splitting. We store it as an attribute mostly for ease of
207 # debugging, since this type of code can be so tricky to debug.
207 # debugging, since this type of code can be so tricky to debug.
208 _delim_expr = None
208 _delim_expr = None
209
209
210 # The regular expression that does the actual splitting
210 # The regular expression that does the actual splitting
211 _delim_re = None
211 _delim_re = None
212
212
213 def __init__(self, delims=None):
213 def __init__(self, delims=None):
214 delims = CompletionSplitter._delims if delims is None else delims
214 delims = CompletionSplitter._delims if delims is None else delims
215 self.set_delims(delims)
215 self.set_delims(delims)
216
216
217 def set_delims(self, delims):
217 def set_delims(self, delims):
218 """Set the delimiters for line splitting."""
218 """Set the delimiters for line splitting."""
219 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
219 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
220 self._delim_re = re.compile(expr)
220 self._delim_re = re.compile(expr)
221 self._delims = delims
221 self._delims = delims
222 self._delim_expr = expr
222 self._delim_expr = expr
223
223
224 def get_delims(self):
224 def get_delims(self):
225 """Return the string of delimiter characters."""
225 """Return the string of delimiter characters."""
226 return self._delims
226 return self._delims
227
227
228 def split_line(self, line, cursor_pos=None):
228 def split_line(self, line, cursor_pos=None):
229 """Split a line of text with a cursor at the given position.
229 """Split a line of text with a cursor at the given position.
230 """
230 """
231 l = line if cursor_pos is None else line[:cursor_pos]
231 l = line if cursor_pos is None else line[:cursor_pos]
232 return self._delim_re.split(l)[-1]
232 return self._delim_re.split(l)[-1]
233
233
234
234
235 class Completer(Configurable):
235 class Completer(Configurable):
236
236
237 greedy = CBool(False, config=True,
237 greedy = CBool(False, config=True,
238 help="""Activate greedy completion
238 help="""Activate greedy completion
239
239
240 This will enable completion on elements of lists, results of function calls, etc.,
240 This will enable completion on elements of lists, results of function calls, etc.,
241 but can be unsafe because the code is actually evaluated on TAB.
241 but can be unsafe because the code is actually evaluated on TAB.
242 """
242 """
243 )
243 )
244
244
245
245
246 def __init__(self, namespace=None, global_namespace=None, config=None, **kwargs):
246 def __init__(self, namespace=None, global_namespace=None, config=None, **kwargs):
247 """Create a new completer for the command line.
247 """Create a new completer for the command line.
248
248
249 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
249 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
250
250
251 If unspecified, the default namespace where completions are performed
251 If unspecified, the default namespace where completions are performed
252 is __main__ (technically, __main__.__dict__). Namespaces should be
252 is __main__ (technically, __main__.__dict__). Namespaces should be
253 given as dictionaries.
253 given as dictionaries.
254
254
255 An optional second namespace can be given. This allows the completer
255 An optional second namespace can be given. This allows the completer
256 to handle cases where both the local and global scopes need to be
256 to handle cases where both the local and global scopes need to be
257 distinguished.
257 distinguished.
258
258
259 Completer instances should be used as the completion mechanism of
259 Completer instances should be used as the completion mechanism of
260 readline via the set_completer() call:
260 readline via the set_completer() call:
261
261
262 readline.set_completer(Completer(my_namespace).complete)
262 readline.set_completer(Completer(my_namespace).complete)
263 """
263 """
264
264
265 # Don't bind to namespace quite yet, but flag whether the user wants a
265 # Don't bind to namespace quite yet, but flag whether the user wants a
266 # specific namespace or to use __main__.__dict__. This will allow us
266 # specific namespace or to use __main__.__dict__. This will allow us
267 # to bind to __main__.__dict__ at completion time, not now.
267 # to bind to __main__.__dict__ at completion time, not now.
268 if namespace is None:
268 if namespace is None:
269 self.use_main_ns = 1
269 self.use_main_ns = 1
270 else:
270 else:
271 self.use_main_ns = 0
271 self.use_main_ns = 0
272 self.namespace = namespace
272 self.namespace = namespace
273
273
274 # The global namespace, if given, can be bound directly
274 # The global namespace, if given, can be bound directly
275 if global_namespace is None:
275 if global_namespace is None:
276 self.global_namespace = {}
276 self.global_namespace = {}
277 else:
277 else:
278 self.global_namespace = global_namespace
278 self.global_namespace = global_namespace
279
279
280 super(Completer, self).__init__(config=config, **kwargs)
280 super(Completer, self).__init__(config=config, **kwargs)
281
281
282 def complete(self, text, state):
282 def complete(self, text, state):
283 """Return the next possible completion for 'text'.
283 """Return the next possible completion for 'text'.
284
284
285 This is called successively with state == 0, 1, 2, ... until it
285 This is called successively with state == 0, 1, 2, ... until it
286 returns None. The completion should begin with 'text'.
286 returns None. The completion should begin with 'text'.
287
287
288 """
288 """
289 if self.use_main_ns:
289 if self.use_main_ns:
290 self.namespace = __main__.__dict__
290 self.namespace = __main__.__dict__
291
291
292 if state == 0:
292 if state == 0:
293 if "." in text:
293 if "." in text:
294 self.matches = self.attr_matches(text)
294 self.matches = self.attr_matches(text)
295 else:
295 else:
296 self.matches = self.global_matches(text)
296 self.matches = self.global_matches(text)
297 try:
297 try:
298 return self.matches[state]
298 return self.matches[state]
299 except IndexError:
299 except IndexError:
300 return None
300 return None
301
301
302 def global_matches(self, text):
302 def global_matches(self, text):
303 """Compute matches when text is a simple name.
303 """Compute matches when text is a simple name.
304
304
305 Return a list of all keywords, built-in functions and names currently
305 Return a list of all keywords, built-in functions and names currently
306 defined in self.namespace or self.global_namespace that match.
306 defined in self.namespace or self.global_namespace that match.
307
307
308 """
308 """
309 #print 'Completer->global_matches, txt=%r' % text # dbg
309 #print 'Completer->global_matches, txt=%r' % text # dbg
310 matches = []
310 matches = []
311 match_append = matches.append
311 match_append = matches.append
312 n = len(text)
312 n = len(text)
313 for lst in [keyword.kwlist,
313 for lst in [keyword.kwlist,
314 __builtin__.__dict__.keys(),
314 __builtin__.__dict__.keys(),
315 self.namespace.keys(),
315 self.namespace.keys(),
316 self.global_namespace.keys()]:
316 self.global_namespace.keys()]:
317 for word in lst:
317 for word in lst:
318 if word[:n] == text and word != "__builtins__":
318 if word[:n] == text and word != "__builtins__":
319 match_append(word)
319 match_append(word)
320 return matches
320 return matches
321
321
322 def attr_matches(self, text):
322 def attr_matches(self, text):
323 """Compute matches when text contains a dot.
323 """Compute matches when text contains a dot.
324
324
325 Assuming the text is of the form NAME.NAME....[NAME], and is
325 Assuming the text is of the form NAME.NAME....[NAME], and is
326 evaluatable in self.namespace or self.global_namespace, it will be
326 evaluatable in self.namespace or self.global_namespace, it will be
327 evaluated and its attributes (as revealed by dir()) are used as
327 evaluated and its attributes (as revealed by dir()) are used as
328 possible completions. (For class instances, class members are are
328 possible completions. (For class instances, class members are are
329 also considered.)
329 also considered.)
330
330
331 WARNING: this can still invoke arbitrary C code, if an object
331 WARNING: this can still invoke arbitrary C code, if an object
332 with a __getattr__ hook is evaluated.
332 with a __getattr__ hook is evaluated.
333
333
334 """
334 """
335
335
336 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
336 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
337 # Another option, seems to work great. Catches things like ''.<tab>
337 # Another option, seems to work great. Catches things like ''.<tab>
338 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
338 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
339
339 if m:
340 if m:
340 expr, attr = m.group(1, 3)
341 expr, attr = m.group(1, 3)
341 elif self.greedy:
342 elif self.greedy:
342 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
343 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
343 if not m2:
344 if not m2:
344 return []
345 return []
345 expr, attr = m2.group(1,2)
346 expr, attr = m2.group(1,2)
346 else:
347 else:
347 return []
348 return []
348
349
349 try:
350 try:
350 obj = eval(expr, self.namespace)
351 obj = eval(expr, self.namespace)
351 except:
352 except:
352 try:
353 try:
353 obj = eval(expr, self.global_namespace)
354 obj = eval(expr, self.global_namespace)
354 except:
355 except:
355 return []
356 return []
356
357
357 if self.limit_to__all__ and hasattr(obj, '__all__'):
358 if self.limit_to__all__ and hasattr(obj, '__all__'):
358 words = get__all__entries(obj)
359 words = get__all__entries(obj)
359 else:
360 else:
360 words = dir2(obj)
361 words = dir2(obj)
361
362
362 try:
363 try:
363 words = generics.complete_object(obj, words)
364 words = generics.complete_object(obj, words)
364 except TryNext:
365 except TryNext:
365 pass
366 pass
366 except Exception:
367 except Exception:
367 # Silence errors from completion function
368 # Silence errors from completion function
368 #raise # dbg
369 #raise # dbg
369 pass
370 pass
370 # Build match list to return
371 # Build match list to return
371 n = len(attr)
372 n = len(attr)
372 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
373 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
373 return res
374 return res
374
375
375
376
376 def get__all__entries(obj):
377 def get__all__entries(obj):
377 """returns the strings in the __all__ attribute"""
378 """returns the strings in the __all__ attribute"""
378 try:
379 try:
379 words = getattr(obj,'__all__')
380 words = getattr(obj,'__all__')
380 except:
381 except:
381 return []
382 return []
382
383
383 return [w for w in words if isinstance(w, basestring)]
384 return [w for w in words if isinstance(w, basestring)]
384
385
385
386
386 class IPCompleter(Completer):
387 class IPCompleter(Completer):
387 """Extension of the completer class with IPython-specific features"""
388 """Extension of the completer class with IPython-specific features"""
388
389
389 def _greedy_changed(self, name, old, new):
390 def _greedy_changed(self, name, old, new):
390 """update the splitter and readline delims when greedy is changed"""
391 """update the splitter and readline delims when greedy is changed"""
391 if new:
392 if new:
392 self.splitter.set_delims(GREEDY_DELIMS)
393 self.splitter.set_delims(GREEDY_DELIMS)
393 else:
394 else:
394 self.splitter.set_delims(DELIMS)
395 self.splitter.set_delims(DELIMS)
395
396
396 if self.readline:
397 if self.readline:
397 self.readline.set_completer_delims(self.splitter.get_delims())
398 self.readline.set_completer_delims(self.splitter.get_delims())
398
399
399 merge_completions = CBool(True, config=True,
400 merge_completions = CBool(True, config=True,
400 help="""Whether to merge completion results into a single list
401 help="""Whether to merge completion results into a single list
401
402
402 If False, only the completion results from the first non-empty
403 If False, only the completion results from the first non-empty
403 completer will be returned.
404 completer will be returned.
404 """
405 """
405 )
406 )
406 omit__names = Enum((0,1,2), default_value=2, config=True,
407 omit__names = Enum((0,1,2), default_value=2, config=True,
407 help="""Instruct the completer to omit private method names
408 help="""Instruct the completer to omit private method names
408
409
409 Specifically, when completing on ``object.<tab>``.
410 Specifically, when completing on ``object.<tab>``.
410
411
411 When 2 [default]: all names that start with '_' will be excluded.
412 When 2 [default]: all names that start with '_' will be excluded.
412
413
413 When 1: all 'magic' names (``__foo__``) will be excluded.
414 When 1: all 'magic' names (``__foo__``) will be excluded.
414
415
415 When 0: nothing will be excluded.
416 When 0: nothing will be excluded.
416 """
417 """
417 )
418 )
418 limit_to__all__ = Enum((0,1), default_value=1, config=True,
419 limit_to__all__ = Enum((0,1), default_value=1, config=True,
419 help="""Instruct the completer to use __all__ for the completion
420 help="""Instruct the completer to use __all__ for the completion
420
421
421 Specifically, when completing on ``object.<tab>``.
422 Specifically, when completing on ``object.<tab>``.
422
423
423 When 1: only those names in obj.__all__ will be included.
424 When 1: only those names in obj.__all__ will be included.
424
425
425 When 0 [default]: the values in the __all__ attribute are ignored
426 When 0 [default]: the values in the __all__ attribute are ignored
426 """
427 """
427 )
428 )
428
429
429 def __init__(self, shell=None, namespace=None, global_namespace=None,
430 def __init__(self, shell=None, namespace=None, global_namespace=None,
430 alias_table=None, use_readline=True,
431 alias_table=None, use_readline=True,
431 config=None, **kwargs):
432 config=None, **kwargs):
432 """IPCompleter() -> completer
433 """IPCompleter() -> completer
433
434
434 Return a completer object suitable for use by the readline library
435 Return a completer object suitable for use by the readline library
435 via readline.set_completer().
436 via readline.set_completer().
436
437
437 Inputs:
438 Inputs:
438
439
439 - shell: a pointer to the ipython shell itself. This is needed
440 - shell: a pointer to the ipython shell itself. This is needed
440 because this completer knows about magic functions, and those can
441 because this completer knows about magic functions, and those can
441 only be accessed via the ipython instance.
442 only be accessed via the ipython instance.
442
443
443 - namespace: an optional dict where completions are performed.
444 - namespace: an optional dict where completions are performed.
444
445
445 - global_namespace: secondary optional dict for completions, to
446 - global_namespace: secondary optional dict for completions, to
446 handle cases (such as IPython embedded inside functions) where
447 handle cases (such as IPython embedded inside functions) where
447 both Python scopes are visible.
448 both Python scopes are visible.
448
449
449 - If alias_table is supplied, it should be a dictionary of aliases
450 - If alias_table is supplied, it should be a dictionary of aliases
450 to complete.
451 to complete.
451
452
452 use_readline : bool, optional
453 use_readline : bool, optional
453 If true, use the readline library. This completer can still function
454 If true, use the readline library. This completer can still function
454 without readline, though in that case callers must provide some extra
455 without readline, though in that case callers must provide some extra
455 information on each call about the current line."""
456 information on each call about the current line."""
456
457
457 self.magic_escape = ESC_MAGIC
458 self.magic_escape = ESC_MAGIC
458 self.splitter = CompletionSplitter()
459 self.splitter = CompletionSplitter()
459
460
460 # Readline configuration, only used by the rlcompleter method.
461 # Readline configuration, only used by the rlcompleter method.
461 if use_readline:
462 if use_readline:
462 # We store the right version of readline so that later code
463 # We store the right version of readline so that later code
463 import IPython.utils.rlineimpl as readline
464 import IPython.utils.rlineimpl as readline
464 self.readline = readline
465 self.readline = readline
465 else:
466 else:
466 self.readline = None
467 self.readline = None
467
468
468 # _greedy_changed() depends on splitter and readline being defined:
469 # _greedy_changed() depends on splitter and readline being defined:
469 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
470 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
470 config=config, **kwargs)
471 config=config, **kwargs)
471
472
472 # List where completion matches will be stored
473 # List where completion matches will be stored
473 self.matches = []
474 self.matches = []
474 self.shell = shell.shell
475 self.shell = shell.shell
475 if alias_table is None:
476 if alias_table is None:
476 alias_table = {}
477 alias_table = {}
477 self.alias_table = alias_table
478 self.alias_table = alias_table
478 # Regexp to split filenames with spaces in them
479 # Regexp to split filenames with spaces in them
479 self.space_name_re = re.compile(r'([^\\] )')
480 self.space_name_re = re.compile(r'([^\\] )')
480 # Hold a local ref. to glob.glob for speed
481 # Hold a local ref. to glob.glob for speed
481 self.glob = glob.glob
482 self.glob = glob.glob
482
483
483 # Determine if we are running on 'dumb' terminals, like (X)Emacs
484 # Determine if we are running on 'dumb' terminals, like (X)Emacs
484 # buffers, to avoid completion problems.
485 # buffers, to avoid completion problems.
485 term = os.environ.get('TERM','xterm')
486 term = os.environ.get('TERM','xterm')
486 self.dumb_terminal = term in ['dumb','emacs']
487 self.dumb_terminal = term in ['dumb','emacs']
487
488
488 # Special handling of backslashes needed in win32 platforms
489 # Special handling of backslashes needed in win32 platforms
489 if sys.platform == "win32":
490 if sys.platform == "win32":
490 self.clean_glob = self._clean_glob_win32
491 self.clean_glob = self._clean_glob_win32
491 else:
492 else:
492 self.clean_glob = self._clean_glob
493 self.clean_glob = self._clean_glob
493
494
494 # All active matcher routines for completion
495 # All active matcher routines for completion
495 self.matchers = [self.python_matches,
496 self.matchers = [self.python_matches,
496 self.file_matches,
497 self.file_matches,
497 self.magic_matches,
498 self.magic_matches,
498 self.alias_matches,
499 self.alias_matches,
499 self.python_func_kw_matches,
500 self.python_func_kw_matches,
500 ]
501 ]
501
502
502 def all_completions(self, text):
503 def all_completions(self, text):
503 """
504 """
504 Wrapper around the complete method for the benefit of emacs
505 Wrapper around the complete method for the benefit of emacs
505 and pydb.
506 and pydb.
506 """
507 """
507 return self.complete(text)[1]
508 return self.complete(text)[1]
508
509
509 def _clean_glob(self,text):
510 def _clean_glob(self,text):
510 return self.glob("%s*" % text)
511 return self.glob("%s*" % text)
511
512
512 def _clean_glob_win32(self,text):
513 def _clean_glob_win32(self,text):
513 return [f.replace("\\","/")
514 return [f.replace("\\","/")
514 for f in self.glob("%s*" % text)]
515 for f in self.glob("%s*" % text)]
515
516
516 def file_matches(self, text):
517 def file_matches(self, text):
517 """Match filenames, expanding ~USER type strings.
518 """Match filenames, expanding ~USER type strings.
518
519
519 Most of the seemingly convoluted logic in this completer is an
520 Most of the seemingly convoluted logic in this completer is an
520 attempt to handle filenames with spaces in them. And yet it's not
521 attempt to handle filenames with spaces in them. And yet it's not
521 quite perfect, because Python's readline doesn't expose all of the
522 quite perfect, because Python's readline doesn't expose all of the
522 GNU readline details needed for this to be done correctly.
523 GNU readline details needed for this to be done correctly.
523
524
524 For a filename with a space in it, the printed completions will be
525 For a filename with a space in it, the printed completions will be
525 only the parts after what's already been typed (instead of the
526 only the parts after what's already been typed (instead of the
526 full completions, as is normally done). I don't think with the
527 full completions, as is normally done). I don't think with the
527 current (as of Python 2.3) Python readline it's possible to do
528 current (as of Python 2.3) Python readline it's possible to do
528 better."""
529 better."""
529
530
530 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
531 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
531
532
532 # chars that require escaping with backslash - i.e. chars
533 # chars that require escaping with backslash - i.e. chars
533 # that readline treats incorrectly as delimiters, but we
534 # that readline treats incorrectly as delimiters, but we
534 # don't want to treat as delimiters in filename matching
535 # don't want to treat as delimiters in filename matching
535 # when escaped with backslash
536 # when escaped with backslash
536 if text.startswith('!'):
537 if text.startswith('!'):
537 text = text[1:]
538 text = text[1:]
538 text_prefix = '!'
539 text_prefix = '!'
539 else:
540 else:
540 text_prefix = ''
541 text_prefix = ''
541
542
542 text_until_cursor = self.text_until_cursor
543 text_until_cursor = self.text_until_cursor
543 # track strings with open quotes
544 # track strings with open quotes
544 open_quotes = has_open_quotes(text_until_cursor)
545 open_quotes = has_open_quotes(text_until_cursor)
545
546
546 if '(' in text_until_cursor or '[' in text_until_cursor:
547 if '(' in text_until_cursor or '[' in text_until_cursor:
547 lsplit = text
548 lsplit = text
548 else:
549 else:
549 try:
550 try:
550 # arg_split ~ shlex.split, but with unicode bugs fixed by us
551 # arg_split ~ shlex.split, but with unicode bugs fixed by us
551 lsplit = arg_split(text_until_cursor)[-1]
552 lsplit = arg_split(text_until_cursor)[-1]
552 except ValueError:
553 except ValueError:
553 # typically an unmatched ", or backslash without escaped char.
554 # typically an unmatched ", or backslash without escaped char.
554 if open_quotes:
555 if open_quotes:
555 lsplit = text_until_cursor.split(open_quotes)[-1]
556 lsplit = text_until_cursor.split(open_quotes)[-1]
556 else:
557 else:
557 return []
558 return []
558 except IndexError:
559 except IndexError:
559 # tab pressed on empty line
560 # tab pressed on empty line
560 lsplit = ""
561 lsplit = ""
561
562
562 if not open_quotes and lsplit != protect_filename(lsplit):
563 if not open_quotes and lsplit != protect_filename(lsplit):
563 # if protectables are found, do matching on the whole escaped name
564 # if protectables are found, do matching on the whole escaped name
564 has_protectables = True
565 has_protectables = True
565 text0,text = text,lsplit
566 text0,text = text,lsplit
566 else:
567 else:
567 has_protectables = False
568 has_protectables = False
568 text = os.path.expanduser(text)
569 text = os.path.expanduser(text)
569
570
570 if text == "":
571 if text == "":
571 return [text_prefix + protect_filename(f) for f in self.glob("*")]
572 return [text_prefix + protect_filename(f) for f in self.glob("*")]
572
573
573 # Compute the matches from the filesystem
574 # Compute the matches from the filesystem
574 m0 = self.clean_glob(text.replace('\\',''))
575 m0 = self.clean_glob(text.replace('\\',''))
575
576
576 if has_protectables:
577 if has_protectables:
577 # If we had protectables, we need to revert our changes to the
578 # If we had protectables, we need to revert our changes to the
578 # beginning of filename so that we don't double-write the part
579 # beginning of filename so that we don't double-write the part
579 # of the filename we have so far
580 # of the filename we have so far
580 len_lsplit = len(lsplit)
581 len_lsplit = len(lsplit)
581 matches = [text_prefix + text0 +
582 matches = [text_prefix + text0 +
582 protect_filename(f[len_lsplit:]) for f in m0]
583 protect_filename(f[len_lsplit:]) for f in m0]
583 else:
584 else:
584 if open_quotes:
585 if open_quotes:
585 # if we have a string with an open quote, we don't need to
586 # if we have a string with an open quote, we don't need to
586 # protect the names at all (and we _shouldn't_, as it
587 # protect the names at all (and we _shouldn't_, as it
587 # would cause bugs when the filesystem call is made).
588 # would cause bugs when the filesystem call is made).
588 matches = m0
589 matches = m0
589 else:
590 else:
590 matches = [text_prefix +
591 matches = [text_prefix +
591 protect_filename(f) for f in m0]
592 protect_filename(f) for f in m0]
592
593
593 #io.rprint('mm', matches) # dbg
594 #io.rprint('mm', matches) # dbg
594
595
595 # Mark directories in input list by appending '/' to their names.
596 # Mark directories in input list by appending '/' to their names.
596 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
597 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
597 return matches
598 return matches
598
599
599 def magic_matches(self, text):
600 def magic_matches(self, text):
600 """Match magics"""
601 """Match magics"""
601 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
602 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
602 # Get all shell magics now rather than statically, so magics loaded at
603 # Get all shell magics now rather than statically, so magics loaded at
603 # runtime show up too
604 # runtime show up too
604 magics = self.shell.lsmagic()
605 magics = self.shell.lsmagic()
605 pre = self.magic_escape
606 pre = self.magic_escape
606 baretext = text.lstrip(pre)
607 baretext = text.lstrip(pre)
607 return [ pre+m for m in magics if m.startswith(baretext)]
608 return [ pre+m for m in magics if m.startswith(baretext)]
608
609
609 def alias_matches(self, text):
610 def alias_matches(self, text):
610 """Match internal system aliases"""
611 """Match internal system aliases"""
611 #print 'Completer->alias_matches:',text,'lb',self.text_until_cursor # dbg
612 #print 'Completer->alias_matches:',text,'lb',self.text_until_cursor # dbg
612
613
613 # if we are not in the first 'item', alias matching
614 # if we are not in the first 'item', alias matching
614 # doesn't make sense - unless we are starting with 'sudo' command.
615 # doesn't make sense - unless we are starting with 'sudo' command.
615 main_text = self.text_until_cursor.lstrip()
616 main_text = self.text_until_cursor.lstrip()
616 if ' ' in main_text and not main_text.startswith('sudo'):
617 if ' ' in main_text and not main_text.startswith('sudo'):
617 return []
618 return []
618 text = os.path.expanduser(text)
619 text = os.path.expanduser(text)
619 aliases = self.alias_table.keys()
620 aliases = self.alias_table.keys()
620 if text == '':
621 if text == '':
621 return aliases
622 return aliases
622 else:
623 else:
623 return [a for a in aliases if a.startswith(text)]
624 return [a for a in aliases if a.startswith(text)]
624
625
625 def python_matches(self,text):
626 def python_matches(self,text):
626 """Match attributes or global python names"""
627 """Match attributes or global python names"""
627
628
628 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
629 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
629 if "." in text:
630 if "." in text:
630 try:
631 try:
631 matches = self.attr_matches(text)
632 matches = self.attr_matches(text)
632 if text.endswith('.') and self.omit__names:
633 if text.endswith('.') and self.omit__names:
633 if self.omit__names == 1:
634 if self.omit__names == 1:
634 # true if txt is _not_ a __ name, false otherwise:
635 # true if txt is _not_ a __ name, false otherwise:
635 no__name = (lambda txt:
636 no__name = (lambda txt:
636 re.match(r'.*\.__.*?__',txt) is None)
637 re.match(r'.*\.__.*?__',txt) is None)
637 else:
638 else:
638 # true if txt is _not_ a _ name, false otherwise:
639 # true if txt is _not_ a _ name, false otherwise:
639 no__name = (lambda txt:
640 no__name = (lambda txt:
640 re.match(r'.*\._.*?',txt) is None)
641 re.match(r'.*\._.*?',txt) is None)
641 matches = filter(no__name, matches)
642 matches = filter(no__name, matches)
642 except NameError:
643 except NameError:
643 # catches <undefined attributes>.<tab>
644 # catches <undefined attributes>.<tab>
644 matches = []
645 matches = []
645 else:
646 else:
646 matches = self.global_matches(text)
647 matches = self.global_matches(text)
647
648
648 return matches
649 return matches
649
650
650 def _default_arguments(self, obj):
651 def _default_arguments(self, obj):
651 """Return the list of default arguments of obj if it is callable,
652 """Return the list of default arguments of obj if it is callable,
652 or empty list otherwise."""
653 or empty list otherwise."""
653
654
654 if not (inspect.isfunction(obj) or inspect.ismethod(obj)):
655 if not (inspect.isfunction(obj) or inspect.ismethod(obj)):
655 # for classes, check for __init__,__new__
656 # for classes, check for __init__,__new__
656 if inspect.isclass(obj):
657 if inspect.isclass(obj):
657 obj = (getattr(obj,'__init__',None) or
658 obj = (getattr(obj,'__init__',None) or
658 getattr(obj,'__new__',None))
659 getattr(obj,'__new__',None))
659 # for all others, check if they are __call__able
660 # for all others, check if they are __call__able
660 elif hasattr(obj, '__call__'):
661 elif hasattr(obj, '__call__'):
661 obj = obj.__call__
662 obj = obj.__call__
662 # XXX: is there a way to handle the builtins ?
663 # XXX: is there a way to handle the builtins ?
663 try:
664 try:
664 args,_,_1,defaults = inspect.getargspec(obj)
665 args,_,_1,defaults = inspect.getargspec(obj)
665 if defaults:
666 if defaults:
666 return args[-len(defaults):]
667 return args[-len(defaults):]
667 except TypeError: pass
668 except TypeError: pass
668 return []
669 return []
669
670
670 def python_func_kw_matches(self,text):
671 def python_func_kw_matches(self,text):
671 """Match named parameters (kwargs) of the last open function"""
672 """Match named parameters (kwargs) of the last open function"""
672
673
673 if "." in text: # a parameter cannot be dotted
674 if "." in text: # a parameter cannot be dotted
674 return []
675 return []
675 try: regexp = self.__funcParamsRegex
676 try: regexp = self.__funcParamsRegex
676 except AttributeError:
677 except AttributeError:
677 regexp = self.__funcParamsRegex = re.compile(r'''
678 regexp = self.__funcParamsRegex = re.compile(r'''
678 '.*?' | # single quoted strings or
679 '.*?' | # single quoted strings or
679 ".*?" | # double quoted strings or
680 ".*?" | # double quoted strings or
680 \w+ | # identifier
681 \w+ | # identifier
681 \S # other characters
682 \S # other characters
682 ''', re.VERBOSE | re.DOTALL)
683 ''', re.VERBOSE | re.DOTALL)
683 # 1. find the nearest identifier that comes before an unclosed
684 # 1. find the nearest identifier that comes before an unclosed
684 # parenthesis e.g. for "foo (1+bar(x), pa", the candidate is "foo"
685 # parenthesis e.g. for "foo (1+bar(x), pa", the candidate is "foo"
685 tokens = regexp.findall(self.line_buffer)
686 tokens = regexp.findall(self.line_buffer)
686 tokens.reverse()
687 tokens.reverse()
687 iterTokens = iter(tokens); openPar = 0
688 iterTokens = iter(tokens); openPar = 0
688 for token in iterTokens:
689 for token in iterTokens:
689 if token == ')':
690 if token == ')':
690 openPar -= 1
691 openPar -= 1
691 elif token == '(':
692 elif token == '(':
692 openPar += 1
693 openPar += 1
693 if openPar > 0:
694 if openPar > 0:
694 # found the last unclosed parenthesis
695 # found the last unclosed parenthesis
695 break
696 break
696 else:
697 else:
697 return []
698 return []
698 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
699 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
699 ids = []
700 ids = []
700 isId = re.compile(r'\w+$').match
701 isId = re.compile(r'\w+$').match
701 while True:
702 while True:
702 try:
703 try:
703 ids.append(iterTokens.next())
704 ids.append(iterTokens.next())
704 if not isId(ids[-1]):
705 if not isId(ids[-1]):
705 ids.pop(); break
706 ids.pop(); break
706 if not iterTokens.next() == '.':
707 if not iterTokens.next() == '.':
707 break
708 break
708 except StopIteration:
709 except StopIteration:
709 break
710 break
710 # lookup the candidate callable matches either using global_matches
711 # lookup the candidate callable matches either using global_matches
711 # or attr_matches for dotted names
712 # or attr_matches for dotted names
712 if len(ids) == 1:
713 if len(ids) == 1:
713 callableMatches = self.global_matches(ids[0])
714 callableMatches = self.global_matches(ids[0])
714 else:
715 else:
715 callableMatches = self.attr_matches('.'.join(ids[::-1]))
716 callableMatches = self.attr_matches('.'.join(ids[::-1]))
716 argMatches = []
717 argMatches = []
717 for callableMatch in callableMatches:
718 for callableMatch in callableMatches:
718 try:
719 try:
719 namedArgs = self._default_arguments(eval(callableMatch,
720 namedArgs = self._default_arguments(eval(callableMatch,
720 self.namespace))
721 self.namespace))
721 except:
722 except:
722 continue
723 continue
723 for namedArg in namedArgs:
724 for namedArg in namedArgs:
724 if namedArg.startswith(text):
725 if namedArg.startswith(text):
725 argMatches.append("%s=" %namedArg)
726 argMatches.append("%s=" %namedArg)
726 return argMatches
727 return argMatches
727
728
728 def dispatch_custom_completer(self, text):
729 def dispatch_custom_completer(self, text):
729 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
730 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
730 line = self.line_buffer
731 line = self.line_buffer
731 if not line.strip():
732 if not line.strip():
732 return None
733 return None
733
734
734 # Create a little structure to pass all the relevant information about
735 # Create a little structure to pass all the relevant information about
735 # the current completion to any custom completer.
736 # the current completion to any custom completer.
736 event = Bunch()
737 event = Bunch()
737 event.line = line
738 event.line = line
738 event.symbol = text
739 event.symbol = text
739 cmd = line.split(None,1)[0]
740 cmd = line.split(None,1)[0]
740 event.command = cmd
741 event.command = cmd
741 event.text_until_cursor = self.text_until_cursor
742 event.text_until_cursor = self.text_until_cursor
742
743
743 #print "\ncustom:{%s]\n" % event # dbg
744 #print "\ncustom:{%s]\n" % event # dbg
744
745
745 # for foo etc, try also to find completer for %foo
746 # for foo etc, try also to find completer for %foo
746 if not cmd.startswith(self.magic_escape):
747 if not cmd.startswith(self.magic_escape):
747 try_magic = self.custom_completers.s_matches(
748 try_magic = self.custom_completers.s_matches(
748 self.magic_escape + cmd)
749 self.magic_escape + cmd)
749 else:
750 else:
750 try_magic = []
751 try_magic = []
751
752
752 for c in itertools.chain(self.custom_completers.s_matches(cmd),
753 for c in itertools.chain(self.custom_completers.s_matches(cmd),
753 try_magic,
754 try_magic,
754 self.custom_completers.flat_matches(self.text_until_cursor)):
755 self.custom_completers.flat_matches(self.text_until_cursor)):
755 #print "try",c # dbg
756 #print "try",c # dbg
756 try:
757 try:
757 res = c(event)
758 res = c(event)
758 if res:
759 if res:
759 # first, try case sensitive match
760 # first, try case sensitive match
760 withcase = [r for r in res if r.startswith(text)]
761 withcase = [r for r in res if r.startswith(text)]
761 if withcase:
762 if withcase:
762 return withcase
763 return withcase
763 # if none, then case insensitive ones are ok too
764 # if none, then case insensitive ones are ok too
764 text_low = text.lower()
765 text_low = text.lower()
765 return [r for r in res if r.lower().startswith(text_low)]
766 return [r for r in res if r.lower().startswith(text_low)]
766 except TryNext:
767 except TryNext:
767 pass
768 pass
768
769
769 return None
770 return None
770
771
771 def complete(self, text=None, line_buffer=None, cursor_pos=None):
772 def complete(self, text=None, line_buffer=None, cursor_pos=None):
772 """Find completions for the given text and line context.
773 """Find completions for the given text and line context.
773
774
774 This is called successively with state == 0, 1, 2, ... until it
775 This is called successively with state == 0, 1, 2, ... until it
775 returns None. The completion should begin with 'text'.
776 returns None. The completion should begin with 'text'.
776
777
777 Note that both the text and the line_buffer are optional, but at least
778 Note that both the text and the line_buffer are optional, but at least
778 one of them must be given.
779 one of them must be given.
779
780
780 Parameters
781 Parameters
781 ----------
782 ----------
782 text : string, optional
783 text : string, optional
783 Text to perform the completion on. If not given, the line buffer
784 Text to perform the completion on. If not given, the line buffer
784 is split using the instance's CompletionSplitter object.
785 is split using the instance's CompletionSplitter object.
785
786
786 line_buffer : string, optional
787 line_buffer : string, optional
787 If not given, the completer attempts to obtain the current line
788 If not given, the completer attempts to obtain the current line
788 buffer via readline. This keyword allows clients which are
789 buffer via readline. This keyword allows clients which are
789 requesting for text completions in non-readline contexts to inform
790 requesting for text completions in non-readline contexts to inform
790 the completer of the entire text.
791 the completer of the entire text.
791
792
792 cursor_pos : int, optional
793 cursor_pos : int, optional
793 Index of the cursor in the full line buffer. Should be provided by
794 Index of the cursor in the full line buffer. Should be provided by
794 remote frontends where kernel has no access to frontend state.
795 remote frontends where kernel has no access to frontend state.
795
796
796 Returns
797 Returns
797 -------
798 -------
798 text : str
799 text : str
799 Text that was actually used in the completion.
800 Text that was actually used in the completion.
800
801
801 matches : list
802 matches : list
802 A list of completion matches.
803 A list of completion matches.
803 """
804 """
804 #io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
805 #io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
805
806
806 # if the cursor position isn't given, the only sane assumption we can
807 # if the cursor position isn't given, the only sane assumption we can
807 # make is that it's at the end of the line (the common case)
808 # make is that it's at the end of the line (the common case)
808 if cursor_pos is None:
809 if cursor_pos is None:
809 cursor_pos = len(line_buffer) if text is None else len(text)
810 cursor_pos = len(line_buffer) if text is None else len(text)
810
811
811 # if text is either None or an empty string, rely on the line buffer
812 # if text is either None or an empty string, rely on the line buffer
812 if not text:
813 if not text:
813 text = self.splitter.split_line(line_buffer, cursor_pos)
814 text = self.splitter.split_line(line_buffer, cursor_pos)
814
815
815 # If no line buffer is given, assume the input text is all there was
816 # If no line buffer is given, assume the input text is all there was
816 if line_buffer is None:
817 if line_buffer is None:
817 line_buffer = text
818 line_buffer = text
818
819
819 self.line_buffer = line_buffer
820 self.line_buffer = line_buffer
820 self.text_until_cursor = self.line_buffer[:cursor_pos]
821 self.text_until_cursor = self.line_buffer[:cursor_pos]
821 #io.rprint('\nCOMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
822 #io.rprint('\nCOMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
822
823
823 # Start with a clean slate of completions
824 # Start with a clean slate of completions
824 self.matches[:] = []
825 self.matches[:] = []
825 custom_res = self.dispatch_custom_completer(text)
826 custom_res = self.dispatch_custom_completer(text)
826 if custom_res is not None:
827 if custom_res is not None:
827 # did custom completers produce something?
828 # did custom completers produce something?
828 self.matches = custom_res
829 self.matches = custom_res
829 else:
830 else:
830 # Extend the list of completions with the results of each
831 # Extend the list of completions with the results of each
831 # matcher, so we return results to the user from all
832 # matcher, so we return results to the user from all
832 # namespaces.
833 # namespaces.
833 if self.merge_completions:
834 if self.merge_completions:
834 self.matches = []
835 self.matches = []
835 for matcher in self.matchers:
836 for matcher in self.matchers:
836 try:
837 try:
837 self.matches.extend(matcher(text))
838 self.matches.extend(matcher(text))
838 except:
839 except:
839 # Show the ugly traceback if the matcher causes an
840 # Show the ugly traceback if the matcher causes an
840 # exception, but do NOT crash the kernel!
841 # exception, but do NOT crash the kernel!
841 sys.excepthook(*sys.exc_info())
842 sys.excepthook(*sys.exc_info())
842 else:
843 else:
843 for matcher in self.matchers:
844 for matcher in self.matchers:
844 self.matches = matcher(text)
845 self.matches = matcher(text)
845 if self.matches:
846 if self.matches:
846 break
847 break
847 # FIXME: we should extend our api to return a dict with completions for
848 # FIXME: we should extend our api to return a dict with completions for
848 # different types of objects. The rlcomplete() method could then
849 # different types of objects. The rlcomplete() method could then
849 # simply collapse the dict into a list for readline, but we'd have
850 # simply collapse the dict into a list for readline, but we'd have
850 # richer completion semantics in other evironments.
851 # richer completion semantics in other evironments.
851 self.matches = sorted(set(self.matches))
852 self.matches = sorted(set(self.matches))
852 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
853 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
853 return text, self.matches
854 return text, self.matches
854
855
855 def rlcomplete(self, text, state):
856 def rlcomplete(self, text, state):
856 """Return the state-th possible completion for 'text'.
857 """Return the state-th possible completion for 'text'.
857
858
858 This is called successively with state == 0, 1, 2, ... until it
859 This is called successively with state == 0, 1, 2, ... until it
859 returns None. The completion should begin with 'text'.
860 returns None. The completion should begin with 'text'.
860
861
861 Parameters
862 Parameters
862 ----------
863 ----------
863 text : string
864 text : string
864 Text to perform the completion on.
865 Text to perform the completion on.
865
866
866 state : int
867 state : int
867 Counter used by readline.
868 Counter used by readline.
868 """
869 """
869 if state==0:
870 if state==0:
870
871
871 self.line_buffer = line_buffer = self.readline.get_line_buffer()
872 self.line_buffer = line_buffer = self.readline.get_line_buffer()
872 cursor_pos = self.readline.get_endidx()
873 cursor_pos = self.readline.get_endidx()
873
874
874 #io.rprint("\nRLCOMPLETE: %r %r %r" %
875 #io.rprint("\nRLCOMPLETE: %r %r %r" %
875 # (text, line_buffer, cursor_pos) ) # dbg
876 # (text, line_buffer, cursor_pos) ) # dbg
876
877
877 # if there is only a tab on a line with only whitespace, instead of
878 # if there is only a tab on a line with only whitespace, instead of
878 # the mostly useless 'do you want to see all million completions'
879 # the mostly useless 'do you want to see all million completions'
879 # message, just do the right thing and give the user his tab!
880 # message, just do the right thing and give the user his tab!
880 # Incidentally, this enables pasting of tabbed text from an editor
881 # Incidentally, this enables pasting of tabbed text from an editor
881 # (as long as autoindent is off).
882 # (as long as autoindent is off).
882
883
883 # It should be noted that at least pyreadline still shows file
884 # It should be noted that at least pyreadline still shows file
884 # completions - is there a way around it?
885 # completions - is there a way around it?
885
886
886 # don't apply this on 'dumb' terminals, such as emacs buffers, so
887 # don't apply this on 'dumb' terminals, such as emacs buffers, so
887 # we don't interfere with their own tab-completion mechanism.
888 # we don't interfere with their own tab-completion mechanism.
888 if not (self.dumb_terminal or line_buffer.strip()):
889 if not (self.dumb_terminal or line_buffer.strip()):
889 self.readline.insert_text('\t')
890 self.readline.insert_text('\t')
890 sys.stdout.flush()
891 sys.stdout.flush()
891 return None
892 return None
892
893
893 # Note: debugging exceptions that may occur in completion is very
894 # Note: debugging exceptions that may occur in completion is very
894 # tricky, because readline unconditionally silences them. So if
895 # tricky, because readline unconditionally silences them. So if
895 # during development you suspect a bug in the completion code, turn
896 # during development you suspect a bug in the completion code, turn
896 # this flag on temporarily by uncommenting the second form (don't
897 # this flag on temporarily by uncommenting the second form (don't
897 # flip the value in the first line, as the '# dbg' marker can be
898 # flip the value in the first line, as the '# dbg' marker can be
898 # automatically detected and is used elsewhere).
899 # automatically detected and is used elsewhere).
899 DEBUG = False
900 DEBUG = False
900 #DEBUG = True # dbg
901 #DEBUG = True # dbg
901 if DEBUG:
902 if DEBUG:
902 try:
903 try:
903 self.complete(text, line_buffer, cursor_pos)
904 self.complete(text, line_buffer, cursor_pos)
904 except:
905 except:
905 import traceback; traceback.print_exc()
906 import traceback; traceback.print_exc()
906 else:
907 else:
907 # The normal production version is here
908 # The normal production version is here
908
909
909 # This method computes the self.matches array
910 # This method computes the self.matches array
910 self.complete(text, line_buffer, cursor_pos)
911 self.complete(text, line_buffer, cursor_pos)
911
912
912 try:
913 try:
913 return self.matches[state]
914 return self.matches[state]
914 except IndexError:
915 except IndexError:
915 return None
916 return None
@@ -1,244 +1,243 b''
1 """Tests for the IPython tab-completion machinery.
1 """Tests for the IPython tab-completion machinery.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Module imports
4 # Module imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6
6
7 # stdlib
7 # stdlib
8 import os
8 import os
9 import sys
9 import sys
10 import unittest
10 import unittest
11
11
12 # third party
12 # third party
13 import nose.tools as nt
13 import nose.tools as nt
14
14
15 # our own packages
15 # our own packages
16 from IPython.config.loader import Config
16 from IPython.config.loader import Config
17 from IPython.core import completer
17 from IPython.core import completer
18 from IPython.external.decorators import knownfailureif
18 from IPython.external.decorators import knownfailureif
19 from IPython.utils.tempdir import TemporaryDirectory
19 from IPython.utils.tempdir import TemporaryDirectory
20 from IPython.utils.generics import complete_object
20 from IPython.utils.generics import complete_object
21 from IPython.testing.globalipapp import get_ipython
22
21
23 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
24 # Test functions
23 # Test functions
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 def test_protect_filename():
25 def test_protect_filename():
27 pairs = [ ('abc','abc'),
26 pairs = [ ('abc','abc'),
28 (' abc',r'\ abc'),
27 (' abc',r'\ abc'),
29 ('a bc',r'a\ bc'),
28 ('a bc',r'a\ bc'),
30 ('a bc',r'a\ \ bc'),
29 ('a bc',r'a\ \ bc'),
31 (' bc',r'\ \ bc'),
30 (' bc',r'\ \ bc'),
32 ]
31 ]
33 # On posix, we also protect parens and other special characters
32 # On posix, we also protect parens and other special characters
34 if sys.platform != 'win32':
33 if sys.platform != 'win32':
35 pairs.extend( [('a(bc',r'a\(bc'),
34 pairs.extend( [('a(bc',r'a\(bc'),
36 ('a)bc',r'a\)bc'),
35 ('a)bc',r'a\)bc'),
37 ('a( )bc',r'a\(\ \)bc'),
36 ('a( )bc',r'a\(\ \)bc'),
38 ('a[1]bc', r'a\[1\]bc'),
37 ('a[1]bc', r'a\[1\]bc'),
39 ('a{1}bc', r'a\{1\}bc'),
38 ('a{1}bc', r'a\{1\}bc'),
40 ('a#bc', r'a\#bc'),
39 ('a#bc', r'a\#bc'),
41 ('a?bc', r'a\?bc'),
40 ('a?bc', r'a\?bc'),
42 ('a=bc', r'a\=bc'),
41 ('a=bc', r'a\=bc'),
43 ('a\\bc', r'a\\bc'),
42 ('a\\bc', r'a\\bc'),
44 ('a|bc', r'a\|bc'),
43 ('a|bc', r'a\|bc'),
45 ('a;bc', r'a\;bc'),
44 ('a;bc', r'a\;bc'),
46 ('a:bc', r'a\:bc'),
45 ('a:bc', r'a\:bc'),
47 ("a'bc", r"a\'bc"),
46 ("a'bc", r"a\'bc"),
48 ('a*bc', r'a\*bc'),
47 ('a*bc', r'a\*bc'),
49 ('a"bc', r'a\"bc'),
48 ('a"bc', r'a\"bc'),
50 ('a^bc', r'a\^bc'),
49 ('a^bc', r'a\^bc'),
51 ('a&bc', r'a\&bc'),
50 ('a&bc', r'a\&bc'),
52 ] )
51 ] )
53 # run the actual tests
52 # run the actual tests
54 for s1, s2 in pairs:
53 for s1, s2 in pairs:
55 s1p = completer.protect_filename(s1)
54 s1p = completer.protect_filename(s1)
56 nt.assert_equals(s1p, s2)
55 nt.assert_equals(s1p, s2)
57
56
58
57
59 def check_line_split(splitter, test_specs):
58 def check_line_split(splitter, test_specs):
60 for part1, part2, split in test_specs:
59 for part1, part2, split in test_specs:
61 cursor_pos = len(part1)
60 cursor_pos = len(part1)
62 line = part1+part2
61 line = part1+part2
63 out = splitter.split_line(line, cursor_pos)
62 out = splitter.split_line(line, cursor_pos)
64 nt.assert_equal(out, split)
63 nt.assert_equal(out, split)
65
64
66
65
67 def test_line_split():
66 def test_line_split():
68 """Basice line splitter test with default specs."""
67 """Basice line splitter test with default specs."""
69 sp = completer.CompletionSplitter()
68 sp = completer.CompletionSplitter()
70 # The format of the test specs is: part1, part2, expected answer. Parts 1
69 # The format of the test specs is: part1, part2, expected answer. Parts 1
71 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
70 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
72 # was at the end of part1. So an empty part2 represents someone hitting
71 # was at the end of part1. So an empty part2 represents someone hitting
73 # tab at the end of the line, the most common case.
72 # tab at the end of the line, the most common case.
74 t = [('run some/scrip', '', 'some/scrip'),
73 t = [('run some/scrip', '', 'some/scrip'),
75 ('run scripts/er', 'ror.py foo', 'scripts/er'),
74 ('run scripts/er', 'ror.py foo', 'scripts/er'),
76 ('echo $HOM', '', 'HOM'),
75 ('echo $HOM', '', 'HOM'),
77 ('print sys.pa', '', 'sys.pa'),
76 ('print sys.pa', '', 'sys.pa'),
78 ('print(sys.pa', '', 'sys.pa'),
77 ('print(sys.pa', '', 'sys.pa'),
79 ("execfile('scripts/er", '', 'scripts/er'),
78 ("execfile('scripts/er", '', 'scripts/er'),
80 ('a[x.', '', 'x.'),
79 ('a[x.', '', 'x.'),
81 ('a[x.', 'y', 'x.'),
80 ('a[x.', 'y', 'x.'),
82 ('cd "some_file/', '', 'some_file/'),
81 ('cd "some_file/', '', 'some_file/'),
83 ]
82 ]
84 check_line_split(sp, t)
83 check_line_split(sp, t)
85 # Ensure splitting works OK with unicode by re-running the tests with
84 # Ensure splitting works OK with unicode by re-running the tests with
86 # all inputs turned into unicode
85 # all inputs turned into unicode
87 check_line_split(sp, [ map(unicode, p) for p in t] )
86 check_line_split(sp, [ map(unicode, p) for p in t] )
88
87
89 def test_custom_completion_error():
88 def test_custom_completion_error():
90 """Test that errors from custom attribute completers are silenced."""
89 """Test that errors from custom attribute completers are silenced."""
91 ip = get_ipython()
90 ip = get_ipython()
92 class A(object): pass
91 class A(object): pass
93 ip.user_ns['a'] = A()
92 ip.user_ns['a'] = A()
94
93
95 @complete_object.when_type(A)
94 @complete_object.when_type(A)
96 def complete_A(a, existing_completions):
95 def complete_A(a, existing_completions):
97 raise TypeError("this should be silenced")
96 raise TypeError("this should be silenced")
98
97
99 ip.complete("a.")
98 ip.complete("a.")
100
99
101
100
102 def test_unicode_completions():
101 def test_unicode_completions():
103 ip = get_ipython()
102 ip = get_ipython()
104 # Some strings that trigger different types of completion. Check them both
103 # Some strings that trigger different types of completion. Check them both
105 # in str and unicode forms
104 # in str and unicode forms
106 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
105 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
107 for t in s + map(unicode, s):
106 for t in s + map(unicode, s):
108 # We don't need to check exact completion values (they may change
107 # We don't need to check exact completion values (they may change
109 # depending on the state of the namespace, but at least no exceptions
108 # depending on the state of the namespace, but at least no exceptions
110 # should be thrown and the return value should be a pair of text, list
109 # should be thrown and the return value should be a pair of text, list
111 # values.
110 # values.
112 text, matches = ip.complete(t)
111 text, matches = ip.complete(t)
113 nt.assert_true(isinstance(text, basestring))
112 nt.assert_true(isinstance(text, basestring))
114 nt.assert_true(isinstance(matches, list))
113 nt.assert_true(isinstance(matches, list))
115
114
116
115
117 class CompletionSplitterTestCase(unittest.TestCase):
116 class CompletionSplitterTestCase(unittest.TestCase):
118 def setUp(self):
117 def setUp(self):
119 self.sp = completer.CompletionSplitter()
118 self.sp = completer.CompletionSplitter()
120
119
121 def test_delim_setting(self):
120 def test_delim_setting(self):
122 self.sp.set_delims(' ')
121 self.sp.set_delims(' ')
123 nt.assert_equal(self.sp.get_delims(), ' ')
122 nt.assert_equal(self.sp.get_delims(), ' ')
124 nt.assert_equal(self.sp._delim_expr, '[\ ]')
123 nt.assert_equal(self.sp._delim_expr, '[\ ]')
125
124
126 def test_spaces(self):
125 def test_spaces(self):
127 """Test with only spaces as split chars."""
126 """Test with only spaces as split chars."""
128 self.sp.delims = ' '
127 self.sp.delims = ' '
129 t = [('foo', '', 'foo'),
128 t = [('foo', '', 'foo'),
130 ('run foo', '', 'foo'),
129 ('run foo', '', 'foo'),
131 ('run foo', 'bar', 'foo'),
130 ('run foo', 'bar', 'foo'),
132 ]
131 ]
133 check_line_split(self.sp, t)
132 check_line_split(self.sp, t)
134
133
135
134
136 def test_has_open_quotes1():
135 def test_has_open_quotes1():
137 for s in ["'", "'''", "'hi' '"]:
136 for s in ["'", "'''", "'hi' '"]:
138 nt.assert_equal(completer.has_open_quotes(s), "'")
137 nt.assert_equal(completer.has_open_quotes(s), "'")
139
138
140
139
141 def test_has_open_quotes2():
140 def test_has_open_quotes2():
142 for s in ['"', '"""', '"hi" "']:
141 for s in ['"', '"""', '"hi" "']:
143 nt.assert_equal(completer.has_open_quotes(s), '"')
142 nt.assert_equal(completer.has_open_quotes(s), '"')
144
143
145
144
146 def test_has_open_quotes3():
145 def test_has_open_quotes3():
147 for s in ["''", "''' '''", "'hi' 'ipython'"]:
146 for s in ["''", "''' '''", "'hi' 'ipython'"]:
148 nt.assert_false(completer.has_open_quotes(s))
147 nt.assert_false(completer.has_open_quotes(s))
149
148
150
149
151 def test_has_open_quotes4():
150 def test_has_open_quotes4():
152 for s in ['""', '""" """', '"hi" "ipython"']:
151 for s in ['""', '""" """', '"hi" "ipython"']:
153 nt.assert_false(completer.has_open_quotes(s))
152 nt.assert_false(completer.has_open_quotes(s))
154
153
155 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
154 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
156 def test_abspath_file_completions():
155 def test_abspath_file_completions():
157 ip = get_ipython()
156 ip = get_ipython()
158 with TemporaryDirectory() as tmpdir:
157 with TemporaryDirectory() as tmpdir:
159 prefix = os.path.join(tmpdir, 'foo')
158 prefix = os.path.join(tmpdir, 'foo')
160 suffixes = map(str, [1,2])
159 suffixes = map(str, [1,2])
161 names = [prefix+s for s in suffixes]
160 names = [prefix+s for s in suffixes]
162 for n in names:
161 for n in names:
163 open(n, 'w').close()
162 open(n, 'w').close()
164
163
165 # Check simple completion
164 # Check simple completion
166 c = ip.complete(prefix)[1]
165 c = ip.complete(prefix)[1]
167 nt.assert_equal(c, names)
166 nt.assert_equal(c, names)
168
167
169 # Now check with a function call
168 # Now check with a function call
170 cmd = 'a = f("%s' % prefix
169 cmd = 'a = f("%s' % prefix
171 c = ip.complete(prefix, cmd)[1]
170 c = ip.complete(prefix, cmd)[1]
172 comp = [prefix+s for s in suffixes]
171 comp = [prefix+s for s in suffixes]
173 nt.assert_equal(c, comp)
172 nt.assert_equal(c, comp)
174
173
175 def test_local_file_completions():
174 def test_local_file_completions():
176 ip = get_ipython()
175 ip = get_ipython()
177 cwd = os.getcwdu()
176 cwd = os.getcwdu()
178 try:
177 try:
179 with TemporaryDirectory() as tmpdir:
178 with TemporaryDirectory() as tmpdir:
180 os.chdir(tmpdir)
179 os.chdir(tmpdir)
181 prefix = './foo'
180 prefix = './foo'
182 suffixes = map(str, [1,2])
181 suffixes = map(str, [1,2])
183 names = [prefix+s for s in suffixes]
182 names = [prefix+s for s in suffixes]
184 for n in names:
183 for n in names:
185 open(n, 'w').close()
184 open(n, 'w').close()
186
185
187 # Check simple completion
186 # Check simple completion
188 c = ip.complete(prefix)[1]
187 c = ip.complete(prefix)[1]
189 nt.assert_equal(c, names)
188 nt.assert_equal(c, names)
190
189
191 # Now check with a function call
190 # Now check with a function call
192 cmd = 'a = f("%s' % prefix
191 cmd = 'a = f("%s' % prefix
193 c = ip.complete(prefix, cmd)[1]
192 c = ip.complete(prefix, cmd)[1]
194 comp = [prefix+s for s in suffixes]
193 comp = [prefix+s for s in suffixes]
195 nt.assert_equal(c, comp)
194 nt.assert_equal(c, comp)
196 finally:
195 finally:
197 # prevent failures from making chdir stick
196 # prevent failures from making chdir stick
198 os.chdir(cwd)
197 os.chdir(cwd)
199
198
200 def test_greedy_completions():
199 def test_greedy_completions():
201 ip = get_ipython()
200 ip = get_ipython()
202 ip.Completer.greedy = False
201 ip.Completer.greedy = False
203 ip.ex('a=range(5)')
202 ip.ex('a=range(5)')
204 _,c = ip.complete('.',line='a[0].')
203 _,c = ip.complete('.',line='a[0].')
205 nt.assert_false('a[0].real' in c, "Shouldn't have completed on a[0]: %s"%c)
204 nt.assert_false('a[0].real' in c, "Shouldn't have completed on a[0]: %s"%c)
206 ip.Completer.greedy = True
205 ip.Completer.greedy = True
207 _,c = ip.complete('.',line='a[0].')
206 _,c = ip.complete('.',line='a[0].')
208 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
207 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
209
208
210 def test_omit__names():
209 def test_omit__names():
211 # also happens to test IPCompleter as a configurable
210 # also happens to test IPCompleter as a configurable
212 ip = get_ipython()
211 ip = get_ipython()
213 ip._hidden_attr = 1
212 ip._hidden_attr = 1
214 c = ip.Completer
213 c = ip.Completer
215 ip.ex('ip=get_ipython()')
214 ip.ex('ip=get_ipython()')
216 cfg = Config()
215 cfg = Config()
217 cfg.IPCompleter.omit__names = 0
216 cfg.IPCompleter.omit__names = 0
218 c.update_config(cfg)
217 c.update_config(cfg)
219 s,matches = c.complete('ip.')
218 s,matches = c.complete('ip.')
220 nt.assert_true('ip.__str__' in matches)
219 nt.assert_true('ip.__str__' in matches)
221 nt.assert_true('ip._hidden_attr' in matches)
220 nt.assert_true('ip._hidden_attr' in matches)
222 cfg.IPCompleter.omit__names = 1
221 cfg.IPCompleter.omit__names = 1
223 c.update_config(cfg)
222 c.update_config(cfg)
224 s,matches = c.complete('ip.')
223 s,matches = c.complete('ip.')
225 nt.assert_false('ip.__str__' in matches)
224 nt.assert_false('ip.__str__' in matches)
226 nt.assert_true('ip._hidden_attr' in matches)
225 nt.assert_true('ip._hidden_attr' in matches)
227 cfg.IPCompleter.omit__names = 2
226 cfg.IPCompleter.omit__names = 2
228 c.update_config(cfg)
227 c.update_config(cfg)
229 s,matches = c.complete('ip.')
228 s,matches = c.complete('ip.')
230 nt.assert_false('ip.__str__' in matches)
229 nt.assert_false('ip.__str__' in matches)
231 nt.assert_false('ip._hidden_attr' in matches)
230 nt.assert_false('ip._hidden_attr' in matches)
232 del ip._hidden_attr
231 del ip._hidden_attr
233
232
234 def test_get__all__entries_ok():
233 def test_get__all__entries_ok():
235 class A(object):
234 class A(object):
236 __all__ = ['x', 1]
235 __all__ = ['x', 1]
237 words = completer.get__all__entries(A())
236 words = completer.get__all__entries(A())
238 nt.assert_equal(words, ['x'])
237 nt.assert_equal(words, ['x'])
239
238
240 def test_get__all__entries_no__all__ok():
239 def test_get__all__entries_no__all__ok():
241 class A(object):
240 class A(object):
242 pass
241 pass
243 words = completer.get__all__entries(A())
242 words = completer.get__all__entries(A())
244 nt.assert_equal(words, [])
243 nt.assert_equal(words, [])
General Comments 0
You need to be logged in to leave comments. Login now