##// END OF EJS Templates
Typo + Add Warning class for deprecation....
Matthias Bussonnier -
Show More
@@ -1,1176 +1,1176 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Word completion for IPython.
2 """Word completion for IPython.
3
3
4 This module stared as fork of the rlcompleter module in the Python standard
4 This module started as fork of the rlcompleter module in the Python standard
5 library. The original enhancements made to rlcompleter have been sent
5 library. The original enhancements made to rlcompleter have been sent
6 upstream and were accepted as of Python 2.3,
6 upstream and were accepted as of Python 2.3,
7
7
8
8
9 This is now mostly Completer implementation made to function with
9 This is now mostly Completer implementation made to function with
10 prompt_toolkit, but that should still work with readline.
10 prompt_toolkit, but that should still work with readline.
11 """
11 """
12
12
13 # Copyright (c) IPython Development Team.
13 # Copyright (c) IPython Development Team.
14 # Distributed under the terms of the Modified BSD License.
14 # Distributed under the terms of the Modified BSD License.
15 #
15 #
16 # Some of this code originated from rlcompleter in the Python standard library
16 # Some of this code originated from rlcompleter in the Python standard library
17 # Copyright (C) 2001 Python Software Foundation, www.python.org
17 # Copyright (C) 2001 Python Software Foundation, www.python.org
18
18
19 from __future__ import print_function
19 from __future__ import print_function
20
20
21 import __main__
21 import __main__
22 import glob
22 import glob
23 import inspect
23 import inspect
24 import itertools
24 import itertools
25 import keyword
25 import keyword
26 import os
26 import os
27 import re
27 import re
28 import sys
28 import sys
29 import unicodedata
29 import unicodedata
30 import string
30 import string
31
31
32 from traitlets.config.configurable import Configurable
32 from traitlets.config.configurable import Configurable
33 from IPython.core.error import TryNext
33 from IPython.core.error import TryNext
34 from IPython.core.inputsplitter import ESC_MAGIC
34 from IPython.core.inputsplitter import ESC_MAGIC
35 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
35 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
36 from IPython.utils import generics
36 from IPython.utils import generics
37 from IPython.utils.decorators import undoc
37 from IPython.utils.decorators import undoc
38 from IPython.utils.dir2 import dir2, get_real_method
38 from IPython.utils.dir2 import dir2, get_real_method
39 from IPython.utils.process import arg_split
39 from IPython.utils.process import arg_split
40 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
40 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
41 from traitlets import Bool, Enum, observe
41 from traitlets import Bool, Enum, observe
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Globals
44 # Globals
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46
46
47 # Public API
47 # Public API
48 __all__ = ['Completer','IPCompleter']
48 __all__ = ['Completer','IPCompleter']
49
49
50 if sys.platform == 'win32':
50 if sys.platform == 'win32':
51 PROTECTABLES = ' '
51 PROTECTABLES = ' '
52 else:
52 else:
53 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
53 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
54
54
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Main functions and classes
57 # Main functions and classes
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 def has_open_quotes(s):
60 def has_open_quotes(s):
61 """Return whether a string has open quotes.
61 """Return whether a string has open quotes.
62
62
63 This simply counts whether the number of quote characters of either type in
63 This simply counts whether the number of quote characters of either type in
64 the string is odd.
64 the string is odd.
65
65
66 Returns
66 Returns
67 -------
67 -------
68 If there is an open quote, the quote character is returned. Else, return
68 If there is an open quote, the quote character is returned. Else, return
69 False.
69 False.
70 """
70 """
71 # We check " first, then ', so complex cases with nested quotes will get
71 # We check " first, then ', so complex cases with nested quotes will get
72 # the " to take precedence.
72 # the " to take precedence.
73 if s.count('"') % 2:
73 if s.count('"') % 2:
74 return '"'
74 return '"'
75 elif s.count("'") % 2:
75 elif s.count("'") % 2:
76 return "'"
76 return "'"
77 else:
77 else:
78 return False
78 return False
79
79
80
80
81 def protect_filename(s):
81 def protect_filename(s):
82 """Escape a string to protect certain characters."""
82 """Escape a string to protect certain characters."""
83 if set(s) & set(PROTECTABLES):
83 if set(s) & set(PROTECTABLES):
84 if sys.platform == "win32":
84 if sys.platform == "win32":
85 return '"' + s + '"'
85 return '"' + s + '"'
86 else:
86 else:
87 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
87 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
88 else:
88 else:
89 return s
89 return s
90
90
91
91
92 def expand_user(path):
92 def expand_user(path):
93 """Expand '~'-style usernames in strings.
93 """Expand '~'-style usernames in strings.
94
94
95 This is similar to :func:`os.path.expanduser`, but it computes and returns
95 This is similar to :func:`os.path.expanduser`, but it computes and returns
96 extra information that will be useful if the input was being used in
96 extra information that will be useful if the input was being used in
97 computing completions, and you wish to return the completions with the
97 computing completions, and you wish to return the completions with the
98 original '~' instead of its expanded value.
98 original '~' instead of its expanded value.
99
99
100 Parameters
100 Parameters
101 ----------
101 ----------
102 path : str
102 path : str
103 String to be expanded. If no ~ is present, the output is the same as the
103 String to be expanded. If no ~ is present, the output is the same as the
104 input.
104 input.
105
105
106 Returns
106 Returns
107 -------
107 -------
108 newpath : str
108 newpath : str
109 Result of ~ expansion in the input path.
109 Result of ~ expansion in the input path.
110 tilde_expand : bool
110 tilde_expand : bool
111 Whether any expansion was performed or not.
111 Whether any expansion was performed or not.
112 tilde_val : str
112 tilde_val : str
113 The value that ~ was replaced with.
113 The value that ~ was replaced with.
114 """
114 """
115 # Default values
115 # Default values
116 tilde_expand = False
116 tilde_expand = False
117 tilde_val = ''
117 tilde_val = ''
118 newpath = path
118 newpath = path
119
119
120 if path.startswith('~'):
120 if path.startswith('~'):
121 tilde_expand = True
121 tilde_expand = True
122 rest = len(path)-1
122 rest = len(path)-1
123 newpath = os.path.expanduser(path)
123 newpath = os.path.expanduser(path)
124 if rest:
124 if rest:
125 tilde_val = newpath[:-rest]
125 tilde_val = newpath[:-rest]
126 else:
126 else:
127 tilde_val = newpath
127 tilde_val = newpath
128
128
129 return newpath, tilde_expand, tilde_val
129 return newpath, tilde_expand, tilde_val
130
130
131
131
132 def compress_user(path, tilde_expand, tilde_val):
132 def compress_user(path, tilde_expand, tilde_val):
133 """Does the opposite of expand_user, with its outputs.
133 """Does the opposite of expand_user, with its outputs.
134 """
134 """
135 if tilde_expand:
135 if tilde_expand:
136 return path.replace(tilde_val, '~')
136 return path.replace(tilde_val, '~')
137 else:
137 else:
138 return path
138 return path
139
139
140
140
141 def completions_sorting_key(word):
141 def completions_sorting_key(word):
142 """key for sorting completions
142 """key for sorting completions
143
143
144 This does several things:
144 This does several things:
145
145
146 - Lowercase all completions, so they are sorted alphabetically with
146 - Lowercase all completions, so they are sorted alphabetically with
147 upper and lower case words mingled
147 upper and lower case words mingled
148 - Demote any completions starting with underscores to the end
148 - Demote any completions starting with underscores to the end
149 - Insert any %magic and %%cellmagic completions in the alphabetical order
149 - Insert any %magic and %%cellmagic completions in the alphabetical order
150 by their name
150 by their name
151 """
151 """
152 # Case insensitive sort
152 # Case insensitive sort
153 word = word.lower()
153 word = word.lower()
154
154
155 prio1, prio2 = 0, 0
155 prio1, prio2 = 0, 0
156
156
157 if word.startswith('__'):
157 if word.startswith('__'):
158 prio1 = 2
158 prio1 = 2
159 elif word.startswith('_'):
159 elif word.startswith('_'):
160 prio1 = 1
160 prio1 = 1
161
161
162 if word.endswith('='):
162 if word.endswith('='):
163 prio1 = -1
163 prio1 = -1
164
164
165 if word.startswith('%%'):
165 if word.startswith('%%'):
166 # If there's another % in there, this is something else, so leave it alone
166 # If there's another % in there, this is something else, so leave it alone
167 if not "%" in word[2:]:
167 if not "%" in word[2:]:
168 word = word[2:]
168 word = word[2:]
169 prio2 = 2
169 prio2 = 2
170 elif word.startswith('%'):
170 elif word.startswith('%'):
171 if not "%" in word[1:]:
171 if not "%" in word[1:]:
172 word = word[1:]
172 word = word[1:]
173 prio2 = 1
173 prio2 = 1
174
174
175 return prio1, word, prio2
175 return prio1, word, prio2
176
176
177
177
178 @undoc
178 @undoc
179 class Bunch(object): pass
179 class Bunch(object): pass
180
180
181
181
182 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
182 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
183 GREEDY_DELIMS = ' =\r\n'
183 GREEDY_DELIMS = ' =\r\n'
184
184
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 regular expression)"""
197 automatically builds the necessary regular expression)"""
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.delims = delims
215 self.delims = delims
216
216
217 @property
217 @property
218 def delims(self):
218 def delims(self):
219 """Return the string of delimiter characters."""
219 """Return the string of delimiter characters."""
220 return self._delims
220 return self._delims
221
221
222 @delims.setter
222 @delims.setter
223 def delims(self, delims):
223 def delims(self, delims):
224 """Set the delimiters for line splitting."""
224 """Set the delimiters for line splitting."""
225 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
225 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
226 self._delim_re = re.compile(expr)
226 self._delim_re = re.compile(expr)
227 self._delims = delims
227 self._delims = delims
228 self._delim_expr = expr
228 self._delim_expr = expr
229
229
230 def split_line(self, line, cursor_pos=None):
230 def split_line(self, line, cursor_pos=None):
231 """Split a line of text with a cursor at the given position.
231 """Split a line of text with a cursor at the given position.
232 """
232 """
233 l = line if cursor_pos is None else line[:cursor_pos]
233 l = line if cursor_pos is None else line[:cursor_pos]
234 return self._delim_re.split(l)[-1]
234 return self._delim_re.split(l)[-1]
235
235
236
236
237 class Completer(Configurable):
237 class Completer(Configurable):
238
238
239 greedy = Bool(False,
239 greedy = Bool(False,
240 help="""Activate greedy completion
240 help="""Activate greedy completion
241 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
241 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
242
242
243 This will enable completion on elements of lists, results of function calls, etc.,
243 This will enable completion on elements of lists, results of function calls, etc.,
244 but can be unsafe because the code is actually evaluated on TAB.
244 but can be unsafe because the code is actually evaluated on TAB.
245 """
245 """
246 ).tag(config=True)
246 ).tag(config=True)
247
247
248
248
249 def __init__(self, namespace=None, global_namespace=None, **kwargs):
249 def __init__(self, namespace=None, global_namespace=None, **kwargs):
250 """Create a new completer for the command line.
250 """Create a new completer for the command line.
251
251
252 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
252 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
253
253
254 If unspecified, the default namespace where completions are performed
254 If unspecified, the default namespace where completions are performed
255 is __main__ (technically, __main__.__dict__). Namespaces should be
255 is __main__ (technically, __main__.__dict__). Namespaces should be
256 given as dictionaries.
256 given as dictionaries.
257
257
258 An optional second namespace can be given. This allows the completer
258 An optional second namespace can be given. This allows the completer
259 to handle cases where both the local and global scopes need to be
259 to handle cases where both the local and global scopes need to be
260 distinguished.
260 distinguished.
261
261
262 Completer instances should be used as the completion mechanism of
262 Completer instances should be used as the completion mechanism of
263 readline via the set_completer() call:
263 readline via the set_completer() call:
264
264
265 readline.set_completer(Completer(my_namespace).complete)
265 readline.set_completer(Completer(my_namespace).complete)
266 """
266 """
267
267
268 # Don't bind to namespace quite yet, but flag whether the user wants a
268 # Don't bind to namespace quite yet, but flag whether the user wants a
269 # specific namespace or to use __main__.__dict__. This will allow us
269 # specific namespace or to use __main__.__dict__. This will allow us
270 # to bind to __main__.__dict__ at completion time, not now.
270 # to bind to __main__.__dict__ at completion time, not now.
271 if namespace is None:
271 if namespace is None:
272 self.use_main_ns = 1
272 self.use_main_ns = 1
273 else:
273 else:
274 self.use_main_ns = 0
274 self.use_main_ns = 0
275 self.namespace = namespace
275 self.namespace = namespace
276
276
277 # The global namespace, if given, can be bound directly
277 # The global namespace, if given, can be bound directly
278 if global_namespace is None:
278 if global_namespace is None:
279 self.global_namespace = {}
279 self.global_namespace = {}
280 else:
280 else:
281 self.global_namespace = global_namespace
281 self.global_namespace = global_namespace
282
282
283 super(Completer, self).__init__(**kwargs)
283 super(Completer, self).__init__(**kwargs)
284
284
285 def complete(self, text, state):
285 def complete(self, text, state):
286 """Return the next possible completion for 'text'.
286 """Return the next possible completion for 'text'.
287
287
288 This is called successively with state == 0, 1, 2, ... until it
288 This is called successively with state == 0, 1, 2, ... until it
289 returns None. The completion should begin with 'text'.
289 returns None. The completion should begin with 'text'.
290
290
291 """
291 """
292 if self.use_main_ns:
292 if self.use_main_ns:
293 self.namespace = __main__.__dict__
293 self.namespace = __main__.__dict__
294
294
295 if state == 0:
295 if state == 0:
296 if "." in text:
296 if "." in text:
297 self.matches = self.attr_matches(text)
297 self.matches = self.attr_matches(text)
298 else:
298 else:
299 self.matches = self.global_matches(text)
299 self.matches = self.global_matches(text)
300 try:
300 try:
301 return self.matches[state]
301 return self.matches[state]
302 except IndexError:
302 except IndexError:
303 return None
303 return None
304
304
305 def global_matches(self, text):
305 def global_matches(self, text):
306 """Compute matches when text is a simple name.
306 """Compute matches when text is a simple name.
307
307
308 Return a list of all keywords, built-in functions and names currently
308 Return a list of all keywords, built-in functions and names currently
309 defined in self.namespace or self.global_namespace that match.
309 defined in self.namespace or self.global_namespace that match.
310
310
311 """
311 """
312 matches = []
312 matches = []
313 match_append = matches.append
313 match_append = matches.append
314 n = len(text)
314 n = len(text)
315 for lst in [keyword.kwlist,
315 for lst in [keyword.kwlist,
316 builtin_mod.__dict__.keys(),
316 builtin_mod.__dict__.keys(),
317 self.namespace.keys(),
317 self.namespace.keys(),
318 self.global_namespace.keys()]:
318 self.global_namespace.keys()]:
319 for word in lst:
319 for word in lst:
320 if word[:n] == text and word != "__builtins__":
320 if word[:n] == text and word != "__builtins__":
321 match_append(word)
321 match_append(word)
322 return [cast_unicode_py2(m) for m in matches]
322 return [cast_unicode_py2(m) for m in matches]
323
323
324 def attr_matches(self, text):
324 def attr_matches(self, text):
325 """Compute matches when text contains a dot.
325 """Compute matches when text contains a dot.
326
326
327 Assuming the text is of the form NAME.NAME....[NAME], and is
327 Assuming the text is of the form NAME.NAME....[NAME], and is
328 evaluatable in self.namespace or self.global_namespace, it will be
328 evaluatable in self.namespace or self.global_namespace, it will be
329 evaluated and its attributes (as revealed by dir()) are used as
329 evaluated and its attributes (as revealed by dir()) are used as
330 possible completions. (For class instances, class members are are
330 possible completions. (For class instances, class members are are
331 also considered.)
331 also considered.)
332
332
333 WARNING: this can still invoke arbitrary C code, if an object
333 WARNING: this can still invoke arbitrary C code, if an object
334 with a __getattr__ hook is evaluated.
334 with a __getattr__ hook is evaluated.
335
335
336 """
336 """
337
337
338 # Another option, seems to work great. Catches things like ''.<tab>
338 # Another option, seems to work great. Catches things like ''.<tab>
339 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
339 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
340
340
341 if m:
341 if m:
342 expr, attr = m.group(1, 3)
342 expr, attr = m.group(1, 3)
343 elif self.greedy:
343 elif self.greedy:
344 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
344 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
345 if not m2:
345 if not m2:
346 return []
346 return []
347 expr, attr = m2.group(1,2)
347 expr, attr = m2.group(1,2)
348 else:
348 else:
349 return []
349 return []
350
350
351 try:
351 try:
352 obj = eval(expr, self.namespace)
352 obj = eval(expr, self.namespace)
353 except:
353 except:
354 try:
354 try:
355 obj = eval(expr, self.global_namespace)
355 obj = eval(expr, self.global_namespace)
356 except:
356 except:
357 return []
357 return []
358
358
359 if self.limit_to__all__ and hasattr(obj, '__all__'):
359 if self.limit_to__all__ and hasattr(obj, '__all__'):
360 words = get__all__entries(obj)
360 words = get__all__entries(obj)
361 else:
361 else:
362 words = dir2(obj)
362 words = dir2(obj)
363
363
364 try:
364 try:
365 words = generics.complete_object(obj, words)
365 words = generics.complete_object(obj, words)
366 except TryNext:
366 except TryNext:
367 pass
367 pass
368 except Exception:
368 except Exception:
369 # Silence errors from completion function
369 # Silence errors from completion function
370 #raise # dbg
370 #raise # dbg
371 pass
371 pass
372 # Build match list to return
372 # Build match list to return
373 n = len(attr)
373 n = len(attr)
374 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
374 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
375
375
376
376
377 def get__all__entries(obj):
377 def get__all__entries(obj):
378 """returns the strings in the __all__ attribute"""
378 """returns the strings in the __all__ attribute"""
379 try:
379 try:
380 words = getattr(obj, '__all__')
380 words = getattr(obj, '__all__')
381 except:
381 except:
382 return []
382 return []
383
383
384 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
384 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
385
385
386
386
387 def match_dict_keys(keys, prefix, delims):
387 def match_dict_keys(keys, prefix, delims):
388 """Used by dict_key_matches, matching the prefix to a list of keys"""
388 """Used by dict_key_matches, matching the prefix to a list of keys"""
389 if not prefix:
389 if not prefix:
390 return None, 0, [repr(k) for k in keys
390 return None, 0, [repr(k) for k in keys
391 if isinstance(k, (string_types, bytes))]
391 if isinstance(k, (string_types, bytes))]
392 quote_match = re.search('["\']', prefix)
392 quote_match = re.search('["\']', prefix)
393 quote = quote_match.group()
393 quote = quote_match.group()
394 try:
394 try:
395 prefix_str = eval(prefix + quote, {})
395 prefix_str = eval(prefix + quote, {})
396 except Exception:
396 except Exception:
397 return None, 0, []
397 return None, 0, []
398
398
399 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
399 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
400 token_match = re.search(pattern, prefix, re.UNICODE)
400 token_match = re.search(pattern, prefix, re.UNICODE)
401 token_start = token_match.start()
401 token_start = token_match.start()
402 token_prefix = token_match.group()
402 token_prefix = token_match.group()
403
403
404 # TODO: support bytes in Py3k
404 # TODO: support bytes in Py3k
405 matched = []
405 matched = []
406 for key in keys:
406 for key in keys:
407 try:
407 try:
408 if not key.startswith(prefix_str):
408 if not key.startswith(prefix_str):
409 continue
409 continue
410 except (AttributeError, TypeError, UnicodeError):
410 except (AttributeError, TypeError, UnicodeError):
411 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
411 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
412 continue
412 continue
413
413
414 # reformat remainder of key to begin with prefix
414 # reformat remainder of key to begin with prefix
415 rem = key[len(prefix_str):]
415 rem = key[len(prefix_str):]
416 # force repr wrapped in '
416 # force repr wrapped in '
417 rem_repr = repr(rem + '"')
417 rem_repr = repr(rem + '"')
418 if rem_repr.startswith('u') and prefix[0] not in 'uU':
418 if rem_repr.startswith('u') and prefix[0] not in 'uU':
419 # Found key is unicode, but prefix is Py2 string.
419 # Found key is unicode, but prefix is Py2 string.
420 # Therefore attempt to interpret key as string.
420 # Therefore attempt to interpret key as string.
421 try:
421 try:
422 rem_repr = repr(rem.encode('ascii') + '"')
422 rem_repr = repr(rem.encode('ascii') + '"')
423 except UnicodeEncodeError:
423 except UnicodeEncodeError:
424 continue
424 continue
425
425
426 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
426 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
427 if quote == '"':
427 if quote == '"':
428 # The entered prefix is quoted with ",
428 # The entered prefix is quoted with ",
429 # but the match is quoted with '.
429 # but the match is quoted with '.
430 # A contained " hence needs escaping for comparison:
430 # A contained " hence needs escaping for comparison:
431 rem_repr = rem_repr.replace('"', '\\"')
431 rem_repr = rem_repr.replace('"', '\\"')
432
432
433 # then reinsert prefix from start of token
433 # then reinsert prefix from start of token
434 matched.append('%s%s' % (token_prefix, rem_repr))
434 matched.append('%s%s' % (token_prefix, rem_repr))
435 return quote, token_start, matched
435 return quote, token_start, matched
436
436
437
437
438 def _safe_isinstance(obj, module, class_name):
438 def _safe_isinstance(obj, module, class_name):
439 """Checks if obj is an instance of module.class_name if loaded
439 """Checks if obj is an instance of module.class_name if loaded
440 """
440 """
441 return (module in sys.modules and
441 return (module in sys.modules and
442 isinstance(obj, getattr(__import__(module), class_name)))
442 isinstance(obj, getattr(__import__(module), class_name)))
443
443
444
444
445 def back_unicode_name_matches(text):
445 def back_unicode_name_matches(text):
446 u"""Match unicode characters back to unicode name
446 u"""Match unicode characters back to unicode name
447
447
448 This does β˜ƒ -> \\snowman
448 This does β˜ƒ -> \\snowman
449
449
450 Note that snowman is not a valid python3 combining character but will be expanded.
450 Note that snowman is not a valid python3 combining character but will be expanded.
451 Though it will not recombine back to the snowman character by the completion machinery.
451 Though it will not recombine back to the snowman character by the completion machinery.
452
452
453 This will not either back-complete standard sequences like \\n, \\b ...
453 This will not either back-complete standard sequences like \\n, \\b ...
454
454
455 Used on Python 3 only.
455 Used on Python 3 only.
456 """
456 """
457 if len(text)<2:
457 if len(text)<2:
458 return u'', ()
458 return u'', ()
459 maybe_slash = text[-2]
459 maybe_slash = text[-2]
460 if maybe_slash != '\\':
460 if maybe_slash != '\\':
461 return u'', ()
461 return u'', ()
462
462
463 char = text[-1]
463 char = text[-1]
464 # no expand on quote for completion in strings.
464 # no expand on quote for completion in strings.
465 # nor backcomplete standard ascii keys
465 # nor backcomplete standard ascii keys
466 if char in string.ascii_letters or char in ['"',"'"]:
466 if char in string.ascii_letters or char in ['"',"'"]:
467 return u'', ()
467 return u'', ()
468 try :
468 try :
469 unic = unicodedata.name(char)
469 unic = unicodedata.name(char)
470 return '\\'+char,['\\'+unic]
470 return '\\'+char,['\\'+unic]
471 except KeyError:
471 except KeyError:
472 pass
472 pass
473 return u'', ()
473 return u'', ()
474
474
475 def back_latex_name_matches(text):
475 def back_latex_name_matches(text):
476 u"""Match latex characters back to unicode name
476 u"""Match latex characters back to unicode name
477
477
478 This does ->\\sqrt
478 This does ->\\sqrt
479
479
480 Used on Python 3 only.
480 Used on Python 3 only.
481 """
481 """
482 if len(text)<2:
482 if len(text)<2:
483 return u'', ()
483 return u'', ()
484 maybe_slash = text[-2]
484 maybe_slash = text[-2]
485 if maybe_slash != '\\':
485 if maybe_slash != '\\':
486 return u'', ()
486 return u'', ()
487
487
488
488
489 char = text[-1]
489 char = text[-1]
490 # no expand on quote for completion in strings.
490 # no expand on quote for completion in strings.
491 # nor backcomplete standard ascii keys
491 # nor backcomplete standard ascii keys
492 if char in string.ascii_letters or char in ['"',"'"]:
492 if char in string.ascii_letters or char in ['"',"'"]:
493 return u'', ()
493 return u'', ()
494 try :
494 try :
495 latex = reverse_latex_symbol[char]
495 latex = reverse_latex_symbol[char]
496 # '\\' replace the \ as well
496 # '\\' replace the \ as well
497 return '\\'+char,[latex]
497 return '\\'+char,[latex]
498 except KeyError:
498 except KeyError:
499 pass
499 pass
500 return u'', ()
500 return u'', ()
501
501
502
502
503 class IPCompleter(Completer):
503 class IPCompleter(Completer):
504 """Extension of the completer class with IPython-specific features"""
504 """Extension of the completer class with IPython-specific features"""
505
505
506 @observe('greedy')
506 @observe('greedy')
507 def _greedy_changed(self, change):
507 def _greedy_changed(self, change):
508 """update the splitter and readline delims when greedy is changed"""
508 """update the splitter and readline delims when greedy is changed"""
509 if change['new']:
509 if change['new']:
510 self.splitter.delims = GREEDY_DELIMS
510 self.splitter.delims = GREEDY_DELIMS
511 else:
511 else:
512 self.splitter.delims = DELIMS
512 self.splitter.delims = DELIMS
513
513
514 if self.readline:
514 if self.readline:
515 self.readline.set_completer_delims(self.splitter.delims)
515 self.readline.set_completer_delims(self.splitter.delims)
516
516
517 merge_completions = Bool(True,
517 merge_completions = Bool(True,
518 help="""Whether to merge completion results into a single list
518 help="""Whether to merge completion results into a single list
519
519
520 If False, only the completion results from the first non-empty
520 If False, only the completion results from the first non-empty
521 completer will be returned.
521 completer will be returned.
522 """
522 """
523 ).tag(config=True)
523 ).tag(config=True)
524 omit__names = Enum((0,1,2), default_value=2,
524 omit__names = Enum((0,1,2), default_value=2,
525 help="""Instruct the completer to omit private method names
525 help="""Instruct the completer to omit private method names
526
526
527 Specifically, when completing on ``object.<tab>``.
527 Specifically, when completing on ``object.<tab>``.
528
528
529 When 2 [default]: all names that start with '_' will be excluded.
529 When 2 [default]: all names that start with '_' will be excluded.
530
530
531 When 1: all 'magic' names (``__foo__``) will be excluded.
531 When 1: all 'magic' names (``__foo__``) will be excluded.
532
532
533 When 0: nothing will be excluded.
533 When 0: nothing will be excluded.
534 """
534 """
535 ).tag(config=True)
535 ).tag(config=True)
536 limit_to__all__ = Bool(False,
536 limit_to__all__ = Bool(False,
537 help="""
537 help="""
538 DEPRECATED as of version 5.0.
538 DEPRECATED as of version 5.0.
539
539
540 Instruct the completer to use __all__ for the completion
540 Instruct the completer to use __all__ for the completion
541
541
542 Specifically, when completing on ``object.<tab>``.
542 Specifically, when completing on ``object.<tab>``.
543
543
544 When True: only those names in obj.__all__ will be included.
544 When True: only those names in obj.__all__ will be included.
545
545
546 When False [default]: the __all__ attribute is ignored
546 When False [default]: the __all__ attribute is ignored
547 """,
547 """,
548 ).tag(config=True)
548 ).tag(config=True)
549
549
550 def __init__(self, shell=None, namespace=None, global_namespace=None,
550 def __init__(self, shell=None, namespace=None, global_namespace=None,
551 use_readline=True, config=None, **kwargs):
551 use_readline=True, config=None, **kwargs):
552 """IPCompleter() -> completer
552 """IPCompleter() -> completer
553
553
554 Return a completer object suitable for use by the readline library
554 Return a completer object suitable for use by the readline library
555 via readline.set_completer().
555 via readline.set_completer().
556
556
557 Inputs:
557 Inputs:
558
558
559 - shell: a pointer to the ipython shell itself. This is needed
559 - shell: a pointer to the ipython shell itself. This is needed
560 because this completer knows about magic functions, and those can
560 because this completer knows about magic functions, and those can
561 only be accessed via the ipython instance.
561 only be accessed via the ipython instance.
562
562
563 - namespace: an optional dict where completions are performed.
563 - namespace: an optional dict where completions are performed.
564
564
565 - global_namespace: secondary optional dict for completions, to
565 - global_namespace: secondary optional dict for completions, to
566 handle cases (such as IPython embedded inside functions) where
566 handle cases (such as IPython embedded inside functions) where
567 both Python scopes are visible.
567 both Python scopes are visible.
568
568
569 use_readline : bool, optional
569 use_readline : bool, optional
570 If true, use the readline library. This completer can still function
570 If true, use the readline library. This completer can still function
571 without readline, though in that case callers must provide some extra
571 without readline, though in that case callers must provide some extra
572 information on each call about the current line."""
572 information on each call about the current line."""
573
573
574 self.magic_escape = ESC_MAGIC
574 self.magic_escape = ESC_MAGIC
575 self.splitter = CompletionSplitter()
575 self.splitter = CompletionSplitter()
576
576
577 # Readline configuration, only used by the rlcompleter method.
577 # Readline configuration, only used by the rlcompleter method.
578 if use_readline:
578 if use_readline:
579 # We store the right version of readline so that later code
579 # We store the right version of readline so that later code
580 import IPython.utils.rlineimpl as readline
580 import IPython.utils.rlineimpl as readline
581 self.readline = readline
581 self.readline = readline
582 else:
582 else:
583 self.readline = None
583 self.readline = None
584
584
585 # _greedy_changed() depends on splitter and readline being defined:
585 # _greedy_changed() depends on splitter and readline being defined:
586 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
586 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
587 config=config, **kwargs)
587 config=config, **kwargs)
588
588
589 # List where completion matches will be stored
589 # List where completion matches will be stored
590 self.matches = []
590 self.matches = []
591 self.shell = shell
591 self.shell = shell
592 # Regexp to split filenames with spaces in them
592 # Regexp to split filenames with spaces in them
593 self.space_name_re = re.compile(r'([^\\] )')
593 self.space_name_re = re.compile(r'([^\\] )')
594 # Hold a local ref. to glob.glob for speed
594 # Hold a local ref. to glob.glob for speed
595 self.glob = glob.glob
595 self.glob = glob.glob
596
596
597 # Determine if we are running on 'dumb' terminals, like (X)Emacs
597 # Determine if we are running on 'dumb' terminals, like (X)Emacs
598 # buffers, to avoid completion problems.
598 # buffers, to avoid completion problems.
599 term = os.environ.get('TERM','xterm')
599 term = os.environ.get('TERM','xterm')
600 self.dumb_terminal = term in ['dumb','emacs']
600 self.dumb_terminal = term in ['dumb','emacs']
601
601
602 # Special handling of backslashes needed in win32 platforms
602 # Special handling of backslashes needed in win32 platforms
603 if sys.platform == "win32":
603 if sys.platform == "win32":
604 self.clean_glob = self._clean_glob_win32
604 self.clean_glob = self._clean_glob_win32
605 else:
605 else:
606 self.clean_glob = self._clean_glob
606 self.clean_glob = self._clean_glob
607
607
608 #regexp to parse docstring for function signature
608 #regexp to parse docstring for function signature
609 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
609 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
610 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
610 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
611 #use this if positional argument name is also needed
611 #use this if positional argument name is also needed
612 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
612 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
613
613
614 # All active matcher routines for completion
614 # All active matcher routines for completion
615 self.matchers = [
615 self.matchers = [
616 self.python_matches,
616 self.python_matches,
617 self.file_matches,
617 self.file_matches,
618 self.magic_matches,
618 self.magic_matches,
619 self.python_func_kw_matches,
619 self.python_func_kw_matches,
620 self.dict_key_matches,
620 self.dict_key_matches,
621 ]
621 ]
622
622
623 # This is set externally by InteractiveShell
623 # This is set externally by InteractiveShell
624 self.custom_completers = None
624 self.custom_completers = None
625
625
626 def all_completions(self, text):
626 def all_completions(self, text):
627 """
627 """
628 Wrapper around the complete method for the benefit of emacs.
628 Wrapper around the complete method for the benefit of emacs.
629 """
629 """
630 return self.complete(text)[1]
630 return self.complete(text)[1]
631
631
632 def _clean_glob(self, text):
632 def _clean_glob(self, text):
633 return self.glob("%s*" % text)
633 return self.glob("%s*" % text)
634
634
635 def _clean_glob_win32(self,text):
635 def _clean_glob_win32(self,text):
636 return [f.replace("\\","/")
636 return [f.replace("\\","/")
637 for f in self.glob("%s*" % text)]
637 for f in self.glob("%s*" % text)]
638
638
639 def file_matches(self, text):
639 def file_matches(self, text):
640 """Match filenames, expanding ~USER type strings.
640 """Match filenames, expanding ~USER type strings.
641
641
642 Most of the seemingly convoluted logic in this completer is an
642 Most of the seemingly convoluted logic in this completer is an
643 attempt to handle filenames with spaces in them. And yet it's not
643 attempt to handle filenames with spaces in them. And yet it's not
644 quite perfect, because Python's readline doesn't expose all of the
644 quite perfect, because Python's readline doesn't expose all of the
645 GNU readline details needed for this to be done correctly.
645 GNU readline details needed for this to be done correctly.
646
646
647 For a filename with a space in it, the printed completions will be
647 For a filename with a space in it, the printed completions will be
648 only the parts after what's already been typed (instead of the
648 only the parts after what's already been typed (instead of the
649 full completions, as is normally done). I don't think with the
649 full completions, as is normally done). I don't think with the
650 current (as of Python 2.3) Python readline it's possible to do
650 current (as of Python 2.3) Python readline it's possible to do
651 better."""
651 better."""
652
652
653 # chars that require escaping with backslash - i.e. chars
653 # chars that require escaping with backslash - i.e. chars
654 # that readline treats incorrectly as delimiters, but we
654 # that readline treats incorrectly as delimiters, but we
655 # don't want to treat as delimiters in filename matching
655 # don't want to treat as delimiters in filename matching
656 # when escaped with backslash
656 # when escaped with backslash
657 if text.startswith('!'):
657 if text.startswith('!'):
658 text = text[1:]
658 text = text[1:]
659 text_prefix = u'!'
659 text_prefix = u'!'
660 else:
660 else:
661 text_prefix = u''
661 text_prefix = u''
662
662
663 text_until_cursor = self.text_until_cursor
663 text_until_cursor = self.text_until_cursor
664 # track strings with open quotes
664 # track strings with open quotes
665 open_quotes = has_open_quotes(text_until_cursor)
665 open_quotes = has_open_quotes(text_until_cursor)
666
666
667 if '(' in text_until_cursor or '[' in text_until_cursor:
667 if '(' in text_until_cursor or '[' in text_until_cursor:
668 lsplit = text
668 lsplit = text
669 else:
669 else:
670 try:
670 try:
671 # arg_split ~ shlex.split, but with unicode bugs fixed by us
671 # arg_split ~ shlex.split, but with unicode bugs fixed by us
672 lsplit = arg_split(text_until_cursor)[-1]
672 lsplit = arg_split(text_until_cursor)[-1]
673 except ValueError:
673 except ValueError:
674 # typically an unmatched ", or backslash without escaped char.
674 # typically an unmatched ", or backslash without escaped char.
675 if open_quotes:
675 if open_quotes:
676 lsplit = text_until_cursor.split(open_quotes)[-1]
676 lsplit = text_until_cursor.split(open_quotes)[-1]
677 else:
677 else:
678 return []
678 return []
679 except IndexError:
679 except IndexError:
680 # tab pressed on empty line
680 # tab pressed on empty line
681 lsplit = ""
681 lsplit = ""
682
682
683 if not open_quotes and lsplit != protect_filename(lsplit):
683 if not open_quotes and lsplit != protect_filename(lsplit):
684 # if protectables are found, do matching on the whole escaped name
684 # if protectables are found, do matching on the whole escaped name
685 has_protectables = True
685 has_protectables = True
686 text0,text = text,lsplit
686 text0,text = text,lsplit
687 else:
687 else:
688 has_protectables = False
688 has_protectables = False
689 text = os.path.expanduser(text)
689 text = os.path.expanduser(text)
690
690
691 if text == "":
691 if text == "":
692 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
692 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
693
693
694 # Compute the matches from the filesystem
694 # Compute the matches from the filesystem
695 m0 = self.clean_glob(text.replace('\\',''))
695 m0 = self.clean_glob(text.replace('\\',''))
696
696
697 if has_protectables:
697 if has_protectables:
698 # If we had protectables, we need to revert our changes to the
698 # If we had protectables, we need to revert our changes to the
699 # beginning of filename so that we don't double-write the part
699 # beginning of filename so that we don't double-write the part
700 # of the filename we have so far
700 # of the filename we have so far
701 len_lsplit = len(lsplit)
701 len_lsplit = len(lsplit)
702 matches = [text_prefix + text0 +
702 matches = [text_prefix + text0 +
703 protect_filename(f[len_lsplit:]) for f in m0]
703 protect_filename(f[len_lsplit:]) for f in m0]
704 else:
704 else:
705 if open_quotes:
705 if open_quotes:
706 # if we have a string with an open quote, we don't need to
706 # if we have a string with an open quote, we don't need to
707 # protect the names at all (and we _shouldn't_, as it
707 # protect the names at all (and we _shouldn't_, as it
708 # would cause bugs when the filesystem call is made).
708 # would cause bugs when the filesystem call is made).
709 matches = m0
709 matches = m0
710 else:
710 else:
711 matches = [text_prefix +
711 matches = [text_prefix +
712 protect_filename(f) for f in m0]
712 protect_filename(f) for f in m0]
713
713
714 # Mark directories in input list by appending '/' to their names.
714 # Mark directories in input list by appending '/' to their names.
715 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
715 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
716
716
717 def magic_matches(self, text):
717 def magic_matches(self, text):
718 """Match magics"""
718 """Match magics"""
719 # Get all shell magics now rather than statically, so magics loaded at
719 # Get all shell magics now rather than statically, so magics loaded at
720 # runtime show up too.
720 # runtime show up too.
721 lsm = self.shell.magics_manager.lsmagic()
721 lsm = self.shell.magics_manager.lsmagic()
722 line_magics = lsm['line']
722 line_magics = lsm['line']
723 cell_magics = lsm['cell']
723 cell_magics = lsm['cell']
724 pre = self.magic_escape
724 pre = self.magic_escape
725 pre2 = pre+pre
725 pre2 = pre+pre
726
726
727 # Completion logic:
727 # Completion logic:
728 # - user gives %%: only do cell magics
728 # - user gives %%: only do cell magics
729 # - user gives %: do both line and cell magics
729 # - user gives %: do both line and cell magics
730 # - no prefix: do both
730 # - no prefix: do both
731 # In other words, line magics are skipped if the user gives %% explicitly
731 # In other words, line magics are skipped if the user gives %% explicitly
732 bare_text = text.lstrip(pre)
732 bare_text = text.lstrip(pre)
733 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
733 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
734 if not text.startswith(pre2):
734 if not text.startswith(pre2):
735 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
735 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
736 return [cast_unicode_py2(c) for c in comp]
736 return [cast_unicode_py2(c) for c in comp]
737
737
738
738
739 def python_matches(self, text):
739 def python_matches(self, text):
740 """Match attributes or global python names"""
740 """Match attributes or global python names"""
741 if "." in text:
741 if "." in text:
742 try:
742 try:
743 matches = self.attr_matches(text)
743 matches = self.attr_matches(text)
744 if text.endswith('.') and self.omit__names:
744 if text.endswith('.') and self.omit__names:
745 if self.omit__names == 1:
745 if self.omit__names == 1:
746 # true if txt is _not_ a __ name, false otherwise:
746 # true if txt is _not_ a __ name, false otherwise:
747 no__name = (lambda txt:
747 no__name = (lambda txt:
748 re.match(r'.*\.__.*?__',txt) is None)
748 re.match(r'.*\.__.*?__',txt) is None)
749 else:
749 else:
750 # true if txt is _not_ a _ name, false otherwise:
750 # true if txt is _not_ a _ name, false otherwise:
751 no__name = (lambda txt:
751 no__name = (lambda txt:
752 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
752 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
753 matches = filter(no__name, matches)
753 matches = filter(no__name, matches)
754 except NameError:
754 except NameError:
755 # catches <undefined attributes>.<tab>
755 # catches <undefined attributes>.<tab>
756 matches = []
756 matches = []
757 else:
757 else:
758 matches = self.global_matches(text)
758 matches = self.global_matches(text)
759 return matches
759 return matches
760
760
761 def _default_arguments_from_docstring(self, doc):
761 def _default_arguments_from_docstring(self, doc):
762 """Parse the first line of docstring for call signature.
762 """Parse the first line of docstring for call signature.
763
763
764 Docstring should be of the form 'min(iterable[, key=func])\n'.
764 Docstring should be of the form 'min(iterable[, key=func])\n'.
765 It can also parse cython docstring of the form
765 It can also parse cython docstring of the form
766 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
766 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
767 """
767 """
768 if doc is None:
768 if doc is None:
769 return []
769 return []
770
770
771 #care only the firstline
771 #care only the firstline
772 line = doc.lstrip().splitlines()[0]
772 line = doc.lstrip().splitlines()[0]
773
773
774 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
774 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
775 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
775 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
776 sig = self.docstring_sig_re.search(line)
776 sig = self.docstring_sig_re.search(line)
777 if sig is None:
777 if sig is None:
778 return []
778 return []
779 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
779 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
780 sig = sig.groups()[0].split(',')
780 sig = sig.groups()[0].split(',')
781 ret = []
781 ret = []
782 for s in sig:
782 for s in sig:
783 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
783 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
784 ret += self.docstring_kwd_re.findall(s)
784 ret += self.docstring_kwd_re.findall(s)
785 return ret
785 return ret
786
786
787 def _default_arguments(self, obj):
787 def _default_arguments(self, obj):
788 """Return the list of default arguments of obj if it is callable,
788 """Return the list of default arguments of obj if it is callable,
789 or empty list otherwise."""
789 or empty list otherwise."""
790 call_obj = obj
790 call_obj = obj
791 ret = []
791 ret = []
792 if inspect.isbuiltin(obj):
792 if inspect.isbuiltin(obj):
793 pass
793 pass
794 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
794 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
795 if inspect.isclass(obj):
795 if inspect.isclass(obj):
796 #for cython embededsignature=True the constructor docstring
796 #for cython embededsignature=True the constructor docstring
797 #belongs to the object itself not __init__
797 #belongs to the object itself not __init__
798 ret += self._default_arguments_from_docstring(
798 ret += self._default_arguments_from_docstring(
799 getattr(obj, '__doc__', ''))
799 getattr(obj, '__doc__', ''))
800 # for classes, check for __init__,__new__
800 # for classes, check for __init__,__new__
801 call_obj = (getattr(obj, '__init__', None) or
801 call_obj = (getattr(obj, '__init__', None) or
802 getattr(obj, '__new__', None))
802 getattr(obj, '__new__', None))
803 # for all others, check if they are __call__able
803 # for all others, check if they are __call__able
804 elif hasattr(obj, '__call__'):
804 elif hasattr(obj, '__call__'):
805 call_obj = obj.__call__
805 call_obj = obj.__call__
806 ret += self._default_arguments_from_docstring(
806 ret += self._default_arguments_from_docstring(
807 getattr(call_obj, '__doc__', ''))
807 getattr(call_obj, '__doc__', ''))
808
808
809 if PY3:
809 if PY3:
810 _keeps = (inspect.Parameter.KEYWORD_ONLY,
810 _keeps = (inspect.Parameter.KEYWORD_ONLY,
811 inspect.Parameter.POSITIONAL_OR_KEYWORD)
811 inspect.Parameter.POSITIONAL_OR_KEYWORD)
812 signature = inspect.signature
812 signature = inspect.signature
813 else:
813 else:
814 import IPython.utils.signatures
814 import IPython.utils.signatures
815 _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY,
815 _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY,
816 IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD)
816 IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD)
817 signature = IPython.utils.signatures.signature
817 signature = IPython.utils.signatures.signature
818
818
819 try:
819 try:
820 sig = signature(call_obj)
820 sig = signature(call_obj)
821 ret.extend(k for k, v in sig.parameters.items() if
821 ret.extend(k for k, v in sig.parameters.items() if
822 v.kind in _keeps)
822 v.kind in _keeps)
823 except ValueError:
823 except ValueError:
824 pass
824 pass
825
825
826 return list(set(ret))
826 return list(set(ret))
827
827
828 def python_func_kw_matches(self,text):
828 def python_func_kw_matches(self,text):
829 """Match named parameters (kwargs) of the last open function"""
829 """Match named parameters (kwargs) of the last open function"""
830
830
831 if "." in text: # a parameter cannot be dotted
831 if "." in text: # a parameter cannot be dotted
832 return []
832 return []
833 try: regexp = self.__funcParamsRegex
833 try: regexp = self.__funcParamsRegex
834 except AttributeError:
834 except AttributeError:
835 regexp = self.__funcParamsRegex = re.compile(r'''
835 regexp = self.__funcParamsRegex = re.compile(r'''
836 '.*?(?<!\\)' | # single quoted strings or
836 '.*?(?<!\\)' | # single quoted strings or
837 ".*?(?<!\\)" | # double quoted strings or
837 ".*?(?<!\\)" | # double quoted strings or
838 \w+ | # identifier
838 \w+ | # identifier
839 \S # other characters
839 \S # other characters
840 ''', re.VERBOSE | re.DOTALL)
840 ''', re.VERBOSE | re.DOTALL)
841 # 1. find the nearest identifier that comes before an unclosed
841 # 1. find the nearest identifier that comes before an unclosed
842 # parenthesis before the cursor
842 # parenthesis before the cursor
843 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
843 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
844 tokens = regexp.findall(self.text_until_cursor)
844 tokens = regexp.findall(self.text_until_cursor)
845 tokens.reverse()
845 tokens.reverse()
846 iterTokens = iter(tokens); openPar = 0
846 iterTokens = iter(tokens); openPar = 0
847
847
848 for token in iterTokens:
848 for token in iterTokens:
849 if token == ')':
849 if token == ')':
850 openPar -= 1
850 openPar -= 1
851 elif token == '(':
851 elif token == '(':
852 openPar += 1
852 openPar += 1
853 if openPar > 0:
853 if openPar > 0:
854 # found the last unclosed parenthesis
854 # found the last unclosed parenthesis
855 break
855 break
856 else:
856 else:
857 return []
857 return []
858 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
858 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
859 ids = []
859 ids = []
860 isId = re.compile(r'\w+$').match
860 isId = re.compile(r'\w+$').match
861
861
862 while True:
862 while True:
863 try:
863 try:
864 ids.append(next(iterTokens))
864 ids.append(next(iterTokens))
865 if not isId(ids[-1]):
865 if not isId(ids[-1]):
866 ids.pop(); break
866 ids.pop(); break
867 if not next(iterTokens) == '.':
867 if not next(iterTokens) == '.':
868 break
868 break
869 except StopIteration:
869 except StopIteration:
870 break
870 break
871 # lookup the candidate callable matches either using global_matches
871 # lookup the candidate callable matches either using global_matches
872 # or attr_matches for dotted names
872 # or attr_matches for dotted names
873 if len(ids) == 1:
873 if len(ids) == 1:
874 callableMatches = self.global_matches(ids[0])
874 callableMatches = self.global_matches(ids[0])
875 else:
875 else:
876 callableMatches = self.attr_matches('.'.join(ids[::-1]))
876 callableMatches = self.attr_matches('.'.join(ids[::-1]))
877 argMatches = []
877 argMatches = []
878 for callableMatch in callableMatches:
878 for callableMatch in callableMatches:
879 try:
879 try:
880 namedArgs = self._default_arguments(eval(callableMatch,
880 namedArgs = self._default_arguments(eval(callableMatch,
881 self.namespace))
881 self.namespace))
882 except:
882 except:
883 continue
883 continue
884
884
885 for namedArg in namedArgs:
885 for namedArg in namedArgs:
886 if namedArg.startswith(text):
886 if namedArg.startswith(text):
887 argMatches.append(u"%s=" %namedArg)
887 argMatches.append(u"%s=" %namedArg)
888 return argMatches
888 return argMatches
889
889
890 def dict_key_matches(self, text):
890 def dict_key_matches(self, text):
891 "Match string keys in a dictionary, after e.g. 'foo[' "
891 "Match string keys in a dictionary, after e.g. 'foo[' "
892 def get_keys(obj):
892 def get_keys(obj):
893 # Objects can define their own completions by defining an
893 # Objects can define their own completions by defining an
894 # _ipy_key_completions_() method.
894 # _ipy_key_completions_() method.
895 method = get_real_method(obj, '_ipython_key_completions_')
895 method = get_real_method(obj, '_ipython_key_completions_')
896 if method is not None:
896 if method is not None:
897 return method()
897 return method()
898
898
899 # Special case some common in-memory dict-like types
899 # Special case some common in-memory dict-like types
900 if isinstance(obj, dict) or\
900 if isinstance(obj, dict) or\
901 _safe_isinstance(obj, 'pandas', 'DataFrame'):
901 _safe_isinstance(obj, 'pandas', 'DataFrame'):
902 try:
902 try:
903 return list(obj.keys())
903 return list(obj.keys())
904 except Exception:
904 except Exception:
905 return []
905 return []
906 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
906 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
907 _safe_isinstance(obj, 'numpy', 'void'):
907 _safe_isinstance(obj, 'numpy', 'void'):
908 return obj.dtype.names or []
908 return obj.dtype.names or []
909 return []
909 return []
910
910
911 try:
911 try:
912 regexps = self.__dict_key_regexps
912 regexps = self.__dict_key_regexps
913 except AttributeError:
913 except AttributeError:
914 dict_key_re_fmt = r'''(?x)
914 dict_key_re_fmt = r'''(?x)
915 ( # match dict-referring expression wrt greedy setting
915 ( # match dict-referring expression wrt greedy setting
916 %s
916 %s
917 )
917 )
918 \[ # open bracket
918 \[ # open bracket
919 \s* # and optional whitespace
919 \s* # and optional whitespace
920 ([uUbB]? # string prefix (r not handled)
920 ([uUbB]? # string prefix (r not handled)
921 (?: # unclosed string
921 (?: # unclosed string
922 '(?:[^']|(?<!\\)\\')*
922 '(?:[^']|(?<!\\)\\')*
923 |
923 |
924 "(?:[^"]|(?<!\\)\\")*
924 "(?:[^"]|(?<!\\)\\")*
925 )
925 )
926 )?
926 )?
927 $
927 $
928 '''
928 '''
929 regexps = self.__dict_key_regexps = {
929 regexps = self.__dict_key_regexps = {
930 False: re.compile(dict_key_re_fmt % '''
930 False: re.compile(dict_key_re_fmt % '''
931 # identifiers separated by .
931 # identifiers separated by .
932 (?!\d)\w+
932 (?!\d)\w+
933 (?:\.(?!\d)\w+)*
933 (?:\.(?!\d)\w+)*
934 '''),
934 '''),
935 True: re.compile(dict_key_re_fmt % '''
935 True: re.compile(dict_key_re_fmt % '''
936 .+
936 .+
937 ''')
937 ''')
938 }
938 }
939
939
940 match = regexps[self.greedy].search(self.text_until_cursor)
940 match = regexps[self.greedy].search(self.text_until_cursor)
941 if match is None:
941 if match is None:
942 return []
942 return []
943
943
944 expr, prefix = match.groups()
944 expr, prefix = match.groups()
945 try:
945 try:
946 obj = eval(expr, self.namespace)
946 obj = eval(expr, self.namespace)
947 except Exception:
947 except Exception:
948 try:
948 try:
949 obj = eval(expr, self.global_namespace)
949 obj = eval(expr, self.global_namespace)
950 except Exception:
950 except Exception:
951 return []
951 return []
952
952
953 keys = get_keys(obj)
953 keys = get_keys(obj)
954 if not keys:
954 if not keys:
955 return keys
955 return keys
956 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
956 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
957 if not matches:
957 if not matches:
958 return matches
958 return matches
959
959
960 # get the cursor position of
960 # get the cursor position of
961 # - the text being completed
961 # - the text being completed
962 # - the start of the key text
962 # - the start of the key text
963 # - the start of the completion
963 # - the start of the completion
964 text_start = len(self.text_until_cursor) - len(text)
964 text_start = len(self.text_until_cursor) - len(text)
965 if prefix:
965 if prefix:
966 key_start = match.start(2)
966 key_start = match.start(2)
967 completion_start = key_start + token_offset
967 completion_start = key_start + token_offset
968 else:
968 else:
969 key_start = completion_start = match.end()
969 key_start = completion_start = match.end()
970
970
971 # grab the leading prefix, to make sure all completions start with `text`
971 # grab the leading prefix, to make sure all completions start with `text`
972 if text_start > key_start:
972 if text_start > key_start:
973 leading = ''
973 leading = ''
974 else:
974 else:
975 leading = text[text_start:completion_start]
975 leading = text[text_start:completion_start]
976
976
977 # the index of the `[` character
977 # the index of the `[` character
978 bracket_idx = match.end(1)
978 bracket_idx = match.end(1)
979
979
980 # append closing quote and bracket as appropriate
980 # append closing quote and bracket as appropriate
981 # this is *not* appropriate if the opening quote or bracket is outside
981 # this is *not* appropriate if the opening quote or bracket is outside
982 # the text given to this method
982 # the text given to this method
983 suf = ''
983 suf = ''
984 continuation = self.line_buffer[len(self.text_until_cursor):]
984 continuation = self.line_buffer[len(self.text_until_cursor):]
985 if key_start > text_start and closing_quote:
985 if key_start > text_start and closing_quote:
986 # quotes were opened inside text, maybe close them
986 # quotes were opened inside text, maybe close them
987 if continuation.startswith(closing_quote):
987 if continuation.startswith(closing_quote):
988 continuation = continuation[len(closing_quote):]
988 continuation = continuation[len(closing_quote):]
989 else:
989 else:
990 suf += closing_quote
990 suf += closing_quote
991 if bracket_idx > text_start:
991 if bracket_idx > text_start:
992 # brackets were opened inside text, maybe close them
992 # brackets were opened inside text, maybe close them
993 if not continuation.startswith(']'):
993 if not continuation.startswith(']'):
994 suf += ']'
994 suf += ']'
995
995
996 return [leading + k + suf for k in matches]
996 return [leading + k + suf for k in matches]
997
997
998 def unicode_name_matches(self, text):
998 def unicode_name_matches(self, text):
999 u"""Match Latex-like syntax for unicode characters base
999 u"""Match Latex-like syntax for unicode characters base
1000 on the name of the character.
1000 on the name of the character.
1001
1001
1002 This does \\GREEK SMALL LETTER ETA -> Ξ·
1002 This does \\GREEK SMALL LETTER ETA -> Ξ·
1003
1003
1004 Works only on valid python 3 identifier, or on combining characters that
1004 Works only on valid python 3 identifier, or on combining characters that
1005 will combine to form a valid identifier.
1005 will combine to form a valid identifier.
1006
1006
1007 Used on Python 3 only.
1007 Used on Python 3 only.
1008 """
1008 """
1009 slashpos = text.rfind('\\')
1009 slashpos = text.rfind('\\')
1010 if slashpos > -1:
1010 if slashpos > -1:
1011 s = text[slashpos+1:]
1011 s = text[slashpos+1:]
1012 try :
1012 try :
1013 unic = unicodedata.lookup(s)
1013 unic = unicodedata.lookup(s)
1014 # allow combining chars
1014 # allow combining chars
1015 if ('a'+unic).isidentifier():
1015 if ('a'+unic).isidentifier():
1016 return '\\'+s,[unic]
1016 return '\\'+s,[unic]
1017 except KeyError:
1017 except KeyError:
1018 pass
1018 pass
1019 return u'', []
1019 return u'', []
1020
1020
1021
1021
1022
1022
1023
1023
1024 def latex_matches(self, text):
1024 def latex_matches(self, text):
1025 u"""Match Latex syntax for unicode characters.
1025 u"""Match Latex syntax for unicode characters.
1026
1026
1027 This does both \\alp -> \\alpha and \\alpha -> Ξ±
1027 This does both \\alp -> \\alpha and \\alpha -> Ξ±
1028
1028
1029 Used on Python 3 only.
1029 Used on Python 3 only.
1030 """
1030 """
1031 slashpos = text.rfind('\\')
1031 slashpos = text.rfind('\\')
1032 if slashpos > -1:
1032 if slashpos > -1:
1033 s = text[slashpos:]
1033 s = text[slashpos:]
1034 if s in latex_symbols:
1034 if s in latex_symbols:
1035 # Try to complete a full latex symbol to unicode
1035 # Try to complete a full latex symbol to unicode
1036 # \\alpha -> Ξ±
1036 # \\alpha -> Ξ±
1037 return s, [latex_symbols[s]]
1037 return s, [latex_symbols[s]]
1038 else:
1038 else:
1039 # If a user has partially typed a latex symbol, give them
1039 # If a user has partially typed a latex symbol, give them
1040 # a full list of options \al -> [\aleph, \alpha]
1040 # a full list of options \al -> [\aleph, \alpha]
1041 matches = [k for k in latex_symbols if k.startswith(s)]
1041 matches = [k for k in latex_symbols if k.startswith(s)]
1042 return s, matches
1042 return s, matches
1043 return u'', []
1043 return u'', []
1044
1044
1045 def dispatch_custom_completer(self, text):
1045 def dispatch_custom_completer(self, text):
1046 if not self.custom_completers:
1046 if not self.custom_completers:
1047 return
1047 return
1048
1048
1049 line = self.line_buffer
1049 line = self.line_buffer
1050 if not line.strip():
1050 if not line.strip():
1051 return None
1051 return None
1052
1052
1053 # Create a little structure to pass all the relevant information about
1053 # Create a little structure to pass all the relevant information about
1054 # the current completion to any custom completer.
1054 # the current completion to any custom completer.
1055 event = Bunch()
1055 event = Bunch()
1056 event.line = line
1056 event.line = line
1057 event.symbol = text
1057 event.symbol = text
1058 cmd = line.split(None,1)[0]
1058 cmd = line.split(None,1)[0]
1059 event.command = cmd
1059 event.command = cmd
1060 event.text_until_cursor = self.text_until_cursor
1060 event.text_until_cursor = self.text_until_cursor
1061
1061
1062 # for foo etc, try also to find completer for %foo
1062 # for foo etc, try also to find completer for %foo
1063 if not cmd.startswith(self.magic_escape):
1063 if not cmd.startswith(self.magic_escape):
1064 try_magic = self.custom_completers.s_matches(
1064 try_magic = self.custom_completers.s_matches(
1065 self.magic_escape + cmd)
1065 self.magic_escape + cmd)
1066 else:
1066 else:
1067 try_magic = []
1067 try_magic = []
1068
1068
1069 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1069 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1070 try_magic,
1070 try_magic,
1071 self.custom_completers.flat_matches(self.text_until_cursor)):
1071 self.custom_completers.flat_matches(self.text_until_cursor)):
1072 try:
1072 try:
1073 res = c(event)
1073 res = c(event)
1074 if res:
1074 if res:
1075 # first, try case sensitive match
1075 # first, try case sensitive match
1076 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1076 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1077 if withcase:
1077 if withcase:
1078 return withcase
1078 return withcase
1079 # if none, then case insensitive ones are ok too
1079 # if none, then case insensitive ones are ok too
1080 text_low = text.lower()
1080 text_low = text.lower()
1081 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1081 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1082 except TryNext:
1082 except TryNext:
1083 pass
1083 pass
1084
1084
1085 return None
1085 return None
1086
1086
1087 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1087 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1088 """Find completions for the given text and line context.
1088 """Find completions for the given text and line context.
1089
1089
1090 Note that both the text and the line_buffer are optional, but at least
1090 Note that both the text and the line_buffer are optional, but at least
1091 one of them must be given.
1091 one of them must be given.
1092
1092
1093 Parameters
1093 Parameters
1094 ----------
1094 ----------
1095 text : string, optional
1095 text : string, optional
1096 Text to perform the completion on. If not given, the line buffer
1096 Text to perform the completion on. If not given, the line buffer
1097 is split using the instance's CompletionSplitter object.
1097 is split using the instance's CompletionSplitter object.
1098
1098
1099 line_buffer : string, optional
1099 line_buffer : string, optional
1100 If not given, the completer attempts to obtain the current line
1100 If not given, the completer attempts to obtain the current line
1101 buffer via readline. This keyword allows clients which are
1101 buffer via readline. This keyword allows clients which are
1102 requesting for text completions in non-readline contexts to inform
1102 requesting for text completions in non-readline contexts to inform
1103 the completer of the entire text.
1103 the completer of the entire text.
1104
1104
1105 cursor_pos : int, optional
1105 cursor_pos : int, optional
1106 Index of the cursor in the full line buffer. Should be provided by
1106 Index of the cursor in the full line buffer. Should be provided by
1107 remote frontends where kernel has no access to frontend state.
1107 remote frontends where kernel has no access to frontend state.
1108
1108
1109 Returns
1109 Returns
1110 -------
1110 -------
1111 text : str
1111 text : str
1112 Text that was actually used in the completion.
1112 Text that was actually used in the completion.
1113
1113
1114 matches : list
1114 matches : list
1115 A list of completion matches.
1115 A list of completion matches.
1116 """
1116 """
1117 # if the cursor position isn't given, the only sane assumption we can
1117 # if the cursor position isn't given, the only sane assumption we can
1118 # make is that it's at the end of the line (the common case)
1118 # make is that it's at the end of the line (the common case)
1119 if cursor_pos is None:
1119 if cursor_pos is None:
1120 cursor_pos = len(line_buffer) if text is None else len(text)
1120 cursor_pos = len(line_buffer) if text is None else len(text)
1121
1121
1122 if PY3:
1122 if PY3:
1123
1123
1124 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1124 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1125 latex_text, latex_matches = self.latex_matches(base_text)
1125 latex_text, latex_matches = self.latex_matches(base_text)
1126 if latex_matches:
1126 if latex_matches:
1127 return latex_text, latex_matches
1127 return latex_text, latex_matches
1128 name_text = ''
1128 name_text = ''
1129 name_matches = []
1129 name_matches = []
1130 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1130 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1131 name_text, name_matches = meth(base_text)
1131 name_text, name_matches = meth(base_text)
1132 if name_text:
1132 if name_text:
1133 return name_text, name_matches
1133 return name_text, name_matches
1134
1134
1135 # if text is either None or an empty string, rely on the line buffer
1135 # if text is either None or an empty string, rely on the line buffer
1136 if not text:
1136 if not text:
1137 text = self.splitter.split_line(line_buffer, cursor_pos)
1137 text = self.splitter.split_line(line_buffer, cursor_pos)
1138
1138
1139 # If no line buffer is given, assume the input text is all there was
1139 # If no line buffer is given, assume the input text is all there was
1140 if line_buffer is None:
1140 if line_buffer is None:
1141 line_buffer = text
1141 line_buffer = text
1142
1142
1143 self.line_buffer = line_buffer
1143 self.line_buffer = line_buffer
1144 self.text_until_cursor = self.line_buffer[:cursor_pos]
1144 self.text_until_cursor = self.line_buffer[:cursor_pos]
1145
1145
1146 # Start with a clean slate of completions
1146 # Start with a clean slate of completions
1147 self.matches[:] = []
1147 self.matches[:] = []
1148 custom_res = self.dispatch_custom_completer(text)
1148 custom_res = self.dispatch_custom_completer(text)
1149 if custom_res is not None:
1149 if custom_res is not None:
1150 # did custom completers produce something?
1150 # did custom completers produce something?
1151 self.matches = custom_res
1151 self.matches = custom_res
1152 else:
1152 else:
1153 # Extend the list of completions with the results of each
1153 # Extend the list of completions with the results of each
1154 # matcher, so we return results to the user from all
1154 # matcher, so we return results to the user from all
1155 # namespaces.
1155 # namespaces.
1156 if self.merge_completions:
1156 if self.merge_completions:
1157 self.matches = []
1157 self.matches = []
1158 for matcher in self.matchers:
1158 for matcher in self.matchers:
1159 try:
1159 try:
1160 self.matches.extend(matcher(text))
1160 self.matches.extend(matcher(text))
1161 except:
1161 except:
1162 # Show the ugly traceback if the matcher causes an
1162 # Show the ugly traceback if the matcher causes an
1163 # exception, but do NOT crash the kernel!
1163 # exception, but do NOT crash the kernel!
1164 sys.excepthook(*sys.exc_info())
1164 sys.excepthook(*sys.exc_info())
1165 else:
1165 else:
1166 for matcher in self.matchers:
1166 for matcher in self.matchers:
1167 self.matches = matcher(text)
1167 self.matches = matcher(text)
1168 if self.matches:
1168 if self.matches:
1169 break
1169 break
1170 # FIXME: we should extend our api to return a dict with completions for
1170 # FIXME: we should extend our api to return a dict with completions for
1171 # different types of objects. The rlcomplete() method could then
1171 # different types of objects. The rlcomplete() method could then
1172 # simply collapse the dict into a list for readline, but we'd have
1172 # simply collapse the dict into a list for readline, but we'd have
1173 # richer completion semantics in other evironments.
1173 # richer completion semantics in other evironments.
1174 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1174 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1175
1175
1176 return text, self.matches
1176 return text, self.matches
@@ -1,73 +1,74 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Miscellaneous context managers.
2 """Miscellaneous context managers.
3 """
3 """
4
4
5 import warnings
5 import warnings
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 class preserve_keys(object):
10 class preserve_keys(object):
11 """Preserve a set of keys in a dictionary.
11 """Preserve a set of keys in a dictionary.
12
12
13 Upon entering the context manager the current values of the keys
13 Upon entering the context manager the current values of the keys
14 will be saved. Upon exiting, the dictionary will be updated to
14 will be saved. Upon exiting, the dictionary will be updated to
15 restore the original value of the preserved keys. Preserved keys
15 restore the original value of the preserved keys. Preserved keys
16 which did not exist when entering the context manager will be
16 which did not exist when entering the context manager will be
17 deleted.
17 deleted.
18
18
19 Examples
19 Examples
20 --------
20 --------
21
21
22 >>> d = {'a': 1, 'b': 2, 'c': 3}
22 >>> d = {'a': 1, 'b': 2, 'c': 3}
23 >>> with preserve_keys(d, 'b', 'c', 'd'):
23 >>> with preserve_keys(d, 'b', 'c', 'd'):
24 ... del d['a']
24 ... del d['a']
25 ... del d['b'] # will be reset to 2
25 ... del d['b'] # will be reset to 2
26 ... d['c'] = None # will be reset to 3
26 ... d['c'] = None # will be reset to 3
27 ... d['d'] = 4 # will be deleted
27 ... d['d'] = 4 # will be deleted
28 ... d['e'] = 5
28 ... d['e'] = 5
29 ... print(sorted(d.items()))
29 ... print(sorted(d.items()))
30 ...
30 ...
31 [('c', None), ('d', 4), ('e', 5)]
31 [('c', None), ('d', 4), ('e', 5)]
32 >>> print(sorted(d.items()))
32 >>> print(sorted(d.items()))
33 [('b', 2), ('c', 3), ('e', 5)]
33 [('b', 2), ('c', 3), ('e', 5)]
34 """
34 """
35
35
36 def __init__(self, dictionary, *keys):
36 def __init__(self, dictionary, *keys):
37 self.dictionary = dictionary
37 self.dictionary = dictionary
38 self.keys = keys
38 self.keys = keys
39
39
40 def __enter__(self):
40 def __enter__(self):
41 # Actions to perform upon exiting.
41 # Actions to perform upon exiting.
42 to_delete = []
42 to_delete = []
43 to_update = {}
43 to_update = {}
44
44
45 d = self.dictionary
45 d = self.dictionary
46 for k in self.keys:
46 for k in self.keys:
47 if k in d:
47 if k in d:
48 to_update[k] = d[k]
48 to_update[k] = d[k]
49 else:
49 else:
50 to_delete.append(k)
50 to_delete.append(k)
51
51
52 self.to_delete = to_delete
52 self.to_delete = to_delete
53 self.to_update = to_update
53 self.to_update = to_update
54
54
55 def __exit__(self, *exc_info):
55 def __exit__(self, *exc_info):
56 d = self.dictionary
56 d = self.dictionary
57
57
58 for k in self.to_delete:
58 for k in self.to_delete:
59 d.pop(k, None)
59 d.pop(k, None)
60 d.update(self.to_update)
60 d.update(self.to_update)
61
61
62
62
63 class NoOpContext(object):
63 class NoOpContext(object):
64 """
64 """
65 Deprecated
65 Deprecated
66
66
67 Context manager that does nothing."""
67 Context manager that does nothing."""
68
68
69 def __init__(self):
69 def __init__(self):
70 warnings.warn("""NoOpContext is deprecated since IPython 5.0 """)
70 warnings.warn("""NoOpContext is deprecated since IPython 5.0 """,
71 DeprecationWarning, stacklevel=2)
71
72
72 def __enter__(self): pass
73 def __enter__(self): pass
73 def __exit__(self, type, value, traceback): pass
74 def __exit__(self, type, value, traceback): pass
General Comments 0
You need to be logged in to leave comments. Login now