##// END OF EJS Templates
deprecate IPython.utils.signatures...
Min RK -
Show More
@@ -1,1236 +1,1229 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Word completion for IPython.
2 """Word completion for IPython.
3
3
4 This module started 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
9
10 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12 #
12 #
13 # Some of this code originated from rlcompleter in the Python standard library
13 # Some of this code originated from rlcompleter in the Python standard library
14 # Copyright (C) 2001 Python Software Foundation, www.python.org
14 # Copyright (C) 2001 Python Software Foundation, www.python.org
15
15
16
16
17 import __main__
17 import __main__
18 import glob
18 import glob
19 import inspect
19 import inspect
20 import itertools
20 import itertools
21 import keyword
21 import keyword
22 import os
22 import os
23 import re
23 import re
24 import sys
24 import sys
25 import unicodedata
25 import unicodedata
26 import string
26 import string
27 import warnings
27 import warnings
28 from importlib import import_module
28 from importlib import import_module
29
29
30 from traitlets.config.configurable import Configurable
30 from traitlets.config.configurable import Configurable
31 from IPython.core.error import TryNext
31 from IPython.core.error import TryNext
32 from IPython.core.inputsplitter import ESC_MAGIC
32 from IPython.core.inputsplitter import ESC_MAGIC
33 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
33 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
34 from IPython.utils import generics
34 from IPython.utils import generics
35 from IPython.utils.decorators import undoc
35 from IPython.utils.decorators import undoc
36 from IPython.utils.dir2 import dir2, get_real_method
36 from IPython.utils.dir2 import dir2, get_real_method
37 from IPython.utils.process import arg_split
37 from IPython.utils.process import arg_split
38 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
38 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
39 from traitlets import Bool, Enum, observe
39 from traitlets import Bool, Enum, observe
40
40
41 from functools import wraps
41 from functools import wraps
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 # Work around BUG decorators.
57 # Work around BUG decorators.
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 def _strip_single_trailing_space(complete):
60 def _strip_single_trailing_space(complete):
61 """
61 """
62 This is a workaround for a weird IPython/Prompt_toolkit behavior,
62 This is a workaround for a weird IPython/Prompt_toolkit behavior,
63 that can be removed once we rely on a slightly more recent prompt_toolkit
63 that can be removed once we rely on a slightly more recent prompt_toolkit
64 version (likely > 1.0.3). So this can likely be removed in IPython 6.0
64 version (likely > 1.0.3). So this can likely be removed in IPython 6.0
65
65
66 cf https://github.com/ipython/ipython/issues/9658
66 cf https://github.com/ipython/ipython/issues/9658
67 and https://github.com/jonathanslenders/python-prompt-toolkit/pull/328
67 and https://github.com/jonathanslenders/python-prompt-toolkit/pull/328
68
68
69 The bug is due to the fact that in PTK the completer will reinvoke itself
69 The bug is due to the fact that in PTK the completer will reinvoke itself
70 after trying to completer to the longuest common prefix of all the
70 after trying to completer to the longuest common prefix of all the
71 completions, unless only one completion is available.
71 completions, unless only one completion is available.
72
72
73 This logic is faulty if the completion ends with space, which can happen in
73 This logic is faulty if the completion ends with space, which can happen in
74 case like::
74 case like::
75
75
76 from foo import im<ta>
76 from foo import im<ta>
77
77
78 which only matching completion is `import `. Note the leading space at the
78 which only matching completion is `import `. Note the leading space at the
79 end. So leaving a space at the end is a reasonable request, but for now
79 end. So leaving a space at the end is a reasonable request, but for now
80 we'll strip it.
80 we'll strip it.
81 """
81 """
82
82
83 @wraps(complete)
83 @wraps(complete)
84 def comp(*args, **kwargs):
84 def comp(*args, **kwargs):
85 text, matches = complete(*args, **kwargs)
85 text, matches = complete(*args, **kwargs)
86 if len(matches) == 1:
86 if len(matches) == 1:
87 return text, [matches[0].rstrip()]
87 return text, [matches[0].rstrip()]
88 return text, matches
88 return text, matches
89
89
90 return comp
90 return comp
91
91
92
92
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Main functions and classes
95 # Main functions and classes
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98 def has_open_quotes(s):
98 def has_open_quotes(s):
99 """Return whether a string has open quotes.
99 """Return whether a string has open quotes.
100
100
101 This simply counts whether the number of quote characters of either type in
101 This simply counts whether the number of quote characters of either type in
102 the string is odd.
102 the string is odd.
103
103
104 Returns
104 Returns
105 -------
105 -------
106 If there is an open quote, the quote character is returned. Else, return
106 If there is an open quote, the quote character is returned. Else, return
107 False.
107 False.
108 """
108 """
109 # We check " first, then ', so complex cases with nested quotes will get
109 # We check " first, then ', so complex cases with nested quotes will get
110 # the " to take precedence.
110 # the " to take precedence.
111 if s.count('"') % 2:
111 if s.count('"') % 2:
112 return '"'
112 return '"'
113 elif s.count("'") % 2:
113 elif s.count("'") % 2:
114 return "'"
114 return "'"
115 else:
115 else:
116 return False
116 return False
117
117
118
118
119 def protect_filename(s):
119 def protect_filename(s):
120 """Escape a string to protect certain characters."""
120 """Escape a string to protect certain characters."""
121 if set(s) & set(PROTECTABLES):
121 if set(s) & set(PROTECTABLES):
122 if sys.platform == "win32":
122 if sys.platform == "win32":
123 return '"' + s + '"'
123 return '"' + s + '"'
124 else:
124 else:
125 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
125 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
126 else:
126 else:
127 return s
127 return s
128
128
129
129
130 def expand_user(path):
130 def expand_user(path):
131 """Expand '~'-style usernames in strings.
131 """Expand '~'-style usernames in strings.
132
132
133 This is similar to :func:`os.path.expanduser`, but it computes and returns
133 This is similar to :func:`os.path.expanduser`, but it computes and returns
134 extra information that will be useful if the input was being used in
134 extra information that will be useful if the input was being used in
135 computing completions, and you wish to return the completions with the
135 computing completions, and you wish to return the completions with the
136 original '~' instead of its expanded value.
136 original '~' instead of its expanded value.
137
137
138 Parameters
138 Parameters
139 ----------
139 ----------
140 path : str
140 path : str
141 String to be expanded. If no ~ is present, the output is the same as the
141 String to be expanded. If no ~ is present, the output is the same as the
142 input.
142 input.
143
143
144 Returns
144 Returns
145 -------
145 -------
146 newpath : str
146 newpath : str
147 Result of ~ expansion in the input path.
147 Result of ~ expansion in the input path.
148 tilde_expand : bool
148 tilde_expand : bool
149 Whether any expansion was performed or not.
149 Whether any expansion was performed or not.
150 tilde_val : str
150 tilde_val : str
151 The value that ~ was replaced with.
151 The value that ~ was replaced with.
152 """
152 """
153 # Default values
153 # Default values
154 tilde_expand = False
154 tilde_expand = False
155 tilde_val = ''
155 tilde_val = ''
156 newpath = path
156 newpath = path
157
157
158 if path.startswith('~'):
158 if path.startswith('~'):
159 tilde_expand = True
159 tilde_expand = True
160 rest = len(path)-1
160 rest = len(path)-1
161 newpath = os.path.expanduser(path)
161 newpath = os.path.expanduser(path)
162 if rest:
162 if rest:
163 tilde_val = newpath[:-rest]
163 tilde_val = newpath[:-rest]
164 else:
164 else:
165 tilde_val = newpath
165 tilde_val = newpath
166
166
167 return newpath, tilde_expand, tilde_val
167 return newpath, tilde_expand, tilde_val
168
168
169
169
170 def compress_user(path, tilde_expand, tilde_val):
170 def compress_user(path, tilde_expand, tilde_val):
171 """Does the opposite of expand_user, with its outputs.
171 """Does the opposite of expand_user, with its outputs.
172 """
172 """
173 if tilde_expand:
173 if tilde_expand:
174 return path.replace(tilde_val, '~')
174 return path.replace(tilde_val, '~')
175 else:
175 else:
176 return path
176 return path
177
177
178
178
179 def completions_sorting_key(word):
179 def completions_sorting_key(word):
180 """key for sorting completions
180 """key for sorting completions
181
181
182 This does several things:
182 This does several things:
183
183
184 - Lowercase all completions, so they are sorted alphabetically with
184 - Lowercase all completions, so they are sorted alphabetically with
185 upper and lower case words mingled
185 upper and lower case words mingled
186 - Demote any completions starting with underscores to the end
186 - Demote any completions starting with underscores to the end
187 - Insert any %magic and %%cellmagic completions in the alphabetical order
187 - Insert any %magic and %%cellmagic completions in the alphabetical order
188 by their name
188 by their name
189 """
189 """
190 # Case insensitive sort
190 # Case insensitive sort
191 word = word.lower()
191 word = word.lower()
192
192
193 prio1, prio2 = 0, 0
193 prio1, prio2 = 0, 0
194
194
195 if word.startswith('__'):
195 if word.startswith('__'):
196 prio1 = 2
196 prio1 = 2
197 elif word.startswith('_'):
197 elif word.startswith('_'):
198 prio1 = 1
198 prio1 = 1
199
199
200 if word.endswith('='):
200 if word.endswith('='):
201 prio1 = -1
201 prio1 = -1
202
202
203 if word.startswith('%%'):
203 if word.startswith('%%'):
204 # If there's another % in there, this is something else, so leave it alone
204 # If there's another % in there, this is something else, so leave it alone
205 if not "%" in word[2:]:
205 if not "%" in word[2:]:
206 word = word[2:]
206 word = word[2:]
207 prio2 = 2
207 prio2 = 2
208 elif word.startswith('%'):
208 elif word.startswith('%'):
209 if not "%" in word[1:]:
209 if not "%" in word[1:]:
210 word = word[1:]
210 word = word[1:]
211 prio2 = 1
211 prio2 = 1
212
212
213 return prio1, word, prio2
213 return prio1, word, prio2
214
214
215
215
216 @undoc
216 @undoc
217 class Bunch(object): pass
217 class Bunch(object): pass
218
218
219
219
220 if sys.platform == 'win32':
220 if sys.platform == 'win32':
221 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
221 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
222 else:
222 else:
223 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
223 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
224
224
225 GREEDY_DELIMS = ' =\r\n'
225 GREEDY_DELIMS = ' =\r\n'
226
226
227
227
228 class CompletionSplitter(object):
228 class CompletionSplitter(object):
229 """An object to split an input line in a manner similar to readline.
229 """An object to split an input line in a manner similar to readline.
230
230
231 By having our own implementation, we can expose readline-like completion in
231 By having our own implementation, we can expose readline-like completion in
232 a uniform manner to all frontends. This object only needs to be given the
232 a uniform manner to all frontends. This object only needs to be given the
233 line of text to be split and the cursor position on said line, and it
233 line of text to be split and the cursor position on said line, and it
234 returns the 'word' to be completed on at the cursor after splitting the
234 returns the 'word' to be completed on at the cursor after splitting the
235 entire line.
235 entire line.
236
236
237 What characters are used as splitting delimiters can be controlled by
237 What characters are used as splitting delimiters can be controlled by
238 setting the `delims` attribute (this is a property that internally
238 setting the `delims` attribute (this is a property that internally
239 automatically builds the necessary regular expression)"""
239 automatically builds the necessary regular expression)"""
240
240
241 # Private interface
241 # Private interface
242
242
243 # A string of delimiter characters. The default value makes sense for
243 # A string of delimiter characters. The default value makes sense for
244 # IPython's most typical usage patterns.
244 # IPython's most typical usage patterns.
245 _delims = DELIMS
245 _delims = DELIMS
246
246
247 # The expression (a normal string) to be compiled into a regular expression
247 # The expression (a normal string) to be compiled into a regular expression
248 # for actual splitting. We store it as an attribute mostly for ease of
248 # for actual splitting. We store it as an attribute mostly for ease of
249 # debugging, since this type of code can be so tricky to debug.
249 # debugging, since this type of code can be so tricky to debug.
250 _delim_expr = None
250 _delim_expr = None
251
251
252 # The regular expression that does the actual splitting
252 # The regular expression that does the actual splitting
253 _delim_re = None
253 _delim_re = None
254
254
255 def __init__(self, delims=None):
255 def __init__(self, delims=None):
256 delims = CompletionSplitter._delims if delims is None else delims
256 delims = CompletionSplitter._delims if delims is None else delims
257 self.delims = delims
257 self.delims = delims
258
258
259 @property
259 @property
260 def delims(self):
260 def delims(self):
261 """Return the string of delimiter characters."""
261 """Return the string of delimiter characters."""
262 return self._delims
262 return self._delims
263
263
264 @delims.setter
264 @delims.setter
265 def delims(self, delims):
265 def delims(self, delims):
266 """Set the delimiters for line splitting."""
266 """Set the delimiters for line splitting."""
267 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
267 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
268 self._delim_re = re.compile(expr)
268 self._delim_re = re.compile(expr)
269 self._delims = delims
269 self._delims = delims
270 self._delim_expr = expr
270 self._delim_expr = expr
271
271
272 def split_line(self, line, cursor_pos=None):
272 def split_line(self, line, cursor_pos=None):
273 """Split a line of text with a cursor at the given position.
273 """Split a line of text with a cursor at the given position.
274 """
274 """
275 l = line if cursor_pos is None else line[:cursor_pos]
275 l = line if cursor_pos is None else line[:cursor_pos]
276 return self._delim_re.split(l)[-1]
276 return self._delim_re.split(l)[-1]
277
277
278
278
279 class Completer(Configurable):
279 class Completer(Configurable):
280
280
281 greedy = Bool(False,
281 greedy = Bool(False,
282 help="""Activate greedy completion
282 help="""Activate greedy completion
283 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
283 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
284
284
285 This will enable completion on elements of lists, results of function calls, etc.,
285 This will enable completion on elements of lists, results of function calls, etc.,
286 but can be unsafe because the code is actually evaluated on TAB.
286 but can be unsafe because the code is actually evaluated on TAB.
287 """
287 """
288 ).tag(config=True)
288 ).tag(config=True)
289
289
290
290
291 def __init__(self, namespace=None, global_namespace=None, **kwargs):
291 def __init__(self, namespace=None, global_namespace=None, **kwargs):
292 """Create a new completer for the command line.
292 """Create a new completer for the command line.
293
293
294 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
294 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
295
295
296 If unspecified, the default namespace where completions are performed
296 If unspecified, the default namespace where completions are performed
297 is __main__ (technically, __main__.__dict__). Namespaces should be
297 is __main__ (technically, __main__.__dict__). Namespaces should be
298 given as dictionaries.
298 given as dictionaries.
299
299
300 An optional second namespace can be given. This allows the completer
300 An optional second namespace can be given. This allows the completer
301 to handle cases where both the local and global scopes need to be
301 to handle cases where both the local and global scopes need to be
302 distinguished.
302 distinguished.
303
303
304 Completer instances should be used as the completion mechanism of
304 Completer instances should be used as the completion mechanism of
305 readline via the set_completer() call:
305 readline via the set_completer() call:
306
306
307 readline.set_completer(Completer(my_namespace).complete)
307 readline.set_completer(Completer(my_namespace).complete)
308 """
308 """
309
309
310 # Don't bind to namespace quite yet, but flag whether the user wants a
310 # Don't bind to namespace quite yet, but flag whether the user wants a
311 # specific namespace or to use __main__.__dict__. This will allow us
311 # specific namespace or to use __main__.__dict__. This will allow us
312 # to bind to __main__.__dict__ at completion time, not now.
312 # to bind to __main__.__dict__ at completion time, not now.
313 if namespace is None:
313 if namespace is None:
314 self.use_main_ns = 1
314 self.use_main_ns = 1
315 else:
315 else:
316 self.use_main_ns = 0
316 self.use_main_ns = 0
317 self.namespace = namespace
317 self.namespace = namespace
318
318
319 # The global namespace, if given, can be bound directly
319 # The global namespace, if given, can be bound directly
320 if global_namespace is None:
320 if global_namespace is None:
321 self.global_namespace = {}
321 self.global_namespace = {}
322 else:
322 else:
323 self.global_namespace = global_namespace
323 self.global_namespace = global_namespace
324
324
325 super(Completer, self).__init__(**kwargs)
325 super(Completer, self).__init__(**kwargs)
326
326
327 def complete(self, text, state):
327 def complete(self, text, state):
328 """Return the next possible completion for 'text'.
328 """Return the next possible completion for 'text'.
329
329
330 This is called successively with state == 0, 1, 2, ... until it
330 This is called successively with state == 0, 1, 2, ... until it
331 returns None. The completion should begin with 'text'.
331 returns None. The completion should begin with 'text'.
332
332
333 """
333 """
334 if self.use_main_ns:
334 if self.use_main_ns:
335 self.namespace = __main__.__dict__
335 self.namespace = __main__.__dict__
336
336
337 if state == 0:
337 if state == 0:
338 if "." in text:
338 if "." in text:
339 self.matches = self.attr_matches(text)
339 self.matches = self.attr_matches(text)
340 else:
340 else:
341 self.matches = self.global_matches(text)
341 self.matches = self.global_matches(text)
342 try:
342 try:
343 return self.matches[state]
343 return self.matches[state]
344 except IndexError:
344 except IndexError:
345 return None
345 return None
346
346
347 def global_matches(self, text):
347 def global_matches(self, text):
348 """Compute matches when text is a simple name.
348 """Compute matches when text is a simple name.
349
349
350 Return a list of all keywords, built-in functions and names currently
350 Return a list of all keywords, built-in functions and names currently
351 defined in self.namespace or self.global_namespace that match.
351 defined in self.namespace or self.global_namespace that match.
352
352
353 """
353 """
354 matches = []
354 matches = []
355 match_append = matches.append
355 match_append = matches.append
356 n = len(text)
356 n = len(text)
357 for lst in [keyword.kwlist,
357 for lst in [keyword.kwlist,
358 builtin_mod.__dict__.keys(),
358 builtin_mod.__dict__.keys(),
359 self.namespace.keys(),
359 self.namespace.keys(),
360 self.global_namespace.keys()]:
360 self.global_namespace.keys()]:
361 for word in lst:
361 for word in lst:
362 if word[:n] == text and word != "__builtins__":
362 if word[:n] == text and word != "__builtins__":
363 match_append(word)
363 match_append(word)
364 return [cast_unicode_py2(m) for m in matches]
364 return [cast_unicode_py2(m) for m in matches]
365
365
366 def attr_matches(self, text):
366 def attr_matches(self, text):
367 """Compute matches when text contains a dot.
367 """Compute matches when text contains a dot.
368
368
369 Assuming the text is of the form NAME.NAME....[NAME], and is
369 Assuming the text is of the form NAME.NAME....[NAME], and is
370 evaluatable in self.namespace or self.global_namespace, it will be
370 evaluatable in self.namespace or self.global_namespace, it will be
371 evaluated and its attributes (as revealed by dir()) are used as
371 evaluated and its attributes (as revealed by dir()) are used as
372 possible completions. (For class instances, class members are are
372 possible completions. (For class instances, class members are are
373 also considered.)
373 also considered.)
374
374
375 WARNING: this can still invoke arbitrary C code, if an object
375 WARNING: this can still invoke arbitrary C code, if an object
376 with a __getattr__ hook is evaluated.
376 with a __getattr__ hook is evaluated.
377
377
378 """
378 """
379
379
380 # Another option, seems to work great. Catches things like ''.<tab>
380 # Another option, seems to work great. Catches things like ''.<tab>
381 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
381 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
382
382
383 if m:
383 if m:
384 expr, attr = m.group(1, 3)
384 expr, attr = m.group(1, 3)
385 elif self.greedy:
385 elif self.greedy:
386 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
386 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
387 if not m2:
387 if not m2:
388 return []
388 return []
389 expr, attr = m2.group(1,2)
389 expr, attr = m2.group(1,2)
390 else:
390 else:
391 return []
391 return []
392
392
393 try:
393 try:
394 obj = eval(expr, self.namespace)
394 obj = eval(expr, self.namespace)
395 except:
395 except:
396 try:
396 try:
397 obj = eval(expr, self.global_namespace)
397 obj = eval(expr, self.global_namespace)
398 except:
398 except:
399 return []
399 return []
400
400
401 if self.limit_to__all__ and hasattr(obj, '__all__'):
401 if self.limit_to__all__ and hasattr(obj, '__all__'):
402 words = get__all__entries(obj)
402 words = get__all__entries(obj)
403 else:
403 else:
404 words = dir2(obj)
404 words = dir2(obj)
405
405
406 try:
406 try:
407 words = generics.complete_object(obj, words)
407 words = generics.complete_object(obj, words)
408 except TryNext:
408 except TryNext:
409 pass
409 pass
410 except Exception:
410 except Exception:
411 # Silence errors from completion function
411 # Silence errors from completion function
412 #raise # dbg
412 #raise # dbg
413 pass
413 pass
414 # Build match list to return
414 # Build match list to return
415 n = len(attr)
415 n = len(attr)
416 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
416 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
417
417
418
418
419 def get__all__entries(obj):
419 def get__all__entries(obj):
420 """returns the strings in the __all__ attribute"""
420 """returns the strings in the __all__ attribute"""
421 try:
421 try:
422 words = getattr(obj, '__all__')
422 words = getattr(obj, '__all__')
423 except:
423 except:
424 return []
424 return []
425
425
426 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
426 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
427
427
428
428
429 def match_dict_keys(keys, prefix, delims):
429 def match_dict_keys(keys, prefix, delims):
430 """Used by dict_key_matches, matching the prefix to a list of keys"""
430 """Used by dict_key_matches, matching the prefix to a list of keys"""
431 if not prefix:
431 if not prefix:
432 return None, 0, [repr(k) for k in keys
432 return None, 0, [repr(k) for k in keys
433 if isinstance(k, (string_types, bytes))]
433 if isinstance(k, (string_types, bytes))]
434 quote_match = re.search('["\']', prefix)
434 quote_match = re.search('["\']', prefix)
435 quote = quote_match.group()
435 quote = quote_match.group()
436 try:
436 try:
437 prefix_str = eval(prefix + quote, {})
437 prefix_str = eval(prefix + quote, {})
438 except Exception:
438 except Exception:
439 return None, 0, []
439 return None, 0, []
440
440
441 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
441 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
442 token_match = re.search(pattern, prefix, re.UNICODE)
442 token_match = re.search(pattern, prefix, re.UNICODE)
443 token_start = token_match.start()
443 token_start = token_match.start()
444 token_prefix = token_match.group()
444 token_prefix = token_match.group()
445
445
446 # TODO: support bytes in Py3k
446 # TODO: support bytes in Py3k
447 matched = []
447 matched = []
448 for key in keys:
448 for key in keys:
449 try:
449 try:
450 if not key.startswith(prefix_str):
450 if not key.startswith(prefix_str):
451 continue
451 continue
452 except (AttributeError, TypeError, UnicodeError):
452 except (AttributeError, TypeError, UnicodeError):
453 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
453 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
454 continue
454 continue
455
455
456 # reformat remainder of key to begin with prefix
456 # reformat remainder of key to begin with prefix
457 rem = key[len(prefix_str):]
457 rem = key[len(prefix_str):]
458 # force repr wrapped in '
458 # force repr wrapped in '
459 rem_repr = repr(rem + '"')
459 rem_repr = repr(rem + '"')
460 if rem_repr.startswith('u') and prefix[0] not in 'uU':
460 if rem_repr.startswith('u') and prefix[0] not in 'uU':
461 # Found key is unicode, but prefix is Py2 string.
461 # Found key is unicode, but prefix is Py2 string.
462 # Therefore attempt to interpret key as string.
462 # Therefore attempt to interpret key as string.
463 try:
463 try:
464 rem_repr = repr(rem.encode('ascii') + '"')
464 rem_repr = repr(rem.encode('ascii') + '"')
465 except UnicodeEncodeError:
465 except UnicodeEncodeError:
466 continue
466 continue
467
467
468 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
468 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
469 if quote == '"':
469 if quote == '"':
470 # The entered prefix is quoted with ",
470 # The entered prefix is quoted with ",
471 # but the match is quoted with '.
471 # but the match is quoted with '.
472 # A contained " hence needs escaping for comparison:
472 # A contained " hence needs escaping for comparison:
473 rem_repr = rem_repr.replace('"', '\\"')
473 rem_repr = rem_repr.replace('"', '\\"')
474
474
475 # then reinsert prefix from start of token
475 # then reinsert prefix from start of token
476 matched.append('%s%s' % (token_prefix, rem_repr))
476 matched.append('%s%s' % (token_prefix, rem_repr))
477 return quote, token_start, matched
477 return quote, token_start, matched
478
478
479
479
480 def _safe_isinstance(obj, module, class_name):
480 def _safe_isinstance(obj, module, class_name):
481 """Checks if obj is an instance of module.class_name if loaded
481 """Checks if obj is an instance of module.class_name if loaded
482 """
482 """
483 return (module in sys.modules and
483 return (module in sys.modules and
484 isinstance(obj, getattr(import_module(module), class_name)))
484 isinstance(obj, getattr(import_module(module), class_name)))
485
485
486
486
487 def back_unicode_name_matches(text):
487 def back_unicode_name_matches(text):
488 u"""Match unicode characters back to unicode name
488 u"""Match unicode characters back to unicode name
489
489
490 This does ☃ -> \\snowman
490 This does ☃ -> \\snowman
491
491
492 Note that snowman is not a valid python3 combining character but will be expanded.
492 Note that snowman is not a valid python3 combining character but will be expanded.
493 Though it will not recombine back to the snowman character by the completion machinery.
493 Though it will not recombine back to the snowman character by the completion machinery.
494
494
495 This will not either back-complete standard sequences like \\n, \\b ...
495 This will not either back-complete standard sequences like \\n, \\b ...
496
496
497 Used on Python 3 only.
497 Used on Python 3 only.
498 """
498 """
499 if len(text)<2:
499 if len(text)<2:
500 return u'', ()
500 return u'', ()
501 maybe_slash = text[-2]
501 maybe_slash = text[-2]
502 if maybe_slash != '\\':
502 if maybe_slash != '\\':
503 return u'', ()
503 return u'', ()
504
504
505 char = text[-1]
505 char = text[-1]
506 # no expand on quote for completion in strings.
506 # no expand on quote for completion in strings.
507 # nor backcomplete standard ascii keys
507 # nor backcomplete standard ascii keys
508 if char in string.ascii_letters or char in ['"',"'"]:
508 if char in string.ascii_letters or char in ['"',"'"]:
509 return u'', ()
509 return u'', ()
510 try :
510 try :
511 unic = unicodedata.name(char)
511 unic = unicodedata.name(char)
512 return '\\'+char,['\\'+unic]
512 return '\\'+char,['\\'+unic]
513 except KeyError:
513 except KeyError:
514 pass
514 pass
515 return u'', ()
515 return u'', ()
516
516
517 def back_latex_name_matches(text):
517 def back_latex_name_matches(text):
518 u"""Match latex characters back to unicode name
518 u"""Match latex characters back to unicode name
519
519
520 This does ->\\sqrt
520 This does ->\\sqrt
521
521
522 Used on Python 3 only.
522 Used on Python 3 only.
523 """
523 """
524 if len(text)<2:
524 if len(text)<2:
525 return u'', ()
525 return u'', ()
526 maybe_slash = text[-2]
526 maybe_slash = text[-2]
527 if maybe_slash != '\\':
527 if maybe_slash != '\\':
528 return u'', ()
528 return u'', ()
529
529
530
530
531 char = text[-1]
531 char = text[-1]
532 # no expand on quote for completion in strings.
532 # no expand on quote for completion in strings.
533 # nor backcomplete standard ascii keys
533 # nor backcomplete standard ascii keys
534 if char in string.ascii_letters or char in ['"',"'"]:
534 if char in string.ascii_letters or char in ['"',"'"]:
535 return u'', ()
535 return u'', ()
536 try :
536 try :
537 latex = reverse_latex_symbol[char]
537 latex = reverse_latex_symbol[char]
538 # '\\' replace the \ as well
538 # '\\' replace the \ as well
539 return '\\'+char,[latex]
539 return '\\'+char,[latex]
540 except KeyError:
540 except KeyError:
541 pass
541 pass
542 return u'', ()
542 return u'', ()
543
543
544
544
545 class IPCompleter(Completer):
545 class IPCompleter(Completer):
546 """Extension of the completer class with IPython-specific features"""
546 """Extension of the completer class with IPython-specific features"""
547
547
548 @observe('greedy')
548 @observe('greedy')
549 def _greedy_changed(self, change):
549 def _greedy_changed(self, change):
550 """update the splitter and readline delims when greedy is changed"""
550 """update the splitter and readline delims when greedy is changed"""
551 if change['new']:
551 if change['new']:
552 self.splitter.delims = GREEDY_DELIMS
552 self.splitter.delims = GREEDY_DELIMS
553 else:
553 else:
554 self.splitter.delims = DELIMS
554 self.splitter.delims = DELIMS
555
555
556 merge_completions = Bool(True,
556 merge_completions = Bool(True,
557 help="""Whether to merge completion results into a single list
557 help="""Whether to merge completion results into a single list
558
558
559 If False, only the completion results from the first non-empty
559 If False, only the completion results from the first non-empty
560 completer will be returned.
560 completer will be returned.
561 """
561 """
562 ).tag(config=True)
562 ).tag(config=True)
563 omit__names = Enum((0,1,2), default_value=2,
563 omit__names = Enum((0,1,2), default_value=2,
564 help="""Instruct the completer to omit private method names
564 help="""Instruct the completer to omit private method names
565
565
566 Specifically, when completing on ``object.<tab>``.
566 Specifically, when completing on ``object.<tab>``.
567
567
568 When 2 [default]: all names that start with '_' will be excluded.
568 When 2 [default]: all names that start with '_' will be excluded.
569
569
570 When 1: all 'magic' names (``__foo__``) will be excluded.
570 When 1: all 'magic' names (``__foo__``) will be excluded.
571
571
572 When 0: nothing will be excluded.
572 When 0: nothing will be excluded.
573 """
573 """
574 ).tag(config=True)
574 ).tag(config=True)
575 limit_to__all__ = Bool(False,
575 limit_to__all__ = Bool(False,
576 help="""
576 help="""
577 DEPRECATED as of version 5.0.
577 DEPRECATED as of version 5.0.
578
578
579 Instruct the completer to use __all__ for the completion
579 Instruct the completer to use __all__ for the completion
580
580
581 Specifically, when completing on ``object.<tab>``.
581 Specifically, when completing on ``object.<tab>``.
582
582
583 When True: only those names in obj.__all__ will be included.
583 When True: only those names in obj.__all__ will be included.
584
584
585 When False [default]: the __all__ attribute is ignored
585 When False [default]: the __all__ attribute is ignored
586 """,
586 """,
587 ).tag(config=True)
587 ).tag(config=True)
588
588
589 def __init__(self, shell=None, namespace=None, global_namespace=None,
589 def __init__(self, shell=None, namespace=None, global_namespace=None,
590 use_readline=False, config=None, **kwargs):
590 use_readline=False, config=None, **kwargs):
591 """IPCompleter() -> completer
591 """IPCompleter() -> completer
592
592
593 Return a completer object suitable for use by the readline library
593 Return a completer object suitable for use by the readline library
594 via readline.set_completer().
594 via readline.set_completer().
595
595
596 Inputs:
596 Inputs:
597
597
598 - shell: a pointer to the ipython shell itself. This is needed
598 - shell: a pointer to the ipython shell itself. This is needed
599 because this completer knows about magic functions, and those can
599 because this completer knows about magic functions, and those can
600 only be accessed via the ipython instance.
600 only be accessed via the ipython instance.
601
601
602 - namespace: an optional dict where completions are performed.
602 - namespace: an optional dict where completions are performed.
603
603
604 - global_namespace: secondary optional dict for completions, to
604 - global_namespace: secondary optional dict for completions, to
605 handle cases (such as IPython embedded inside functions) where
605 handle cases (such as IPython embedded inside functions) where
606 both Python scopes are visible.
606 both Python scopes are visible.
607
607
608 use_readline : bool, optional
608 use_readline : bool, optional
609 DEPRECATED, ignored.
609 DEPRECATED, ignored.
610 """
610 """
611
611
612 self.magic_escape = ESC_MAGIC
612 self.magic_escape = ESC_MAGIC
613 self.splitter = CompletionSplitter()
613 self.splitter = CompletionSplitter()
614
614
615 if use_readline:
615 if use_readline:
616 warnings.warn('The use_readline parameter is deprecated and ignored since IPython 6.0.',
616 warnings.warn('The use_readline parameter is deprecated and ignored since IPython 6.0.',
617 DeprecationWarning, stacklevel=2)
617 DeprecationWarning, stacklevel=2)
618
618
619 # _greedy_changed() depends on splitter and readline being defined:
619 # _greedy_changed() depends on splitter and readline being defined:
620 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
620 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
621 config=config, **kwargs)
621 config=config, **kwargs)
622
622
623 # List where completion matches will be stored
623 # List where completion matches will be stored
624 self.matches = []
624 self.matches = []
625 self.shell = shell
625 self.shell = shell
626 # Regexp to split filenames with spaces in them
626 # Regexp to split filenames with spaces in them
627 self.space_name_re = re.compile(r'([^\\] )')
627 self.space_name_re = re.compile(r'([^\\] )')
628 # Hold a local ref. to glob.glob for speed
628 # Hold a local ref. to glob.glob for speed
629 self.glob = glob.glob
629 self.glob = glob.glob
630
630
631 # Determine if we are running on 'dumb' terminals, like (X)Emacs
631 # Determine if we are running on 'dumb' terminals, like (X)Emacs
632 # buffers, to avoid completion problems.
632 # buffers, to avoid completion problems.
633 term = os.environ.get('TERM','xterm')
633 term = os.environ.get('TERM','xterm')
634 self.dumb_terminal = term in ['dumb','emacs']
634 self.dumb_terminal = term in ['dumb','emacs']
635
635
636 # Special handling of backslashes needed in win32 platforms
636 # Special handling of backslashes needed in win32 platforms
637 if sys.platform == "win32":
637 if sys.platform == "win32":
638 self.clean_glob = self._clean_glob_win32
638 self.clean_glob = self._clean_glob_win32
639 else:
639 else:
640 self.clean_glob = self._clean_glob
640 self.clean_glob = self._clean_glob
641
641
642 #regexp to parse docstring for function signature
642 #regexp to parse docstring for function signature
643 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
643 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
644 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
644 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
645 #use this if positional argument name is also needed
645 #use this if positional argument name is also needed
646 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
646 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
647
647
648 # All active matcher routines for completion
648 # All active matcher routines for completion
649 self.matchers = [
649 self.matchers = [
650 self.python_matches,
650 self.python_matches,
651 self.file_matches,
651 self.file_matches,
652 self.magic_matches,
652 self.magic_matches,
653 self.python_func_kw_matches,
653 self.python_func_kw_matches,
654 self.dict_key_matches,
654 self.dict_key_matches,
655 ]
655 ]
656
656
657 # This is set externally by InteractiveShell
657 # This is set externally by InteractiveShell
658 self.custom_completers = None
658 self.custom_completers = None
659
659
660 def all_completions(self, text):
660 def all_completions(self, text):
661 """
661 """
662 Wrapper around the complete method for the benefit of emacs.
662 Wrapper around the complete method for the benefit of emacs.
663 """
663 """
664 return self.complete(text)[1]
664 return self.complete(text)[1]
665
665
666 def _clean_glob(self, text):
666 def _clean_glob(self, text):
667 return self.glob("%s*" % text)
667 return self.glob("%s*" % text)
668
668
669 def _clean_glob_win32(self,text):
669 def _clean_glob_win32(self,text):
670 return [f.replace("\\","/")
670 return [f.replace("\\","/")
671 for f in self.glob("%s*" % text)]
671 for f in self.glob("%s*" % text)]
672
672
673 def file_matches(self, text):
673 def file_matches(self, text):
674 """Match filenames, expanding ~USER type strings.
674 """Match filenames, expanding ~USER type strings.
675
675
676 Most of the seemingly convoluted logic in this completer is an
676 Most of the seemingly convoluted logic in this completer is an
677 attempt to handle filenames with spaces in them. And yet it's not
677 attempt to handle filenames with spaces in them. And yet it's not
678 quite perfect, because Python's readline doesn't expose all of the
678 quite perfect, because Python's readline doesn't expose all of the
679 GNU readline details needed for this to be done correctly.
679 GNU readline details needed for this to be done correctly.
680
680
681 For a filename with a space in it, the printed completions will be
681 For a filename with a space in it, the printed completions will be
682 only the parts after what's already been typed (instead of the
682 only the parts after what's already been typed (instead of the
683 full completions, as is normally done). I don't think with the
683 full completions, as is normally done). I don't think with the
684 current (as of Python 2.3) Python readline it's possible to do
684 current (as of Python 2.3) Python readline it's possible to do
685 better."""
685 better."""
686
686
687 # chars that require escaping with backslash - i.e. chars
687 # chars that require escaping with backslash - i.e. chars
688 # that readline treats incorrectly as delimiters, but we
688 # that readline treats incorrectly as delimiters, but we
689 # don't want to treat as delimiters in filename matching
689 # don't want to treat as delimiters in filename matching
690 # when escaped with backslash
690 # when escaped with backslash
691 if text.startswith('!'):
691 if text.startswith('!'):
692 text = text[1:]
692 text = text[1:]
693 text_prefix = u'!'
693 text_prefix = u'!'
694 else:
694 else:
695 text_prefix = u''
695 text_prefix = u''
696
696
697 text_until_cursor = self.text_until_cursor
697 text_until_cursor = self.text_until_cursor
698 # track strings with open quotes
698 # track strings with open quotes
699 open_quotes = has_open_quotes(text_until_cursor)
699 open_quotes = has_open_quotes(text_until_cursor)
700
700
701 if '(' in text_until_cursor or '[' in text_until_cursor:
701 if '(' in text_until_cursor or '[' in text_until_cursor:
702 lsplit = text
702 lsplit = text
703 else:
703 else:
704 try:
704 try:
705 # arg_split ~ shlex.split, but with unicode bugs fixed by us
705 # arg_split ~ shlex.split, but with unicode bugs fixed by us
706 lsplit = arg_split(text_until_cursor)[-1]
706 lsplit = arg_split(text_until_cursor)[-1]
707 except ValueError:
707 except ValueError:
708 # typically an unmatched ", or backslash without escaped char.
708 # typically an unmatched ", or backslash without escaped char.
709 if open_quotes:
709 if open_quotes:
710 lsplit = text_until_cursor.split(open_quotes)[-1]
710 lsplit = text_until_cursor.split(open_quotes)[-1]
711 else:
711 else:
712 return []
712 return []
713 except IndexError:
713 except IndexError:
714 # tab pressed on empty line
714 # tab pressed on empty line
715 lsplit = ""
715 lsplit = ""
716
716
717 if not open_quotes and lsplit != protect_filename(lsplit):
717 if not open_quotes and lsplit != protect_filename(lsplit):
718 # if protectables are found, do matching on the whole escaped name
718 # if protectables are found, do matching on the whole escaped name
719 has_protectables = True
719 has_protectables = True
720 text0,text = text,lsplit
720 text0,text = text,lsplit
721 else:
721 else:
722 has_protectables = False
722 has_protectables = False
723 text = os.path.expanduser(text)
723 text = os.path.expanduser(text)
724
724
725 if text == "":
725 if text == "":
726 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
726 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
727
727
728 # Compute the matches from the filesystem
728 # Compute the matches from the filesystem
729 if sys.platform == 'win32':
729 if sys.platform == 'win32':
730 m0 = self.clean_glob(text)
730 m0 = self.clean_glob(text)
731 else:
731 else:
732 m0 = self.clean_glob(text.replace('\\', ''))
732 m0 = self.clean_glob(text.replace('\\', ''))
733
733
734 if has_protectables:
734 if has_protectables:
735 # If we had protectables, we need to revert our changes to the
735 # If we had protectables, we need to revert our changes to the
736 # beginning of filename so that we don't double-write the part
736 # beginning of filename so that we don't double-write the part
737 # of the filename we have so far
737 # of the filename we have so far
738 len_lsplit = len(lsplit)
738 len_lsplit = len(lsplit)
739 matches = [text_prefix + text0 +
739 matches = [text_prefix + text0 +
740 protect_filename(f[len_lsplit:]) for f in m0]
740 protect_filename(f[len_lsplit:]) for f in m0]
741 else:
741 else:
742 if open_quotes:
742 if open_quotes:
743 # if we have a string with an open quote, we don't need to
743 # if we have a string with an open quote, we don't need to
744 # protect the names at all (and we _shouldn't_, as it
744 # protect the names at all (and we _shouldn't_, as it
745 # would cause bugs when the filesystem call is made).
745 # would cause bugs when the filesystem call is made).
746 matches = m0
746 matches = m0
747 else:
747 else:
748 matches = [text_prefix +
748 matches = [text_prefix +
749 protect_filename(f) for f in m0]
749 protect_filename(f) for f in m0]
750
750
751 # Mark directories in input list by appending '/' to their names.
751 # Mark directories in input list by appending '/' to their names.
752 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
752 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
753
753
754 def magic_matches(self, text):
754 def magic_matches(self, text):
755 """Match magics"""
755 """Match magics"""
756 # Get all shell magics now rather than statically, so magics loaded at
756 # Get all shell magics now rather than statically, so magics loaded at
757 # runtime show up too.
757 # runtime show up too.
758 lsm = self.shell.magics_manager.lsmagic()
758 lsm = self.shell.magics_manager.lsmagic()
759 line_magics = lsm['line']
759 line_magics = lsm['line']
760 cell_magics = lsm['cell']
760 cell_magics = lsm['cell']
761 pre = self.magic_escape
761 pre = self.magic_escape
762 pre2 = pre+pre
762 pre2 = pre+pre
763
763
764 # Completion logic:
764 # Completion logic:
765 # - user gives %%: only do cell magics
765 # - user gives %%: only do cell magics
766 # - user gives %: do both line and cell magics
766 # - user gives %: do both line and cell magics
767 # - no prefix: do both
767 # - no prefix: do both
768 # In other words, line magics are skipped if the user gives %% explicitly
768 # In other words, line magics are skipped if the user gives %% explicitly
769 bare_text = text.lstrip(pre)
769 bare_text = text.lstrip(pre)
770 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
770 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
771 if not text.startswith(pre2):
771 if not text.startswith(pre2):
772 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
772 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
773 return [cast_unicode_py2(c) for c in comp]
773 return [cast_unicode_py2(c) for c in comp]
774
774
775
775
776 def python_matches(self, text):
776 def python_matches(self, text):
777 """Match attributes or global python names"""
777 """Match attributes or global python names"""
778 if "." in text:
778 if "." in text:
779 try:
779 try:
780 matches = self.attr_matches(text)
780 matches = self.attr_matches(text)
781 if text.endswith('.') and self.omit__names:
781 if text.endswith('.') and self.omit__names:
782 if self.omit__names == 1:
782 if self.omit__names == 1:
783 # true if txt is _not_ a __ name, false otherwise:
783 # true if txt is _not_ a __ name, false otherwise:
784 no__name = (lambda txt:
784 no__name = (lambda txt:
785 re.match(r'.*\.__.*?__',txt) is None)
785 re.match(r'.*\.__.*?__',txt) is None)
786 else:
786 else:
787 # true if txt is _not_ a _ name, false otherwise:
787 # true if txt is _not_ a _ name, false otherwise:
788 no__name = (lambda txt:
788 no__name = (lambda txt:
789 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
789 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
790 matches = filter(no__name, matches)
790 matches = filter(no__name, matches)
791 except NameError:
791 except NameError:
792 # catches <undefined attributes>.<tab>
792 # catches <undefined attributes>.<tab>
793 matches = []
793 matches = []
794 else:
794 else:
795 matches = self.global_matches(text)
795 matches = self.global_matches(text)
796 return matches
796 return matches
797
797
798 def _default_arguments_from_docstring(self, doc):
798 def _default_arguments_from_docstring(self, doc):
799 """Parse the first line of docstring for call signature.
799 """Parse the first line of docstring for call signature.
800
800
801 Docstring should be of the form 'min(iterable[, key=func])\n'.
801 Docstring should be of the form 'min(iterable[, key=func])\n'.
802 It can also parse cython docstring of the form
802 It can also parse cython docstring of the form
803 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
803 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
804 """
804 """
805 if doc is None:
805 if doc is None:
806 return []
806 return []
807
807
808 #care only the firstline
808 #care only the firstline
809 line = doc.lstrip().splitlines()[0]
809 line = doc.lstrip().splitlines()[0]
810
810
811 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
811 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
812 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
812 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
813 sig = self.docstring_sig_re.search(line)
813 sig = self.docstring_sig_re.search(line)
814 if sig is None:
814 if sig is None:
815 return []
815 return []
816 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
816 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
817 sig = sig.groups()[0].split(',')
817 sig = sig.groups()[0].split(',')
818 ret = []
818 ret = []
819 for s in sig:
819 for s in sig:
820 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
820 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
821 ret += self.docstring_kwd_re.findall(s)
821 ret += self.docstring_kwd_re.findall(s)
822 return ret
822 return ret
823
823
824 def _default_arguments(self, obj):
824 def _default_arguments(self, obj):
825 """Return the list of default arguments of obj if it is callable,
825 """Return the list of default arguments of obj if it is callable,
826 or empty list otherwise."""
826 or empty list otherwise."""
827 call_obj = obj
827 call_obj = obj
828 ret = []
828 ret = []
829 if inspect.isbuiltin(obj):
829 if inspect.isbuiltin(obj):
830 pass
830 pass
831 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
831 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
832 if inspect.isclass(obj):
832 if inspect.isclass(obj):
833 #for cython embededsignature=True the constructor docstring
833 #for cython embededsignature=True the constructor docstring
834 #belongs to the object itself not __init__
834 #belongs to the object itself not __init__
835 ret += self._default_arguments_from_docstring(
835 ret += self._default_arguments_from_docstring(
836 getattr(obj, '__doc__', ''))
836 getattr(obj, '__doc__', ''))
837 # for classes, check for __init__,__new__
837 # for classes, check for __init__,__new__
838 call_obj = (getattr(obj, '__init__', None) or
838 call_obj = (getattr(obj, '__init__', None) or
839 getattr(obj, '__new__', None))
839 getattr(obj, '__new__', None))
840 # for all others, check if they are __call__able
840 # for all others, check if they are __call__able
841 elif hasattr(obj, '__call__'):
841 elif hasattr(obj, '__call__'):
842 call_obj = obj.__call__
842 call_obj = obj.__call__
843 ret += self._default_arguments_from_docstring(
843 ret += self._default_arguments_from_docstring(
844 getattr(call_obj, '__doc__', ''))
844 getattr(call_obj, '__doc__', ''))
845
845
846 if PY3:
846 _keeps = (inspect.Parameter.KEYWORD_ONLY,
847 _keeps = (inspect.Parameter.KEYWORD_ONLY,
847 inspect.Parameter.POSITIONAL_OR_KEYWORD)
848 inspect.Parameter.POSITIONAL_OR_KEYWORD)
849 signature = inspect.signature
850 else:
851 import IPython.utils.signatures
852 _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY,
853 IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD)
854 signature = IPython.utils.signatures.signature
855
848
856 try:
849 try:
857 sig = signature(call_obj)
850 sig = inspect.signature(call_obj)
858 ret.extend(k for k, v in sig.parameters.items() if
851 ret.extend(k for k, v in sig.parameters.items() if
859 v.kind in _keeps)
852 v.kind in _keeps)
860 except ValueError:
853 except ValueError:
861 pass
854 pass
862
855
863 return list(set(ret))
856 return list(set(ret))
864
857
865 def python_func_kw_matches(self,text):
858 def python_func_kw_matches(self,text):
866 """Match named parameters (kwargs) of the last open function"""
859 """Match named parameters (kwargs) of the last open function"""
867
860
868 if "." in text: # a parameter cannot be dotted
861 if "." in text: # a parameter cannot be dotted
869 return []
862 return []
870 try: regexp = self.__funcParamsRegex
863 try: regexp = self.__funcParamsRegex
871 except AttributeError:
864 except AttributeError:
872 regexp = self.__funcParamsRegex = re.compile(r'''
865 regexp = self.__funcParamsRegex = re.compile(r'''
873 '.*?(?<!\\)' | # single quoted strings or
866 '.*?(?<!\\)' | # single quoted strings or
874 ".*?(?<!\\)" | # double quoted strings or
867 ".*?(?<!\\)" | # double quoted strings or
875 \w+ | # identifier
868 \w+ | # identifier
876 \S # other characters
869 \S # other characters
877 ''', re.VERBOSE | re.DOTALL)
870 ''', re.VERBOSE | re.DOTALL)
878 # 1. find the nearest identifier that comes before an unclosed
871 # 1. find the nearest identifier that comes before an unclosed
879 # parenthesis before the cursor
872 # parenthesis before the cursor
880 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
873 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
881 tokens = regexp.findall(self.text_until_cursor)
874 tokens = regexp.findall(self.text_until_cursor)
882 iterTokens = reversed(tokens); openPar = 0
875 iterTokens = reversed(tokens); openPar = 0
883
876
884 for token in iterTokens:
877 for token in iterTokens:
885 if token == ')':
878 if token == ')':
886 openPar -= 1
879 openPar -= 1
887 elif token == '(':
880 elif token == '(':
888 openPar += 1
881 openPar += 1
889 if openPar > 0:
882 if openPar > 0:
890 # found the last unclosed parenthesis
883 # found the last unclosed parenthesis
891 break
884 break
892 else:
885 else:
893 return []
886 return []
894 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
887 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
895 ids = []
888 ids = []
896 isId = re.compile(r'\w+$').match
889 isId = re.compile(r'\w+$').match
897
890
898 while True:
891 while True:
899 try:
892 try:
900 ids.append(next(iterTokens))
893 ids.append(next(iterTokens))
901 if not isId(ids[-1]):
894 if not isId(ids[-1]):
902 ids.pop(); break
895 ids.pop(); break
903 if not next(iterTokens) == '.':
896 if not next(iterTokens) == '.':
904 break
897 break
905 except StopIteration:
898 except StopIteration:
906 break
899 break
907
900
908 # Find all named arguments already assigned to, as to avoid suggesting
901 # Find all named arguments already assigned to, as to avoid suggesting
909 # them again
902 # them again
910 usedNamedArgs = set()
903 usedNamedArgs = set()
911 par_level = -1
904 par_level = -1
912 for token, next_token in zip(tokens, tokens[1:]):
905 for token, next_token in zip(tokens, tokens[1:]):
913 if token == '(':
906 if token == '(':
914 par_level += 1
907 par_level += 1
915 elif token == ')':
908 elif token == ')':
916 par_level -= 1
909 par_level -= 1
917
910
918 if par_level != 0:
911 if par_level != 0:
919 continue
912 continue
920
913
921 if next_token != '=':
914 if next_token != '=':
922 continue
915 continue
923
916
924 usedNamedArgs.add(token)
917 usedNamedArgs.add(token)
925
918
926 # lookup the candidate callable matches either using global_matches
919 # lookup the candidate callable matches either using global_matches
927 # or attr_matches for dotted names
920 # or attr_matches for dotted names
928 if len(ids) == 1:
921 if len(ids) == 1:
929 callableMatches = self.global_matches(ids[0])
922 callableMatches = self.global_matches(ids[0])
930 else:
923 else:
931 callableMatches = self.attr_matches('.'.join(ids[::-1]))
924 callableMatches = self.attr_matches('.'.join(ids[::-1]))
932 argMatches = []
925 argMatches = []
933 for callableMatch in callableMatches:
926 for callableMatch in callableMatches:
934 try:
927 try:
935 namedArgs = self._default_arguments(eval(callableMatch,
928 namedArgs = self._default_arguments(eval(callableMatch,
936 self.namespace))
929 self.namespace))
937 except:
930 except:
938 continue
931 continue
939
932
940 # Remove used named arguments from the list, no need to show twice
933 # Remove used named arguments from the list, no need to show twice
941 for namedArg in set(namedArgs) - usedNamedArgs:
934 for namedArg in set(namedArgs) - usedNamedArgs:
942 if namedArg.startswith(text):
935 if namedArg.startswith(text):
943 argMatches.append(u"%s=" %namedArg)
936 argMatches.append(u"%s=" %namedArg)
944 return argMatches
937 return argMatches
945
938
946 def dict_key_matches(self, text):
939 def dict_key_matches(self, text):
947 "Match string keys in a dictionary, after e.g. 'foo[' "
940 "Match string keys in a dictionary, after e.g. 'foo[' "
948 def get_keys(obj):
941 def get_keys(obj):
949 # Objects can define their own completions by defining an
942 # Objects can define their own completions by defining an
950 # _ipy_key_completions_() method.
943 # _ipy_key_completions_() method.
951 method = get_real_method(obj, '_ipython_key_completions_')
944 method = get_real_method(obj, '_ipython_key_completions_')
952 if method is not None:
945 if method is not None:
953 return method()
946 return method()
954
947
955 # Special case some common in-memory dict-like types
948 # Special case some common in-memory dict-like types
956 if isinstance(obj, dict) or\
949 if isinstance(obj, dict) or\
957 _safe_isinstance(obj, 'pandas', 'DataFrame'):
950 _safe_isinstance(obj, 'pandas', 'DataFrame'):
958 try:
951 try:
959 return list(obj.keys())
952 return list(obj.keys())
960 except Exception:
953 except Exception:
961 return []
954 return []
962 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
955 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
963 _safe_isinstance(obj, 'numpy', 'void'):
956 _safe_isinstance(obj, 'numpy', 'void'):
964 return obj.dtype.names or []
957 return obj.dtype.names or []
965 return []
958 return []
966
959
967 try:
960 try:
968 regexps = self.__dict_key_regexps
961 regexps = self.__dict_key_regexps
969 except AttributeError:
962 except AttributeError:
970 dict_key_re_fmt = r'''(?x)
963 dict_key_re_fmt = r'''(?x)
971 ( # match dict-referring expression wrt greedy setting
964 ( # match dict-referring expression wrt greedy setting
972 %s
965 %s
973 )
966 )
974 \[ # open bracket
967 \[ # open bracket
975 \s* # and optional whitespace
968 \s* # and optional whitespace
976 ([uUbB]? # string prefix (r not handled)
969 ([uUbB]? # string prefix (r not handled)
977 (?: # unclosed string
970 (?: # unclosed string
978 '(?:[^']|(?<!\\)\\')*
971 '(?:[^']|(?<!\\)\\')*
979 |
972 |
980 "(?:[^"]|(?<!\\)\\")*
973 "(?:[^"]|(?<!\\)\\")*
981 )
974 )
982 )?
975 )?
983 $
976 $
984 '''
977 '''
985 regexps = self.__dict_key_regexps = {
978 regexps = self.__dict_key_regexps = {
986 False: re.compile(dict_key_re_fmt % '''
979 False: re.compile(dict_key_re_fmt % '''
987 # identifiers separated by .
980 # identifiers separated by .
988 (?!\d)\w+
981 (?!\d)\w+
989 (?:\.(?!\d)\w+)*
982 (?:\.(?!\d)\w+)*
990 '''),
983 '''),
991 True: re.compile(dict_key_re_fmt % '''
984 True: re.compile(dict_key_re_fmt % '''
992 .+
985 .+
993 ''')
986 ''')
994 }
987 }
995
988
996 match = regexps[self.greedy].search(self.text_until_cursor)
989 match = regexps[self.greedy].search(self.text_until_cursor)
997 if match is None:
990 if match is None:
998 return []
991 return []
999
992
1000 expr, prefix = match.groups()
993 expr, prefix = match.groups()
1001 try:
994 try:
1002 obj = eval(expr, self.namespace)
995 obj = eval(expr, self.namespace)
1003 except Exception:
996 except Exception:
1004 try:
997 try:
1005 obj = eval(expr, self.global_namespace)
998 obj = eval(expr, self.global_namespace)
1006 except Exception:
999 except Exception:
1007 return []
1000 return []
1008
1001
1009 keys = get_keys(obj)
1002 keys = get_keys(obj)
1010 if not keys:
1003 if not keys:
1011 return keys
1004 return keys
1012 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1005 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1013 if not matches:
1006 if not matches:
1014 return matches
1007 return matches
1015
1008
1016 # get the cursor position of
1009 # get the cursor position of
1017 # - the text being completed
1010 # - the text being completed
1018 # - the start of the key text
1011 # - the start of the key text
1019 # - the start of the completion
1012 # - the start of the completion
1020 text_start = len(self.text_until_cursor) - len(text)
1013 text_start = len(self.text_until_cursor) - len(text)
1021 if prefix:
1014 if prefix:
1022 key_start = match.start(2)
1015 key_start = match.start(2)
1023 completion_start = key_start + token_offset
1016 completion_start = key_start + token_offset
1024 else:
1017 else:
1025 key_start = completion_start = match.end()
1018 key_start = completion_start = match.end()
1026
1019
1027 # grab the leading prefix, to make sure all completions start with `text`
1020 # grab the leading prefix, to make sure all completions start with `text`
1028 if text_start > key_start:
1021 if text_start > key_start:
1029 leading = ''
1022 leading = ''
1030 else:
1023 else:
1031 leading = text[text_start:completion_start]
1024 leading = text[text_start:completion_start]
1032
1025
1033 # the index of the `[` character
1026 # the index of the `[` character
1034 bracket_idx = match.end(1)
1027 bracket_idx = match.end(1)
1035
1028
1036 # append closing quote and bracket as appropriate
1029 # append closing quote and bracket as appropriate
1037 # this is *not* appropriate if the opening quote or bracket is outside
1030 # this is *not* appropriate if the opening quote or bracket is outside
1038 # the text given to this method
1031 # the text given to this method
1039 suf = ''
1032 suf = ''
1040 continuation = self.line_buffer[len(self.text_until_cursor):]
1033 continuation = self.line_buffer[len(self.text_until_cursor):]
1041 if key_start > text_start and closing_quote:
1034 if key_start > text_start and closing_quote:
1042 # quotes were opened inside text, maybe close them
1035 # quotes were opened inside text, maybe close them
1043 if continuation.startswith(closing_quote):
1036 if continuation.startswith(closing_quote):
1044 continuation = continuation[len(closing_quote):]
1037 continuation = continuation[len(closing_quote):]
1045 else:
1038 else:
1046 suf += closing_quote
1039 suf += closing_quote
1047 if bracket_idx > text_start:
1040 if bracket_idx > text_start:
1048 # brackets were opened inside text, maybe close them
1041 # brackets were opened inside text, maybe close them
1049 if not continuation.startswith(']'):
1042 if not continuation.startswith(']'):
1050 suf += ']'
1043 suf += ']'
1051
1044
1052 return [leading + k + suf for k in matches]
1045 return [leading + k + suf for k in matches]
1053
1046
1054 def unicode_name_matches(self, text):
1047 def unicode_name_matches(self, text):
1055 u"""Match Latex-like syntax for unicode characters base
1048 u"""Match Latex-like syntax for unicode characters base
1056 on the name of the character.
1049 on the name of the character.
1057
1050
1058 This does \\GREEK SMALL LETTER ETA -> η
1051 This does \\GREEK SMALL LETTER ETA -> η
1059
1052
1060 Works only on valid python 3 identifier, or on combining characters that
1053 Works only on valid python 3 identifier, or on combining characters that
1061 will combine to form a valid identifier.
1054 will combine to form a valid identifier.
1062
1055
1063 Used on Python 3 only.
1056 Used on Python 3 only.
1064 """
1057 """
1065 slashpos = text.rfind('\\')
1058 slashpos = text.rfind('\\')
1066 if slashpos > -1:
1059 if slashpos > -1:
1067 s = text[slashpos+1:]
1060 s = text[slashpos+1:]
1068 try :
1061 try :
1069 unic = unicodedata.lookup(s)
1062 unic = unicodedata.lookup(s)
1070 # allow combining chars
1063 # allow combining chars
1071 if ('a'+unic).isidentifier():
1064 if ('a'+unic).isidentifier():
1072 return '\\'+s,[unic]
1065 return '\\'+s,[unic]
1073 except KeyError:
1066 except KeyError:
1074 pass
1067 pass
1075 return u'', []
1068 return u'', []
1076
1069
1077
1070
1078
1071
1079
1072
1080 def latex_matches(self, text):
1073 def latex_matches(self, text):
1081 u"""Match Latex syntax for unicode characters.
1074 u"""Match Latex syntax for unicode characters.
1082
1075
1083 This does both \\alp -> \\alpha and \\alpha -> α
1076 This does both \\alp -> \\alpha and \\alpha -> α
1084
1077
1085 Used on Python 3 only.
1078 Used on Python 3 only.
1086 """
1079 """
1087 slashpos = text.rfind('\\')
1080 slashpos = text.rfind('\\')
1088 if slashpos > -1:
1081 if slashpos > -1:
1089 s = text[slashpos:]
1082 s = text[slashpos:]
1090 if s in latex_symbols:
1083 if s in latex_symbols:
1091 # Try to complete a full latex symbol to unicode
1084 # Try to complete a full latex symbol to unicode
1092 # \\alpha -> α
1085 # \\alpha -> α
1093 return s, [latex_symbols[s]]
1086 return s, [latex_symbols[s]]
1094 else:
1087 else:
1095 # If a user has partially typed a latex symbol, give them
1088 # If a user has partially typed a latex symbol, give them
1096 # a full list of options \al -> [\aleph, \alpha]
1089 # a full list of options \al -> [\aleph, \alpha]
1097 matches = [k for k in latex_symbols if k.startswith(s)]
1090 matches = [k for k in latex_symbols if k.startswith(s)]
1098 return s, matches
1091 return s, matches
1099 return u'', []
1092 return u'', []
1100
1093
1101 def dispatch_custom_completer(self, text):
1094 def dispatch_custom_completer(self, text):
1102 if not self.custom_completers:
1095 if not self.custom_completers:
1103 return
1096 return
1104
1097
1105 line = self.line_buffer
1098 line = self.line_buffer
1106 if not line.strip():
1099 if not line.strip():
1107 return None
1100 return None
1108
1101
1109 # Create a little structure to pass all the relevant information about
1102 # Create a little structure to pass all the relevant information about
1110 # the current completion to any custom completer.
1103 # the current completion to any custom completer.
1111 event = Bunch()
1104 event = Bunch()
1112 event.line = line
1105 event.line = line
1113 event.symbol = text
1106 event.symbol = text
1114 cmd = line.split(None,1)[0]
1107 cmd = line.split(None,1)[0]
1115 event.command = cmd
1108 event.command = cmd
1116 event.text_until_cursor = self.text_until_cursor
1109 event.text_until_cursor = self.text_until_cursor
1117
1110
1118 # for foo etc, try also to find completer for %foo
1111 # for foo etc, try also to find completer for %foo
1119 if not cmd.startswith(self.magic_escape):
1112 if not cmd.startswith(self.magic_escape):
1120 try_magic = self.custom_completers.s_matches(
1113 try_magic = self.custom_completers.s_matches(
1121 self.magic_escape + cmd)
1114 self.magic_escape + cmd)
1122 else:
1115 else:
1123 try_magic = []
1116 try_magic = []
1124
1117
1125 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1118 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1126 try_magic,
1119 try_magic,
1127 self.custom_completers.flat_matches(self.text_until_cursor)):
1120 self.custom_completers.flat_matches(self.text_until_cursor)):
1128 try:
1121 try:
1129 res = c(event)
1122 res = c(event)
1130 if res:
1123 if res:
1131 # first, try case sensitive match
1124 # first, try case sensitive match
1132 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1125 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1133 if withcase:
1126 if withcase:
1134 return withcase
1127 return withcase
1135 # if none, then case insensitive ones are ok too
1128 # if none, then case insensitive ones are ok too
1136 text_low = text.lower()
1129 text_low = text.lower()
1137 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1130 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1138 except TryNext:
1131 except TryNext:
1139 pass
1132 pass
1140
1133
1141 return None
1134 return None
1142
1135
1143 @_strip_single_trailing_space
1136 @_strip_single_trailing_space
1144 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1137 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1145 """Find completions for the given text and line context.
1138 """Find completions for the given text and line context.
1146
1139
1147 Note that both the text and the line_buffer are optional, but at least
1140 Note that both the text and the line_buffer are optional, but at least
1148 one of them must be given.
1141 one of them must be given.
1149
1142
1150 Parameters
1143 Parameters
1151 ----------
1144 ----------
1152 text : string, optional
1145 text : string, optional
1153 Text to perform the completion on. If not given, the line buffer
1146 Text to perform the completion on. If not given, the line buffer
1154 is split using the instance's CompletionSplitter object.
1147 is split using the instance's CompletionSplitter object.
1155
1148
1156 line_buffer : string, optional
1149 line_buffer : string, optional
1157 If not given, the completer attempts to obtain the current line
1150 If not given, the completer attempts to obtain the current line
1158 buffer via readline. This keyword allows clients which are
1151 buffer via readline. This keyword allows clients which are
1159 requesting for text completions in non-readline contexts to inform
1152 requesting for text completions in non-readline contexts to inform
1160 the completer of the entire text.
1153 the completer of the entire text.
1161
1154
1162 cursor_pos : int, optional
1155 cursor_pos : int, optional
1163 Index of the cursor in the full line buffer. Should be provided by
1156 Index of the cursor in the full line buffer. Should be provided by
1164 remote frontends where kernel has no access to frontend state.
1157 remote frontends where kernel has no access to frontend state.
1165
1158
1166 Returns
1159 Returns
1167 -------
1160 -------
1168 text : str
1161 text : str
1169 Text that was actually used in the completion.
1162 Text that was actually used in the completion.
1170
1163
1171 matches : list
1164 matches : list
1172 A list of completion matches.
1165 A list of completion matches.
1173 """
1166 """
1174 # if the cursor position isn't given, the only sane assumption we can
1167 # if the cursor position isn't given, the only sane assumption we can
1175 # make is that it's at the end of the line (the common case)
1168 # make is that it's at the end of the line (the common case)
1176 if cursor_pos is None:
1169 if cursor_pos is None:
1177 cursor_pos = len(line_buffer) if text is None else len(text)
1170 cursor_pos = len(line_buffer) if text is None else len(text)
1178
1171
1179 if self.use_main_ns:
1172 if self.use_main_ns:
1180 self.namespace = __main__.__dict__
1173 self.namespace = __main__.__dict__
1181
1174
1182 if PY3:
1175 if PY3:
1183
1176
1184 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1177 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1185 latex_text, latex_matches = self.latex_matches(base_text)
1178 latex_text, latex_matches = self.latex_matches(base_text)
1186 if latex_matches:
1179 if latex_matches:
1187 return latex_text, latex_matches
1180 return latex_text, latex_matches
1188 name_text = ''
1181 name_text = ''
1189 name_matches = []
1182 name_matches = []
1190 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1183 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1191 name_text, name_matches = meth(base_text)
1184 name_text, name_matches = meth(base_text)
1192 if name_text:
1185 if name_text:
1193 return name_text, name_matches
1186 return name_text, name_matches
1194
1187
1195 # if text is either None or an empty string, rely on the line buffer
1188 # if text is either None or an empty string, rely on the line buffer
1196 if not text:
1189 if not text:
1197 text = self.splitter.split_line(line_buffer, cursor_pos)
1190 text = self.splitter.split_line(line_buffer, cursor_pos)
1198
1191
1199 # If no line buffer is given, assume the input text is all there was
1192 # If no line buffer is given, assume the input text is all there was
1200 if line_buffer is None:
1193 if line_buffer is None:
1201 line_buffer = text
1194 line_buffer = text
1202
1195
1203 self.line_buffer = line_buffer
1196 self.line_buffer = line_buffer
1204 self.text_until_cursor = self.line_buffer[:cursor_pos]
1197 self.text_until_cursor = self.line_buffer[:cursor_pos]
1205
1198
1206 # Start with a clean slate of completions
1199 # Start with a clean slate of completions
1207 self.matches[:] = []
1200 self.matches[:] = []
1208 custom_res = self.dispatch_custom_completer(text)
1201 custom_res = self.dispatch_custom_completer(text)
1209 if custom_res is not None:
1202 if custom_res is not None:
1210 # did custom completers produce something?
1203 # did custom completers produce something?
1211 self.matches = custom_res
1204 self.matches = custom_res
1212 else:
1205 else:
1213 # Extend the list of completions with the results of each
1206 # Extend the list of completions with the results of each
1214 # matcher, so we return results to the user from all
1207 # matcher, so we return results to the user from all
1215 # namespaces.
1208 # namespaces.
1216 if self.merge_completions:
1209 if self.merge_completions:
1217 self.matches = []
1210 self.matches = []
1218 for matcher in self.matchers:
1211 for matcher in self.matchers:
1219 try:
1212 try:
1220 self.matches.extend(matcher(text))
1213 self.matches.extend(matcher(text))
1221 except:
1214 except:
1222 # Show the ugly traceback if the matcher causes an
1215 # Show the ugly traceback if the matcher causes an
1223 # exception, but do NOT crash the kernel!
1216 # exception, but do NOT crash the kernel!
1224 sys.excepthook(*sys.exc_info())
1217 sys.excepthook(*sys.exc_info())
1225 else:
1218 else:
1226 for matcher in self.matchers:
1219 for matcher in self.matchers:
1227 self.matches = matcher(text)
1220 self.matches = matcher(text)
1228 if self.matches:
1221 if self.matches:
1229 break
1222 break
1230 # FIXME: we should extend our api to return a dict with completions for
1223 # FIXME: we should extend our api to return a dict with completions for
1231 # different types of objects. The rlcomplete() method could then
1224 # different types of objects. The rlcomplete() method could then
1232 # simply collapse the dict into a list for readline, but we'd have
1225 # simply collapse the dict into a list for readline, but we'd have
1233 # richer completion semantics in other evironments.
1226 # richer completion semantics in other evironments.
1234 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1227 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1235
1228
1236 return text, self.matches
1229 return text, self.matches
@@ -1,1009 +1,1009 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8 """
8 """
9
9
10 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12
12
13 __all__ = ['Inspector','InspectColors']
13 __all__ = ['Inspector','InspectColors']
14
14
15 # stdlib modules
15 # stdlib modules
16 import inspect
16 import inspect
17 from inspect import signature
17 import linecache
18 import linecache
18 import warnings
19 import warnings
19 import os
20 import os
20 from textwrap import dedent
21 from textwrap import dedent
21 import types
22 import types
22 import io as stdlib_io
23 import io as stdlib_io
23
24
24 try:
25 try:
25 from itertools import izip_longest
26 from itertools import izip_longest
26 except ImportError:
27 except ImportError:
27 from itertools import zip_longest as izip_longest
28 from itertools import zip_longest as izip_longest
28
29
29 # IPython's own
30 # IPython's own
30 from IPython.core import page
31 from IPython.core import page
31 from IPython.lib.pretty import pretty
32 from IPython.lib.pretty import pretty
32 from IPython.testing.skipdoctest import skip_doctest
33 from IPython.testing.skipdoctest import skip_doctest
33 from IPython.utils import PyColorize
34 from IPython.utils import PyColorize
34 from IPython.utils import openpy
35 from IPython.utils import openpy
35 from IPython.utils import py3compat
36 from IPython.utils import py3compat
36 from IPython.utils.dir2 import safe_hasattr
37 from IPython.utils.dir2 import safe_hasattr
37 from IPython.utils.path import compress_user
38 from IPython.utils.path import compress_user
38 from IPython.utils.text import indent
39 from IPython.utils.text import indent
39 from IPython.utils.wildcard import list_namespace
40 from IPython.utils.wildcard import list_namespace
40 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41 from IPython.utils.py3compat import cast_unicode, string_types, PY3
42 from IPython.utils.py3compat import cast_unicode, string_types, PY3
42 from IPython.utils.signatures import signature
43 from IPython.utils.colorable import Colorable
43 from IPython.utils.colorable import Colorable
44
44
45 from pygments import highlight
45 from pygments import highlight
46 from pygments.lexers import PythonLexer
46 from pygments.lexers import PythonLexer
47 from pygments.formatters import HtmlFormatter
47 from pygments.formatters import HtmlFormatter
48
48
49 def pylight(code):
49 def pylight(code):
50 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
50 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
51
51
52 # builtin docstrings to ignore
52 # builtin docstrings to ignore
53 _func_call_docstring = types.FunctionType.__call__.__doc__
53 _func_call_docstring = types.FunctionType.__call__.__doc__
54 _object_init_docstring = object.__init__.__doc__
54 _object_init_docstring = object.__init__.__doc__
55 _builtin_type_docstrings = {
55 _builtin_type_docstrings = {
56 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
56 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
57 types.FunctionType, property)
57 types.FunctionType, property)
58 }
58 }
59
59
60 _builtin_func_type = type(all)
60 _builtin_func_type = type(all)
61 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
61 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
62 #****************************************************************************
62 #****************************************************************************
63 # Builtin color schemes
63 # Builtin color schemes
64
64
65 Colors = TermColors # just a shorthand
65 Colors = TermColors # just a shorthand
66
66
67 InspectColors = PyColorize.ANSICodeColors
67 InspectColors = PyColorize.ANSICodeColors
68
68
69 #****************************************************************************
69 #****************************************************************************
70 # Auxiliary functions and objects
70 # Auxiliary functions and objects
71
71
72 # See the messaging spec for the definition of all these fields. This list
72 # See the messaging spec for the definition of all these fields. This list
73 # effectively defines the order of display
73 # effectively defines the order of display
74 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
74 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
75 'length', 'file', 'definition', 'docstring', 'source',
75 'length', 'file', 'definition', 'docstring', 'source',
76 'init_definition', 'class_docstring', 'init_docstring',
76 'init_definition', 'class_docstring', 'init_docstring',
77 'call_def', 'call_docstring',
77 'call_def', 'call_docstring',
78 # These won't be printed but will be used to determine how to
78 # These won't be printed but will be used to determine how to
79 # format the object
79 # format the object
80 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
80 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
81 ]
81 ]
82
82
83
83
84 def object_info(**kw):
84 def object_info(**kw):
85 """Make an object info dict with all fields present."""
85 """Make an object info dict with all fields present."""
86 infodict = dict(izip_longest(info_fields, [None]))
86 infodict = dict(izip_longest(info_fields, [None]))
87 infodict.update(kw)
87 infodict.update(kw)
88 return infodict
88 return infodict
89
89
90
90
91 def get_encoding(obj):
91 def get_encoding(obj):
92 """Get encoding for python source file defining obj
92 """Get encoding for python source file defining obj
93
93
94 Returns None if obj is not defined in a sourcefile.
94 Returns None if obj is not defined in a sourcefile.
95 """
95 """
96 ofile = find_file(obj)
96 ofile = find_file(obj)
97 # run contents of file through pager starting at line where the object
97 # run contents of file through pager starting at line where the object
98 # is defined, as long as the file isn't binary and is actually on the
98 # is defined, as long as the file isn't binary and is actually on the
99 # filesystem.
99 # filesystem.
100 if ofile is None:
100 if ofile is None:
101 return None
101 return None
102 elif ofile.endswith(('.so', '.dll', '.pyd')):
102 elif ofile.endswith(('.so', '.dll', '.pyd')):
103 return None
103 return None
104 elif not os.path.isfile(ofile):
104 elif not os.path.isfile(ofile):
105 return None
105 return None
106 else:
106 else:
107 # Print only text files, not extension binaries. Note that
107 # Print only text files, not extension binaries. Note that
108 # getsourcelines returns lineno with 1-offset and page() uses
108 # getsourcelines returns lineno with 1-offset and page() uses
109 # 0-offset, so we must adjust.
109 # 0-offset, so we must adjust.
110 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
110 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
111 encoding, lines = openpy.detect_encoding(buffer.readline)
111 encoding, lines = openpy.detect_encoding(buffer.readline)
112 return encoding
112 return encoding
113
113
114 def getdoc(obj):
114 def getdoc(obj):
115 """Stable wrapper around inspect.getdoc.
115 """Stable wrapper around inspect.getdoc.
116
116
117 This can't crash because of attribute problems.
117 This can't crash because of attribute problems.
118
118
119 It also attempts to call a getdoc() method on the given object. This
119 It also attempts to call a getdoc() method on the given object. This
120 allows objects which provide their docstrings via non-standard mechanisms
120 allows objects which provide their docstrings via non-standard mechanisms
121 (like Pyro proxies) to still be inspected by ipython's ? system.
121 (like Pyro proxies) to still be inspected by ipython's ? system.
122 """
122 """
123 # Allow objects to offer customized documentation via a getdoc method:
123 # Allow objects to offer customized documentation via a getdoc method:
124 try:
124 try:
125 ds = obj.getdoc()
125 ds = obj.getdoc()
126 except Exception:
126 except Exception:
127 pass
127 pass
128 else:
128 else:
129 # if we get extra info, we add it to the normal docstring.
129 # if we get extra info, we add it to the normal docstring.
130 if isinstance(ds, string_types):
130 if isinstance(ds, string_types):
131 return inspect.cleandoc(ds)
131 return inspect.cleandoc(ds)
132 try:
132 try:
133 docstr = inspect.getdoc(obj)
133 docstr = inspect.getdoc(obj)
134 encoding = get_encoding(obj)
134 encoding = get_encoding(obj)
135 return py3compat.cast_unicode(docstr, encoding=encoding)
135 return py3compat.cast_unicode(docstr, encoding=encoding)
136 except Exception:
136 except Exception:
137 # Harden against an inspect failure, which can occur with
137 # Harden against an inspect failure, which can occur with
138 # extensions modules.
138 # extensions modules.
139 raise
139 raise
140 return None
140 return None
141
141
142
142
143 def getsource(obj, oname=''):
143 def getsource(obj, oname=''):
144 """Wrapper around inspect.getsource.
144 """Wrapper around inspect.getsource.
145
145
146 This can be modified by other projects to provide customized source
146 This can be modified by other projects to provide customized source
147 extraction.
147 extraction.
148
148
149 Parameters
149 Parameters
150 ----------
150 ----------
151 obj : object
151 obj : object
152 an object whose source code we will attempt to extract
152 an object whose source code we will attempt to extract
153 oname : str
153 oname : str
154 (optional) a name under which the object is known
154 (optional) a name under which the object is known
155
155
156 Returns
156 Returns
157 -------
157 -------
158 src : unicode or None
158 src : unicode or None
159
159
160 """
160 """
161
161
162 if isinstance(obj, property):
162 if isinstance(obj, property):
163 sources = []
163 sources = []
164 for attrname in ['fget', 'fset', 'fdel']:
164 for attrname in ['fget', 'fset', 'fdel']:
165 fn = getattr(obj, attrname)
165 fn = getattr(obj, attrname)
166 if fn is not None:
166 if fn is not None:
167 encoding = get_encoding(fn)
167 encoding = get_encoding(fn)
168 oname_prefix = ('%s.' % oname) if oname else ''
168 oname_prefix = ('%s.' % oname) if oname else ''
169 sources.append(cast_unicode(
169 sources.append(cast_unicode(
170 ''.join(('# ', oname_prefix, attrname)),
170 ''.join(('# ', oname_prefix, attrname)),
171 encoding=encoding))
171 encoding=encoding))
172 if inspect.isfunction(fn):
172 if inspect.isfunction(fn):
173 sources.append(dedent(getsource(fn)))
173 sources.append(dedent(getsource(fn)))
174 else:
174 else:
175 # Default str/repr only prints function name,
175 # Default str/repr only prints function name,
176 # pretty.pretty prints module name too.
176 # pretty.pretty prints module name too.
177 sources.append(cast_unicode(
177 sources.append(cast_unicode(
178 '%s%s = %s\n' % (
178 '%s%s = %s\n' % (
179 oname_prefix, attrname, pretty(fn)),
179 oname_prefix, attrname, pretty(fn)),
180 encoding=encoding))
180 encoding=encoding))
181 if sources:
181 if sources:
182 return '\n'.join(sources)
182 return '\n'.join(sources)
183 else:
183 else:
184 return None
184 return None
185
185
186 else:
186 else:
187 # Get source for non-property objects.
187 # Get source for non-property objects.
188
188
189 obj = _get_wrapped(obj)
189 obj = _get_wrapped(obj)
190
190
191 try:
191 try:
192 src = inspect.getsource(obj)
192 src = inspect.getsource(obj)
193 except TypeError:
193 except TypeError:
194 # The object itself provided no meaningful source, try looking for
194 # The object itself provided no meaningful source, try looking for
195 # its class definition instead.
195 # its class definition instead.
196 if hasattr(obj, '__class__'):
196 if hasattr(obj, '__class__'):
197 try:
197 try:
198 src = inspect.getsource(obj.__class__)
198 src = inspect.getsource(obj.__class__)
199 except TypeError:
199 except TypeError:
200 return None
200 return None
201
201
202 encoding = get_encoding(obj)
202 encoding = get_encoding(obj)
203 return cast_unicode(src, encoding=encoding)
203 return cast_unicode(src, encoding=encoding)
204
204
205
205
206 def is_simple_callable(obj):
206 def is_simple_callable(obj):
207 """True if obj is a function ()"""
207 """True if obj is a function ()"""
208 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
208 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
209 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
209 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
210
210
211
211
212 def getargspec(obj):
212 def getargspec(obj):
213 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
213 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
214 :func:inspect.getargspec` on Python 2.
214 :func:inspect.getargspec` on Python 2.
215
215
216 In addition to functions and methods, this can also handle objects with a
216 In addition to functions and methods, this can also handle objects with a
217 ``__call__`` attribute.
217 ``__call__`` attribute.
218 """
218 """
219 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
219 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
220 obj = obj.__call__
220 obj = obj.__call__
221
221
222 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
222 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
223
223
224
224
225 def format_argspec(argspec):
225 def format_argspec(argspec):
226 """Format argspect, convenience wrapper around inspect's.
226 """Format argspect, convenience wrapper around inspect's.
227
227
228 This takes a dict instead of ordered arguments and calls
228 This takes a dict instead of ordered arguments and calls
229 inspect.format_argspec with the arguments in the necessary order.
229 inspect.format_argspec with the arguments in the necessary order.
230 """
230 """
231 return inspect.formatargspec(argspec['args'], argspec['varargs'],
231 return inspect.formatargspec(argspec['args'], argspec['varargs'],
232 argspec['varkw'], argspec['defaults'])
232 argspec['varkw'], argspec['defaults'])
233
233
234
234
235 def call_tip(oinfo, format_call=True):
235 def call_tip(oinfo, format_call=True):
236 """Extract call tip data from an oinfo dict.
236 """Extract call tip data from an oinfo dict.
237
237
238 Parameters
238 Parameters
239 ----------
239 ----------
240 oinfo : dict
240 oinfo : dict
241
241
242 format_call : bool, optional
242 format_call : bool, optional
243 If True, the call line is formatted and returned as a string. If not, a
243 If True, the call line is formatted and returned as a string. If not, a
244 tuple of (name, argspec) is returned.
244 tuple of (name, argspec) is returned.
245
245
246 Returns
246 Returns
247 -------
247 -------
248 call_info : None, str or (str, dict) tuple.
248 call_info : None, str or (str, dict) tuple.
249 When format_call is True, the whole call information is formattted as a
249 When format_call is True, the whole call information is formattted as a
250 single string. Otherwise, the object's name and its argspec dict are
250 single string. Otherwise, the object's name and its argspec dict are
251 returned. If no call information is available, None is returned.
251 returned. If no call information is available, None is returned.
252
252
253 docstring : str or None
253 docstring : str or None
254 The most relevant docstring for calling purposes is returned, if
254 The most relevant docstring for calling purposes is returned, if
255 available. The priority is: call docstring for callable instances, then
255 available. The priority is: call docstring for callable instances, then
256 constructor docstring for classes, then main object's docstring otherwise
256 constructor docstring for classes, then main object's docstring otherwise
257 (regular functions).
257 (regular functions).
258 """
258 """
259 # Get call definition
259 # Get call definition
260 argspec = oinfo.get('argspec')
260 argspec = oinfo.get('argspec')
261 if argspec is None:
261 if argspec is None:
262 call_line = None
262 call_line = None
263 else:
263 else:
264 # Callable objects will have 'self' as their first argument, prune
264 # Callable objects will have 'self' as their first argument, prune
265 # it out if it's there for clarity (since users do *not* pass an
265 # it out if it's there for clarity (since users do *not* pass an
266 # extra first argument explicitly).
266 # extra first argument explicitly).
267 try:
267 try:
268 has_self = argspec['args'][0] == 'self'
268 has_self = argspec['args'][0] == 'self'
269 except (KeyError, IndexError):
269 except (KeyError, IndexError):
270 pass
270 pass
271 else:
271 else:
272 if has_self:
272 if has_self:
273 argspec['args'] = argspec['args'][1:]
273 argspec['args'] = argspec['args'][1:]
274
274
275 call_line = oinfo['name']+format_argspec(argspec)
275 call_line = oinfo['name']+format_argspec(argspec)
276
276
277 # Now get docstring.
277 # Now get docstring.
278 # The priority is: call docstring, constructor docstring, main one.
278 # The priority is: call docstring, constructor docstring, main one.
279 doc = oinfo.get('call_docstring')
279 doc = oinfo.get('call_docstring')
280 if doc is None:
280 if doc is None:
281 doc = oinfo.get('init_docstring')
281 doc = oinfo.get('init_docstring')
282 if doc is None:
282 if doc is None:
283 doc = oinfo.get('docstring','')
283 doc = oinfo.get('docstring','')
284
284
285 return call_line, doc
285 return call_line, doc
286
286
287
287
288 def _get_wrapped(obj):
288 def _get_wrapped(obj):
289 """Get the original object if wrapped in one or more @decorators
289 """Get the original object if wrapped in one or more @decorators
290
290
291 Some objects automatically construct similar objects on any unrecognised
291 Some objects automatically construct similar objects on any unrecognised
292 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
292 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
293 this will arbitrarily cut off after 100 levels of obj.__wrapped__
293 this will arbitrarily cut off after 100 levels of obj.__wrapped__
294 attribute access. --TK, Jan 2016
294 attribute access. --TK, Jan 2016
295 """
295 """
296 orig_obj = obj
296 orig_obj = obj
297 i = 0
297 i = 0
298 while safe_hasattr(obj, '__wrapped__'):
298 while safe_hasattr(obj, '__wrapped__'):
299 obj = obj.__wrapped__
299 obj = obj.__wrapped__
300 i += 1
300 i += 1
301 if i > 100:
301 if i > 100:
302 # __wrapped__ is probably a lie, so return the thing we started with
302 # __wrapped__ is probably a lie, so return the thing we started with
303 return orig_obj
303 return orig_obj
304 return obj
304 return obj
305
305
306 def find_file(obj):
306 def find_file(obj):
307 """Find the absolute path to the file where an object was defined.
307 """Find the absolute path to the file where an object was defined.
308
308
309 This is essentially a robust wrapper around `inspect.getabsfile`.
309 This is essentially a robust wrapper around `inspect.getabsfile`.
310
310
311 Returns None if no file can be found.
311 Returns None if no file can be found.
312
312
313 Parameters
313 Parameters
314 ----------
314 ----------
315 obj : any Python object
315 obj : any Python object
316
316
317 Returns
317 Returns
318 -------
318 -------
319 fname : str
319 fname : str
320 The absolute path to the file where the object was defined.
320 The absolute path to the file where the object was defined.
321 """
321 """
322 obj = _get_wrapped(obj)
322 obj = _get_wrapped(obj)
323
323
324 fname = None
324 fname = None
325 try:
325 try:
326 fname = inspect.getabsfile(obj)
326 fname = inspect.getabsfile(obj)
327 except TypeError:
327 except TypeError:
328 # For an instance, the file that matters is where its class was
328 # For an instance, the file that matters is where its class was
329 # declared.
329 # declared.
330 if hasattr(obj, '__class__'):
330 if hasattr(obj, '__class__'):
331 try:
331 try:
332 fname = inspect.getabsfile(obj.__class__)
332 fname = inspect.getabsfile(obj.__class__)
333 except TypeError:
333 except TypeError:
334 # Can happen for builtins
334 # Can happen for builtins
335 pass
335 pass
336 except:
336 except:
337 pass
337 pass
338 return cast_unicode(fname)
338 return cast_unicode(fname)
339
339
340
340
341 def find_source_lines(obj):
341 def find_source_lines(obj):
342 """Find the line number in a file where an object was defined.
342 """Find the line number in a file where an object was defined.
343
343
344 This is essentially a robust wrapper around `inspect.getsourcelines`.
344 This is essentially a robust wrapper around `inspect.getsourcelines`.
345
345
346 Returns None if no file can be found.
346 Returns None if no file can be found.
347
347
348 Parameters
348 Parameters
349 ----------
349 ----------
350 obj : any Python object
350 obj : any Python object
351
351
352 Returns
352 Returns
353 -------
353 -------
354 lineno : int
354 lineno : int
355 The line number where the object definition starts.
355 The line number where the object definition starts.
356 """
356 """
357 obj = _get_wrapped(obj)
357 obj = _get_wrapped(obj)
358
358
359 try:
359 try:
360 try:
360 try:
361 lineno = inspect.getsourcelines(obj)[1]
361 lineno = inspect.getsourcelines(obj)[1]
362 except TypeError:
362 except TypeError:
363 # For instances, try the class object like getsource() does
363 # For instances, try the class object like getsource() does
364 if hasattr(obj, '__class__'):
364 if hasattr(obj, '__class__'):
365 lineno = inspect.getsourcelines(obj.__class__)[1]
365 lineno = inspect.getsourcelines(obj.__class__)[1]
366 else:
366 else:
367 lineno = None
367 lineno = None
368 except:
368 except:
369 return None
369 return None
370
370
371 return lineno
371 return lineno
372
372
373 class Inspector(Colorable):
373 class Inspector(Colorable):
374
374
375 def __init__(self, color_table=InspectColors,
375 def __init__(self, color_table=InspectColors,
376 code_color_table=PyColorize.ANSICodeColors,
376 code_color_table=PyColorize.ANSICodeColors,
377 scheme='NoColor',
377 scheme='NoColor',
378 str_detail_level=0,
378 str_detail_level=0,
379 parent=None, config=None):
379 parent=None, config=None):
380 super(Inspector, self).__init__(parent=parent, config=config)
380 super(Inspector, self).__init__(parent=parent, config=config)
381 self.color_table = color_table
381 self.color_table = color_table
382 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
382 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
383 self.format = self.parser.format
383 self.format = self.parser.format
384 self.str_detail_level = str_detail_level
384 self.str_detail_level = str_detail_level
385 self.set_active_scheme(scheme)
385 self.set_active_scheme(scheme)
386
386
387 def _getdef(self,obj,oname=''):
387 def _getdef(self,obj,oname=''):
388 """Return the call signature for any callable object.
388 """Return the call signature for any callable object.
389
389
390 If any exception is generated, None is returned instead and the
390 If any exception is generated, None is returned instead and the
391 exception is suppressed."""
391 exception is suppressed."""
392 try:
392 try:
393 hdef = oname + str(signature(obj))
393 hdef = oname + str(signature(obj))
394 return cast_unicode(hdef)
394 return cast_unicode(hdef)
395 except:
395 except:
396 return None
396 return None
397
397
398 def __head(self,h):
398 def __head(self,h):
399 """Return a header string with proper colors."""
399 """Return a header string with proper colors."""
400 return '%s%s%s' % (self.color_table.active_colors.header,h,
400 return '%s%s%s' % (self.color_table.active_colors.header,h,
401 self.color_table.active_colors.normal)
401 self.color_table.active_colors.normal)
402
402
403 def set_active_scheme(self, scheme):
403 def set_active_scheme(self, scheme):
404 self.color_table.set_active_scheme(scheme)
404 self.color_table.set_active_scheme(scheme)
405 self.parser.color_table.set_active_scheme(scheme)
405 self.parser.color_table.set_active_scheme(scheme)
406
406
407 def noinfo(self, msg, oname):
407 def noinfo(self, msg, oname):
408 """Generic message when no information is found."""
408 """Generic message when no information is found."""
409 print('No %s found' % msg, end=' ')
409 print('No %s found' % msg, end=' ')
410 if oname:
410 if oname:
411 print('for %s' % oname)
411 print('for %s' % oname)
412 else:
412 else:
413 print()
413 print()
414
414
415 def pdef(self, obj, oname=''):
415 def pdef(self, obj, oname=''):
416 """Print the call signature for any callable object.
416 """Print the call signature for any callable object.
417
417
418 If the object is a class, print the constructor information."""
418 If the object is a class, print the constructor information."""
419
419
420 if not callable(obj):
420 if not callable(obj):
421 print('Object is not callable.')
421 print('Object is not callable.')
422 return
422 return
423
423
424 header = ''
424 header = ''
425
425
426 if inspect.isclass(obj):
426 if inspect.isclass(obj):
427 header = self.__head('Class constructor information:\n')
427 header = self.__head('Class constructor information:\n')
428 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
428 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
429 obj = obj.__call__
429 obj = obj.__call__
430
430
431 output = self._getdef(obj,oname)
431 output = self._getdef(obj,oname)
432 if output is None:
432 if output is None:
433 self.noinfo('definition header',oname)
433 self.noinfo('definition header',oname)
434 else:
434 else:
435 print(header,self.format(output), end=' ')
435 print(header,self.format(output), end=' ')
436
436
437 # In Python 3, all classes are new-style, so they all have __init__.
437 # In Python 3, all classes are new-style, so they all have __init__.
438 @skip_doctest
438 @skip_doctest
439 def pdoc(self, obj, oname='', formatter=None):
439 def pdoc(self, obj, oname='', formatter=None):
440 """Print the docstring for any object.
440 """Print the docstring for any object.
441
441
442 Optional:
442 Optional:
443 -formatter: a function to run the docstring through for specially
443 -formatter: a function to run the docstring through for specially
444 formatted docstrings.
444 formatted docstrings.
445
445
446 Examples
446 Examples
447 --------
447 --------
448
448
449 In [1]: class NoInit:
449 In [1]: class NoInit:
450 ...: pass
450 ...: pass
451
451
452 In [2]: class NoDoc:
452 In [2]: class NoDoc:
453 ...: def __init__(self):
453 ...: def __init__(self):
454 ...: pass
454 ...: pass
455
455
456 In [3]: %pdoc NoDoc
456 In [3]: %pdoc NoDoc
457 No documentation found for NoDoc
457 No documentation found for NoDoc
458
458
459 In [4]: %pdoc NoInit
459 In [4]: %pdoc NoInit
460 No documentation found for NoInit
460 No documentation found for NoInit
461
461
462 In [5]: obj = NoInit()
462 In [5]: obj = NoInit()
463
463
464 In [6]: %pdoc obj
464 In [6]: %pdoc obj
465 No documentation found for obj
465 No documentation found for obj
466
466
467 In [5]: obj2 = NoDoc()
467 In [5]: obj2 = NoDoc()
468
468
469 In [6]: %pdoc obj2
469 In [6]: %pdoc obj2
470 No documentation found for obj2
470 No documentation found for obj2
471 """
471 """
472
472
473 head = self.__head # For convenience
473 head = self.__head # For convenience
474 lines = []
474 lines = []
475 ds = getdoc(obj)
475 ds = getdoc(obj)
476 if formatter:
476 if formatter:
477 ds = formatter(ds).get('plain/text', ds)
477 ds = formatter(ds).get('plain/text', ds)
478 if ds:
478 if ds:
479 lines.append(head("Class docstring:"))
479 lines.append(head("Class docstring:"))
480 lines.append(indent(ds))
480 lines.append(indent(ds))
481 if inspect.isclass(obj) and hasattr(obj, '__init__'):
481 if inspect.isclass(obj) and hasattr(obj, '__init__'):
482 init_ds = getdoc(obj.__init__)
482 init_ds = getdoc(obj.__init__)
483 if init_ds is not None:
483 if init_ds is not None:
484 lines.append(head("Init docstring:"))
484 lines.append(head("Init docstring:"))
485 lines.append(indent(init_ds))
485 lines.append(indent(init_ds))
486 elif hasattr(obj,'__call__'):
486 elif hasattr(obj,'__call__'):
487 call_ds = getdoc(obj.__call__)
487 call_ds = getdoc(obj.__call__)
488 if call_ds:
488 if call_ds:
489 lines.append(head("Call docstring:"))
489 lines.append(head("Call docstring:"))
490 lines.append(indent(call_ds))
490 lines.append(indent(call_ds))
491
491
492 if not lines:
492 if not lines:
493 self.noinfo('documentation',oname)
493 self.noinfo('documentation',oname)
494 else:
494 else:
495 page.page('\n'.join(lines))
495 page.page('\n'.join(lines))
496
496
497 def psource(self, obj, oname=''):
497 def psource(self, obj, oname=''):
498 """Print the source code for an object."""
498 """Print the source code for an object."""
499
499
500 # Flush the source cache because inspect can return out-of-date source
500 # Flush the source cache because inspect can return out-of-date source
501 linecache.checkcache()
501 linecache.checkcache()
502 try:
502 try:
503 src = getsource(obj, oname=oname)
503 src = getsource(obj, oname=oname)
504 except Exception:
504 except Exception:
505 src = None
505 src = None
506
506
507 if src is None:
507 if src is None:
508 self.noinfo('source', oname)
508 self.noinfo('source', oname)
509 else:
509 else:
510 page.page(self.format(src))
510 page.page(self.format(src))
511
511
512 def pfile(self, obj, oname=''):
512 def pfile(self, obj, oname=''):
513 """Show the whole file where an object was defined."""
513 """Show the whole file where an object was defined."""
514
514
515 lineno = find_source_lines(obj)
515 lineno = find_source_lines(obj)
516 if lineno is None:
516 if lineno is None:
517 self.noinfo('file', oname)
517 self.noinfo('file', oname)
518 return
518 return
519
519
520 ofile = find_file(obj)
520 ofile = find_file(obj)
521 # run contents of file through pager starting at line where the object
521 # run contents of file through pager starting at line where the object
522 # is defined, as long as the file isn't binary and is actually on the
522 # is defined, as long as the file isn't binary and is actually on the
523 # filesystem.
523 # filesystem.
524 if ofile.endswith(('.so', '.dll', '.pyd')):
524 if ofile.endswith(('.so', '.dll', '.pyd')):
525 print('File %r is binary, not printing.' % ofile)
525 print('File %r is binary, not printing.' % ofile)
526 elif not os.path.isfile(ofile):
526 elif not os.path.isfile(ofile):
527 print('File %r does not exist, not printing.' % ofile)
527 print('File %r does not exist, not printing.' % ofile)
528 else:
528 else:
529 # Print only text files, not extension binaries. Note that
529 # Print only text files, not extension binaries. Note that
530 # getsourcelines returns lineno with 1-offset and page() uses
530 # getsourcelines returns lineno with 1-offset and page() uses
531 # 0-offset, so we must adjust.
531 # 0-offset, so we must adjust.
532 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
532 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
533
533
534 def _format_fields(self, fields, title_width=0):
534 def _format_fields(self, fields, title_width=0):
535 """Formats a list of fields for display.
535 """Formats a list of fields for display.
536
536
537 Parameters
537 Parameters
538 ----------
538 ----------
539 fields : list
539 fields : list
540 A list of 2-tuples: (field_title, field_content)
540 A list of 2-tuples: (field_title, field_content)
541 title_width : int
541 title_width : int
542 How many characters to pad titles to. Default to longest title.
542 How many characters to pad titles to. Default to longest title.
543 """
543 """
544 out = []
544 out = []
545 header = self.__head
545 header = self.__head
546 if title_width == 0:
546 if title_width == 0:
547 title_width = max(len(title) + 2 for title, _ in fields)
547 title_width = max(len(title) + 2 for title, _ in fields)
548 for title, content in fields:
548 for title, content in fields:
549 if len(content.splitlines()) > 1:
549 if len(content.splitlines()) > 1:
550 title = header(title + ':') + '\n'
550 title = header(title + ':') + '\n'
551 else:
551 else:
552 title = header((title + ':').ljust(title_width))
552 title = header((title + ':').ljust(title_width))
553 out.append(cast_unicode(title) + cast_unicode(content))
553 out.append(cast_unicode(title) + cast_unicode(content))
554 return "\n".join(out)
554 return "\n".join(out)
555
555
556 def _mime_format(self, text, formatter=None):
556 def _mime_format(self, text, formatter=None):
557 """Return a mime bundle representation of the input text.
557 """Return a mime bundle representation of the input text.
558
558
559 - if `formatter` is None, the returned mime bundle has
559 - if `formatter` is None, the returned mime bundle has
560 a `text/plain` field, with the input text.
560 a `text/plain` field, with the input text.
561 a `text/html` field with a `<pre>` tag containing the input text.
561 a `text/html` field with a `<pre>` tag containing the input text.
562
562
563 - if `formatter` is not None, it must be a callable transforming the
563 - if `formatter` is not None, it must be a callable transforming the
564 input text into a mime bundle. Default values for `text/plain` and
564 input text into a mime bundle. Default values for `text/plain` and
565 `text/html` representations are the ones described above.
565 `text/html` representations are the ones described above.
566
566
567 Note:
567 Note:
568
568
569 Formatters returning strings are supported but this behavior is deprecated.
569 Formatters returning strings are supported but this behavior is deprecated.
570
570
571 """
571 """
572 text = cast_unicode(text)
572 text = cast_unicode(text)
573 defaults = {
573 defaults = {
574 'text/plain': text,
574 'text/plain': text,
575 'text/html': '<pre>' + text + '</pre>'
575 'text/html': '<pre>' + text + '</pre>'
576 }
576 }
577
577
578 if formatter is None:
578 if formatter is None:
579 return defaults
579 return defaults
580 else:
580 else:
581 formatted = formatter(text)
581 formatted = formatter(text)
582
582
583 if not isinstance(formatted, dict):
583 if not isinstance(formatted, dict):
584 # Handle the deprecated behavior of a formatter returning
584 # Handle the deprecated behavior of a formatter returning
585 # a string instead of a mime bundle.
585 # a string instead of a mime bundle.
586 return {
586 return {
587 'text/plain': formatted,
587 'text/plain': formatted,
588 'text/html': '<pre>' + formatted + '</pre>'
588 'text/html': '<pre>' + formatted + '</pre>'
589 }
589 }
590
590
591 else:
591 else:
592 return dict(defaults, **formatted)
592 return dict(defaults, **formatted)
593
593
594
594
595 def format_mime(self, bundle):
595 def format_mime(self, bundle):
596
596
597 text_plain = bundle['text/plain']
597 text_plain = bundle['text/plain']
598
598
599 text = ''
599 text = ''
600 heads, bodies = list(zip(*text_plain))
600 heads, bodies = list(zip(*text_plain))
601 _len = max(len(h) for h in heads)
601 _len = max(len(h) for h in heads)
602
602
603 for head, body in zip(heads, bodies):
603 for head, body in zip(heads, bodies):
604 body = body.strip('\n')
604 body = body.strip('\n')
605 delim = '\n' if '\n' in body else ' '
605 delim = '\n' if '\n' in body else ' '
606 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
606 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
607
607
608 bundle['text/plain'] = text
608 bundle['text/plain'] = text
609 return bundle
609 return bundle
610
610
611 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
611 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
612 """Retrieve an info dict and format it."""
612 """Retrieve an info dict and format it."""
613
613
614 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
614 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
615
615
616 _mime = {
616 _mime = {
617 'text/plain': [],
617 'text/plain': [],
618 'text/html': '',
618 'text/html': '',
619 }
619 }
620
620
621 def append_field(bundle, title, key, formatter=None):
621 def append_field(bundle, title, key, formatter=None):
622 field = info[key]
622 field = info[key]
623 if field is not None:
623 if field is not None:
624 formatted_field = self._mime_format(field, formatter)
624 formatted_field = self._mime_format(field, formatter)
625 bundle['text/plain'].append((title, formatted_field['text/plain']))
625 bundle['text/plain'].append((title, formatted_field['text/plain']))
626 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
626 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
627
627
628 def code_formatter(text):
628 def code_formatter(text):
629 return {
629 return {
630 'text/plain': self.format(text),
630 'text/plain': self.format(text),
631 'text/html': pylight(text)
631 'text/html': pylight(text)
632 }
632 }
633
633
634 if info['isalias']:
634 if info['isalias']:
635 append_field(_mime, 'Repr', 'string_form')
635 append_field(_mime, 'Repr', 'string_form')
636
636
637 elif info['ismagic']:
637 elif info['ismagic']:
638 if detail_level > 0:
638 if detail_level > 0:
639 append_field(_mime, 'Source', 'source', code_formatter)
639 append_field(_mime, 'Source', 'source', code_formatter)
640 else:
640 else:
641 append_field(_mime, 'Docstring', 'docstring', formatter)
641 append_field(_mime, 'Docstring', 'docstring', formatter)
642 append_field(_mime, 'File', 'file')
642 append_field(_mime, 'File', 'file')
643
643
644 elif info['isclass'] or is_simple_callable(obj):
644 elif info['isclass'] or is_simple_callable(obj):
645 # Functions, methods, classes
645 # Functions, methods, classes
646 append_field(_mime, 'Signature', 'definition', code_formatter)
646 append_field(_mime, 'Signature', 'definition', code_formatter)
647 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
647 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
648 if detail_level > 0:
648 if detail_level > 0:
649 append_field(_mime, 'Source', 'source', code_formatter)
649 append_field(_mime, 'Source', 'source', code_formatter)
650 else:
650 else:
651 append_field(_mime, 'Docstring', 'docstring', formatter)
651 append_field(_mime, 'Docstring', 'docstring', formatter)
652 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
652 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
653
653
654 append_field(_mime, 'File', 'file')
654 append_field(_mime, 'File', 'file')
655 append_field(_mime, 'Type', 'type_name')
655 append_field(_mime, 'Type', 'type_name')
656
656
657 else:
657 else:
658 # General Python objects
658 # General Python objects
659 append_field(_mime, 'Signature', 'definition', code_formatter)
659 append_field(_mime, 'Signature', 'definition', code_formatter)
660 append_field(_mime, 'Call signature', 'call_def', code_formatter)
660 append_field(_mime, 'Call signature', 'call_def', code_formatter)
661
661
662 append_field(_mime, 'Type', 'type_name')
662 append_field(_mime, 'Type', 'type_name')
663
663
664 # Base class for old-style instances
664 # Base class for old-style instances
665 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
665 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
666 append_field(_mime, 'Base Class', 'base_class')
666 append_field(_mime, 'Base Class', 'base_class')
667
667
668 append_field(_mime, 'String form', 'string_form')
668 append_field(_mime, 'String form', 'string_form')
669
669
670 # Namespace
670 # Namespace
671 if info['namespace'] != 'Interactive':
671 if info['namespace'] != 'Interactive':
672 append_field(_mime, 'Namespace', 'namespace')
672 append_field(_mime, 'Namespace', 'namespace')
673
673
674 append_field(_mime, 'Length', 'length')
674 append_field(_mime, 'Length', 'length')
675 append_field(_mime, 'File', 'file')
675 append_field(_mime, 'File', 'file')
676
676
677 # Source or docstring, depending on detail level and whether
677 # Source or docstring, depending on detail level and whether
678 # source found.
678 # source found.
679 if detail_level > 0:
679 if detail_level > 0:
680 append_field(_mime, 'Source', 'source', code_formatter)
680 append_field(_mime, 'Source', 'source', code_formatter)
681 else:
681 else:
682 append_field(_mime, 'Docstring', 'docstring', formatter)
682 append_field(_mime, 'Docstring', 'docstring', formatter)
683
683
684 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
684 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
685 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
685 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
686 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
686 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
687
687
688
688
689 return self.format_mime(_mime)
689 return self.format_mime(_mime)
690
690
691 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
691 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
692 """Show detailed information about an object.
692 """Show detailed information about an object.
693
693
694 Optional arguments:
694 Optional arguments:
695
695
696 - oname: name of the variable pointing to the object.
696 - oname: name of the variable pointing to the object.
697
697
698 - formatter: callable (optional)
698 - formatter: callable (optional)
699 A special formatter for docstrings.
699 A special formatter for docstrings.
700
700
701 The formatter is a callable that takes a string as an input
701 The formatter is a callable that takes a string as an input
702 and returns either a formatted string or a mime type bundle
702 and returns either a formatted string or a mime type bundle
703 in the form of a dictionnary.
703 in the form of a dictionnary.
704
704
705 Although the support of custom formatter returning a string
705 Although the support of custom formatter returning a string
706 instead of a mime type bundle is deprecated.
706 instead of a mime type bundle is deprecated.
707
707
708 - info: a structure with some information fields which may have been
708 - info: a structure with some information fields which may have been
709 precomputed already.
709 precomputed already.
710
710
711 - detail_level: if set to 1, more information is given.
711 - detail_level: if set to 1, more information is given.
712 """
712 """
713 info = self._get_info(obj, oname, formatter, info, detail_level)
713 info = self._get_info(obj, oname, formatter, info, detail_level)
714 if not enable_html_pager:
714 if not enable_html_pager:
715 del info['text/html']
715 del info['text/html']
716 page.page(info)
716 page.page(info)
717
717
718 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
718 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
719 """DEPRECATED. Compute a dict with detailed information about an object.
719 """DEPRECATED. Compute a dict with detailed information about an object.
720 """
720 """
721 if formatter is not None:
721 if formatter is not None:
722 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
722 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
723 'is deprecated as of IPython 5.0 and will have no effects.',
723 'is deprecated as of IPython 5.0 and will have no effects.',
724 DeprecationWarning, stacklevel=2)
724 DeprecationWarning, stacklevel=2)
725 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
725 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
726
726
727 def _info(self, obj, oname='', info=None, detail_level=0):
727 def _info(self, obj, oname='', info=None, detail_level=0):
728 """Compute a dict with detailed information about an object.
728 """Compute a dict with detailed information about an object.
729
729
730 Optional arguments:
730 Optional arguments:
731
731
732 - oname: name of the variable pointing to the object.
732 - oname: name of the variable pointing to the object.
733
733
734 - info: a structure with some information fields which may have been
734 - info: a structure with some information fields which may have been
735 precomputed already.
735 precomputed already.
736
736
737 - detail_level: if set to 1, more information is given.
737 - detail_level: if set to 1, more information is given.
738 """
738 """
739
739
740 obj_type = type(obj)
740 obj_type = type(obj)
741
741
742 if info is None:
742 if info is None:
743 ismagic = 0
743 ismagic = 0
744 isalias = 0
744 isalias = 0
745 ospace = ''
745 ospace = ''
746 else:
746 else:
747 ismagic = info.ismagic
747 ismagic = info.ismagic
748 isalias = info.isalias
748 isalias = info.isalias
749 ospace = info.namespace
749 ospace = info.namespace
750
750
751 # Get docstring, special-casing aliases:
751 # Get docstring, special-casing aliases:
752 if isalias:
752 if isalias:
753 if not callable(obj):
753 if not callable(obj):
754 try:
754 try:
755 ds = "Alias to the system command:\n %s" % obj[1]
755 ds = "Alias to the system command:\n %s" % obj[1]
756 except:
756 except:
757 ds = "Alias: " + str(obj)
757 ds = "Alias: " + str(obj)
758 else:
758 else:
759 ds = "Alias to " + str(obj)
759 ds = "Alias to " + str(obj)
760 if obj.__doc__:
760 if obj.__doc__:
761 ds += "\nDocstring:\n" + obj.__doc__
761 ds += "\nDocstring:\n" + obj.__doc__
762 else:
762 else:
763 ds = getdoc(obj)
763 ds = getdoc(obj)
764 if ds is None:
764 if ds is None:
765 ds = '<no docstring>'
765 ds = '<no docstring>'
766
766
767 # store output in a dict, we initialize it here and fill it as we go
767 # store output in a dict, we initialize it here and fill it as we go
768 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
768 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
769
769
770 string_max = 200 # max size of strings to show (snipped if longer)
770 string_max = 200 # max size of strings to show (snipped if longer)
771 shalf = int((string_max - 5) / 2)
771 shalf = int((string_max - 5) / 2)
772
772
773 if ismagic:
773 if ismagic:
774 obj_type_name = 'Magic function'
774 obj_type_name = 'Magic function'
775 elif isalias:
775 elif isalias:
776 obj_type_name = 'System alias'
776 obj_type_name = 'System alias'
777 else:
777 else:
778 obj_type_name = obj_type.__name__
778 obj_type_name = obj_type.__name__
779 out['type_name'] = obj_type_name
779 out['type_name'] = obj_type_name
780
780
781 try:
781 try:
782 bclass = obj.__class__
782 bclass = obj.__class__
783 out['base_class'] = str(bclass)
783 out['base_class'] = str(bclass)
784 except: pass
784 except: pass
785
785
786 # String form, but snip if too long in ? form (full in ??)
786 # String form, but snip if too long in ? form (full in ??)
787 if detail_level >= self.str_detail_level:
787 if detail_level >= self.str_detail_level:
788 try:
788 try:
789 ostr = str(obj)
789 ostr = str(obj)
790 str_head = 'string_form'
790 str_head = 'string_form'
791 if not detail_level and len(ostr)>string_max:
791 if not detail_level and len(ostr)>string_max:
792 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
792 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
793 ostr = ("\n" + " " * len(str_head.expandtabs())).\
793 ostr = ("\n" + " " * len(str_head.expandtabs())).\
794 join(q.strip() for q in ostr.split("\n"))
794 join(q.strip() for q in ostr.split("\n"))
795 out[str_head] = ostr
795 out[str_head] = ostr
796 except:
796 except:
797 pass
797 pass
798
798
799 if ospace:
799 if ospace:
800 out['namespace'] = ospace
800 out['namespace'] = ospace
801
801
802 # Length (for strings and lists)
802 # Length (for strings and lists)
803 try:
803 try:
804 out['length'] = str(len(obj))
804 out['length'] = str(len(obj))
805 except: pass
805 except: pass
806
806
807 # Filename where object was defined
807 # Filename where object was defined
808 binary_file = False
808 binary_file = False
809 fname = find_file(obj)
809 fname = find_file(obj)
810 if fname is None:
810 if fname is None:
811 # if anything goes wrong, we don't want to show source, so it's as
811 # if anything goes wrong, we don't want to show source, so it's as
812 # if the file was binary
812 # if the file was binary
813 binary_file = True
813 binary_file = True
814 else:
814 else:
815 if fname.endswith(('.so', '.dll', '.pyd')):
815 if fname.endswith(('.so', '.dll', '.pyd')):
816 binary_file = True
816 binary_file = True
817 elif fname.endswith('<string>'):
817 elif fname.endswith('<string>'):
818 fname = 'Dynamically generated function. No source code available.'
818 fname = 'Dynamically generated function. No source code available.'
819 out['file'] = compress_user(fname)
819 out['file'] = compress_user(fname)
820
820
821 # Original source code for a callable, class or property.
821 # Original source code for a callable, class or property.
822 if detail_level:
822 if detail_level:
823 # Flush the source cache because inspect can return out-of-date
823 # Flush the source cache because inspect can return out-of-date
824 # source
824 # source
825 linecache.checkcache()
825 linecache.checkcache()
826 try:
826 try:
827 if isinstance(obj, property) or not binary_file:
827 if isinstance(obj, property) or not binary_file:
828 src = getsource(obj, oname)
828 src = getsource(obj, oname)
829 if src is not None:
829 if src is not None:
830 src = src.rstrip()
830 src = src.rstrip()
831 out['source'] = src
831 out['source'] = src
832
832
833 except Exception:
833 except Exception:
834 pass
834 pass
835
835
836 # Add docstring only if no source is to be shown (avoid repetitions).
836 # Add docstring only if no source is to be shown (avoid repetitions).
837 if ds and out.get('source', None) is None:
837 if ds and out.get('source', None) is None:
838 out['docstring'] = ds
838 out['docstring'] = ds
839
839
840 # Constructor docstring for classes
840 # Constructor docstring for classes
841 if inspect.isclass(obj):
841 if inspect.isclass(obj):
842 out['isclass'] = True
842 out['isclass'] = True
843
843
844 # get the init signature:
844 # get the init signature:
845 try:
845 try:
846 init_def = self._getdef(obj, oname)
846 init_def = self._getdef(obj, oname)
847 except AttributeError:
847 except AttributeError:
848 init_def = None
848 init_def = None
849
849
850 # get the __init__ docstring
850 # get the __init__ docstring
851 try:
851 try:
852 obj_init = obj.__init__
852 obj_init = obj.__init__
853 except AttributeError:
853 except AttributeError:
854 init_ds = None
854 init_ds = None
855 else:
855 else:
856 if init_def is None:
856 if init_def is None:
857 # Get signature from init if top-level sig failed.
857 # Get signature from init if top-level sig failed.
858 # Can happen for built-in types (list, etc.).
858 # Can happen for built-in types (list, etc.).
859 try:
859 try:
860 init_def = self._getdef(obj_init, oname)
860 init_def = self._getdef(obj_init, oname)
861 except AttributeError:
861 except AttributeError:
862 pass
862 pass
863 init_ds = getdoc(obj_init)
863 init_ds = getdoc(obj_init)
864 # Skip Python's auto-generated docstrings
864 # Skip Python's auto-generated docstrings
865 if init_ds == _object_init_docstring:
865 if init_ds == _object_init_docstring:
866 init_ds = None
866 init_ds = None
867
867
868 if init_def:
868 if init_def:
869 out['init_definition'] = init_def
869 out['init_definition'] = init_def
870
870
871 if init_ds:
871 if init_ds:
872 out['init_docstring'] = init_ds
872 out['init_docstring'] = init_ds
873
873
874 # and class docstring for instances:
874 # and class docstring for instances:
875 else:
875 else:
876 # reconstruct the function definition and print it:
876 # reconstruct the function definition and print it:
877 defln = self._getdef(obj, oname)
877 defln = self._getdef(obj, oname)
878 if defln:
878 if defln:
879 out['definition'] = defln
879 out['definition'] = defln
880
880
881 # First, check whether the instance docstring is identical to the
881 # First, check whether the instance docstring is identical to the
882 # class one, and print it separately if they don't coincide. In
882 # class one, and print it separately if they don't coincide. In
883 # most cases they will, but it's nice to print all the info for
883 # most cases they will, but it's nice to print all the info for
884 # objects which use instance-customized docstrings.
884 # objects which use instance-customized docstrings.
885 if ds:
885 if ds:
886 try:
886 try:
887 cls = getattr(obj,'__class__')
887 cls = getattr(obj,'__class__')
888 except:
888 except:
889 class_ds = None
889 class_ds = None
890 else:
890 else:
891 class_ds = getdoc(cls)
891 class_ds = getdoc(cls)
892 # Skip Python's auto-generated docstrings
892 # Skip Python's auto-generated docstrings
893 if class_ds in _builtin_type_docstrings:
893 if class_ds in _builtin_type_docstrings:
894 class_ds = None
894 class_ds = None
895 if class_ds and ds != class_ds:
895 if class_ds and ds != class_ds:
896 out['class_docstring'] = class_ds
896 out['class_docstring'] = class_ds
897
897
898 # Next, try to show constructor docstrings
898 # Next, try to show constructor docstrings
899 try:
899 try:
900 init_ds = getdoc(obj.__init__)
900 init_ds = getdoc(obj.__init__)
901 # Skip Python's auto-generated docstrings
901 # Skip Python's auto-generated docstrings
902 if init_ds == _object_init_docstring:
902 if init_ds == _object_init_docstring:
903 init_ds = None
903 init_ds = None
904 except AttributeError:
904 except AttributeError:
905 init_ds = None
905 init_ds = None
906 if init_ds:
906 if init_ds:
907 out['init_docstring'] = init_ds
907 out['init_docstring'] = init_ds
908
908
909 # Call form docstring for callable instances
909 # Call form docstring for callable instances
910 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
910 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
911 call_def = self._getdef(obj.__call__, oname)
911 call_def = self._getdef(obj.__call__, oname)
912 if call_def and (call_def != out.get('definition')):
912 if call_def and (call_def != out.get('definition')):
913 # it may never be the case that call def and definition differ,
913 # it may never be the case that call def and definition differ,
914 # but don't include the same signature twice
914 # but don't include the same signature twice
915 out['call_def'] = call_def
915 out['call_def'] = call_def
916 call_ds = getdoc(obj.__call__)
916 call_ds = getdoc(obj.__call__)
917 # Skip Python's auto-generated docstrings
917 # Skip Python's auto-generated docstrings
918 if call_ds == _func_call_docstring:
918 if call_ds == _func_call_docstring:
919 call_ds = None
919 call_ds = None
920 if call_ds:
920 if call_ds:
921 out['call_docstring'] = call_ds
921 out['call_docstring'] = call_ds
922
922
923 # Compute the object's argspec as a callable. The key is to decide
923 # Compute the object's argspec as a callable. The key is to decide
924 # whether to pull it from the object itself, from its __init__ or
924 # whether to pull it from the object itself, from its __init__ or
925 # from its __call__ method.
925 # from its __call__ method.
926
926
927 if inspect.isclass(obj):
927 if inspect.isclass(obj):
928 # Old-style classes need not have an __init__
928 # Old-style classes need not have an __init__
929 callable_obj = getattr(obj, "__init__", None)
929 callable_obj = getattr(obj, "__init__", None)
930 elif callable(obj):
930 elif callable(obj):
931 callable_obj = obj
931 callable_obj = obj
932 else:
932 else:
933 callable_obj = None
933 callable_obj = None
934
934
935 if callable_obj is not None:
935 if callable_obj is not None:
936 try:
936 try:
937 argspec = getargspec(callable_obj)
937 argspec = getargspec(callable_obj)
938 except (TypeError, AttributeError):
938 except (TypeError, AttributeError):
939 # For extensions/builtins we can't retrieve the argspec
939 # For extensions/builtins we can't retrieve the argspec
940 pass
940 pass
941 else:
941 else:
942 # named tuples' _asdict() method returns an OrderedDict, but we
942 # named tuples' _asdict() method returns an OrderedDict, but we
943 # we want a normal
943 # we want a normal
944 out['argspec'] = argspec_dict = dict(argspec._asdict())
944 out['argspec'] = argspec_dict = dict(argspec._asdict())
945 # We called this varkw before argspec became a named tuple.
945 # We called this varkw before argspec became a named tuple.
946 # With getfullargspec it's also called varkw.
946 # With getfullargspec it's also called varkw.
947 if 'varkw' not in argspec_dict:
947 if 'varkw' not in argspec_dict:
948 argspec_dict['varkw'] = argspec_dict.pop('keywords')
948 argspec_dict['varkw'] = argspec_dict.pop('keywords')
949
949
950 return object_info(**out)
950 return object_info(**out)
951
951
952 def psearch(self,pattern,ns_table,ns_search=[],
952 def psearch(self,pattern,ns_table,ns_search=[],
953 ignore_case=False,show_all=False):
953 ignore_case=False,show_all=False):
954 """Search namespaces with wildcards for objects.
954 """Search namespaces with wildcards for objects.
955
955
956 Arguments:
956 Arguments:
957
957
958 - pattern: string containing shell-like wildcards to use in namespace
958 - pattern: string containing shell-like wildcards to use in namespace
959 searches and optionally a type specification to narrow the search to
959 searches and optionally a type specification to narrow the search to
960 objects of that type.
960 objects of that type.
961
961
962 - ns_table: dict of name->namespaces for search.
962 - ns_table: dict of name->namespaces for search.
963
963
964 Optional arguments:
964 Optional arguments:
965
965
966 - ns_search: list of namespace names to include in search.
966 - ns_search: list of namespace names to include in search.
967
967
968 - ignore_case(False): make the search case-insensitive.
968 - ignore_case(False): make the search case-insensitive.
969
969
970 - show_all(False): show all names, including those starting with
970 - show_all(False): show all names, including those starting with
971 underscores.
971 underscores.
972 """
972 """
973 #print 'ps pattern:<%r>' % pattern # dbg
973 #print 'ps pattern:<%r>' % pattern # dbg
974
974
975 # defaults
975 # defaults
976 type_pattern = 'all'
976 type_pattern = 'all'
977 filter = ''
977 filter = ''
978
978
979 cmds = pattern.split()
979 cmds = pattern.split()
980 len_cmds = len(cmds)
980 len_cmds = len(cmds)
981 if len_cmds == 1:
981 if len_cmds == 1:
982 # Only filter pattern given
982 # Only filter pattern given
983 filter = cmds[0]
983 filter = cmds[0]
984 elif len_cmds == 2:
984 elif len_cmds == 2:
985 # Both filter and type specified
985 # Both filter and type specified
986 filter,type_pattern = cmds
986 filter,type_pattern = cmds
987 else:
987 else:
988 raise ValueError('invalid argument string for psearch: <%s>' %
988 raise ValueError('invalid argument string for psearch: <%s>' %
989 pattern)
989 pattern)
990
990
991 # filter search namespaces
991 # filter search namespaces
992 for name in ns_search:
992 for name in ns_search:
993 if name not in ns_table:
993 if name not in ns_table:
994 raise ValueError('invalid namespace <%s>. Valid names: %s' %
994 raise ValueError('invalid namespace <%s>. Valid names: %s' %
995 (name,ns_table.keys()))
995 (name,ns_table.keys()))
996
996
997 #print 'type_pattern:',type_pattern # dbg
997 #print 'type_pattern:',type_pattern # dbg
998 search_result, namespaces_seen = set(), set()
998 search_result, namespaces_seen = set(), set()
999 for ns_name in ns_search:
999 for ns_name in ns_search:
1000 ns = ns_table[ns_name]
1000 ns = ns_table[ns_name]
1001 # Normally, locals and globals are the same, so we just check one.
1001 # Normally, locals and globals are the same, so we just check one.
1002 if id(ns) in namespaces_seen:
1002 if id(ns) in namespaces_seen:
1003 continue
1003 continue
1004 namespaces_seen.add(id(ns))
1004 namespaces_seen.add(id(ns))
1005 tmp_res = list_namespace(ns, type_pattern, filter,
1005 tmp_res = list_namespace(ns, type_pattern, filter,
1006 ignore_case=ignore_case, show_all=show_all)
1006 ignore_case=ignore_case, show_all=show_all)
1007 search_result.update(tmp_res)
1007 search_result.update(tmp_res)
1008
1008
1009 page.page('\n'.join(sorted(search_result)))
1009 page.page('\n'.join(sorted(search_result)))
@@ -1,454 +1,455 b''
1 """Tests for the object inspection functionality.
1 """Tests for the object inspection functionality.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 from inspect import Signature, Parameter
8 import os
9 import os
9 import re
10 import re
10 import sys
11 import sys
11
12
12 import nose.tools as nt
13 import nose.tools as nt
13
14
14 from .. import oinspect
15 from .. import oinspect
15 from IPython.core.magic import (Magics, magics_class, line_magic,
16 from IPython.core.magic import (Magics, magics_class, line_magic,
16 cell_magic, line_cell_magic,
17 cell_magic, line_cell_magic,
17 register_line_magic, register_cell_magic,
18 register_line_magic, register_cell_magic,
18 register_line_cell_magic)
19 register_line_cell_magic)
19 from decorator import decorator
20 from decorator import decorator
21 from IPython import get_ipython
20 from IPython.testing.decorators import skipif
22 from IPython.testing.decorators import skipif
21 from IPython.testing.tools import AssertPrints
23 from IPython.testing.tools import AssertPrints
22 from IPython.utils.path import compress_user
24 from IPython.utils.path import compress_user
23 from IPython.utils import py3compat
25 from IPython.utils import py3compat
24 from IPython.utils.signatures import Signature, Parameter
25
26
26
27
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28 # Globals and constants
29 # Globals and constants
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30
31
31 inspector = oinspect.Inspector()
32 inspector = oinspect.Inspector()
32 ip = get_ipython()
33 ip = get_ipython()
33
34
34 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
35 # Local utilities
36 # Local utilities
36 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
37
38
38 # WARNING: since this test checks the line number where a function is
39 # WARNING: since this test checks the line number where a function is
39 # defined, if any code is inserted above, the following line will need to be
40 # defined, if any code is inserted above, the following line will need to be
40 # updated. Do NOT insert any whitespace between the next line and the function
41 # updated. Do NOT insert any whitespace between the next line and the function
41 # definition below.
42 # definition below.
42 THIS_LINE_NUMBER = 42 # Put here the actual number of this line
43 THIS_LINE_NUMBER = 43 # Put here the actual number of this line
43
44
44 from unittest import TestCase
45 from unittest import TestCase
45
46
46 class Test(TestCase):
47 class Test(TestCase):
47
48
48 def test_find_source_lines(self):
49 def test_find_source_lines(self):
49 self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines),
50 self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines),
50 THIS_LINE_NUMBER+6)
51 THIS_LINE_NUMBER+6)
51
52
52
53
53 # A couple of utilities to ensure these tests work the same from a source or a
54 # A couple of utilities to ensure these tests work the same from a source or a
54 # binary install
55 # binary install
55 def pyfile(fname):
56 def pyfile(fname):
56 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
57
58
58
59
59 def match_pyfiles(f1, f2):
60 def match_pyfiles(f1, f2):
60 nt.assert_equal(pyfile(f1), pyfile(f2))
61 nt.assert_equal(pyfile(f1), pyfile(f2))
61
62
62
63
63 def test_find_file():
64 def test_find_file():
64 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
65
66
66
67
67 def test_find_file_decorated1():
68 def test_find_file_decorated1():
68
69
69 @decorator
70 @decorator
70 def noop1(f):
71 def noop1(f):
71 def wrapper():
72 def wrapper(*a, **kw):
72 return f(*a, **kw)
73 return f(*a, **kw)
73 return wrapper
74 return wrapper
74
75
75 @noop1
76 @noop1
76 def f(x):
77 def f(x):
77 "My docstring"
78 "My docstring"
78
79
79 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
80 nt.assert_equal(f.__doc__, "My docstring")
81 nt.assert_equal(f.__doc__, "My docstring")
81
82
82
83
83 def test_find_file_decorated2():
84 def test_find_file_decorated2():
84
85
85 @decorator
86 @decorator
86 def noop2(f, *a, **kw):
87 def noop2(f, *a, **kw):
87 return f(*a, **kw)
88 return f(*a, **kw)
88
89
89 @noop2
90 @noop2
90 @noop2
91 @noop2
91 @noop2
92 @noop2
92 def f(x):
93 def f(x):
93 "My docstring 2"
94 "My docstring 2"
94
95
95 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
96 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
96 nt.assert_equal(f.__doc__, "My docstring 2")
97 nt.assert_equal(f.__doc__, "My docstring 2")
97
98
98
99
99 def test_find_file_magic():
100 def test_find_file_magic():
100 run = ip.find_line_magic('run')
101 run = ip.find_line_magic('run')
101 nt.assert_not_equal(oinspect.find_file(run), None)
102 nt.assert_not_equal(oinspect.find_file(run), None)
102
103
103
104
104 # A few generic objects we can then inspect in the tests below
105 # A few generic objects we can then inspect in the tests below
105
106
106 class Call(object):
107 class Call(object):
107 """This is the class docstring."""
108 """This is the class docstring."""
108
109
109 def __init__(self, x, y=1):
110 def __init__(self, x, y=1):
110 """This is the constructor docstring."""
111 """This is the constructor docstring."""
111
112
112 def __call__(self, *a, **kw):
113 def __call__(self, *a, **kw):
113 """This is the call docstring."""
114 """This is the call docstring."""
114
115
115 def method(self, x, z=2):
116 def method(self, x, z=2):
116 """Some method's docstring"""
117 """Some method's docstring"""
117
118
118 class HasSignature(object):
119 class HasSignature(object):
119 """This is the class docstring."""
120 """This is the class docstring."""
120 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
121 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
121
122
122 def __init__(self, *args):
123 def __init__(self, *args):
123 """This is the init docstring"""
124 """This is the init docstring"""
124
125
125
126
126 class SimpleClass(object):
127 class SimpleClass(object):
127 def method(self, x, z=2):
128 def method(self, x, z=2):
128 """Some method's docstring"""
129 """Some method's docstring"""
129
130
130
131
131 class OldStyle:
132 class OldStyle:
132 """An old-style class for testing."""
133 """An old-style class for testing."""
133 pass
134 pass
134
135
135
136
136 def f(x, y=2, *a, **kw):
137 def f(x, y=2, *a, **kw):
137 """A simple function."""
138 """A simple function."""
138
139
139
140
140 def g(y, z=3, *a, **kw):
141 def g(y, z=3, *a, **kw):
141 pass # no docstring
142 pass # no docstring
142
143
143
144
144 @register_line_magic
145 @register_line_magic
145 def lmagic(line):
146 def lmagic(line):
146 "A line magic"
147 "A line magic"
147
148
148
149
149 @register_cell_magic
150 @register_cell_magic
150 def cmagic(line, cell):
151 def cmagic(line, cell):
151 "A cell magic"
152 "A cell magic"
152
153
153
154
154 @register_line_cell_magic
155 @register_line_cell_magic
155 def lcmagic(line, cell=None):
156 def lcmagic(line, cell=None):
156 "A line/cell magic"
157 "A line/cell magic"
157
158
158
159
159 @magics_class
160 @magics_class
160 class SimpleMagics(Magics):
161 class SimpleMagics(Magics):
161 @line_magic
162 @line_magic
162 def Clmagic(self, cline):
163 def Clmagic(self, cline):
163 "A class-based line magic"
164 "A class-based line magic"
164
165
165 @cell_magic
166 @cell_magic
166 def Ccmagic(self, cline, ccell):
167 def Ccmagic(self, cline, ccell):
167 "A class-based cell magic"
168 "A class-based cell magic"
168
169
169 @line_cell_magic
170 @line_cell_magic
170 def Clcmagic(self, cline, ccell=None):
171 def Clcmagic(self, cline, ccell=None):
171 "A class-based line/cell magic"
172 "A class-based line/cell magic"
172
173
173
174
174 class Awkward(object):
175 class Awkward(object):
175 def __getattr__(self, name):
176 def __getattr__(self, name):
176 raise Exception(name)
177 raise Exception(name)
177
178
178 class NoBoolCall:
179 class NoBoolCall:
179 """
180 """
180 callable with `__bool__` raising should still be inspect-able.
181 callable with `__bool__` raising should still be inspect-able.
181 """
182 """
182
183
183 def __call__(self):
184 def __call__(self):
184 """does nothing"""
185 """does nothing"""
185 pass
186 pass
186
187
187 def __bool__(self):
188 def __bool__(self):
188 """just raise NotImplemented"""
189 """just raise NotImplemented"""
189 raise NotImplementedError('Must be implemented')
190 raise NotImplementedError('Must be implemented')
190
191
191
192
192 class SerialLiar(object):
193 class SerialLiar(object):
193 """Attribute accesses always get another copy of the same class.
194 """Attribute accesses always get another copy of the same class.
194
195
195 unittest.mock.call does something similar, but it's not ideal for testing
196 unittest.mock.call does something similar, but it's not ideal for testing
196 as the failure mode is to eat all your RAM. This gives up after 10k levels.
197 as the failure mode is to eat all your RAM. This gives up after 10k levels.
197 """
198 """
198 def __init__(self, max_fibbing_twig, lies_told=0):
199 def __init__(self, max_fibbing_twig, lies_told=0):
199 if lies_told > 10000:
200 if lies_told > 10000:
200 raise RuntimeError('Nose too long, honesty is the best policy')
201 raise RuntimeError('Nose too long, honesty is the best policy')
201 self.max_fibbing_twig = max_fibbing_twig
202 self.max_fibbing_twig = max_fibbing_twig
202 self.lies_told = lies_told
203 self.lies_told = lies_told
203 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
204 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
204
205
205 def __getattr__(self, item):
206 def __getattr__(self, item):
206 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
207 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
207
208
208
209
209 def check_calltip(obj, name, call, docstring):
210 def check_calltip(obj, name, call, docstring):
210 """Generic check pattern all calltip tests will use"""
211 """Generic check pattern all calltip tests will use"""
211 info = inspector.info(obj, name)
212 info = inspector.info(obj, name)
212 call_line, ds = oinspect.call_tip(info)
213 call_line, ds = oinspect.call_tip(info)
213 nt.assert_equal(call_line, call)
214 nt.assert_equal(call_line, call)
214 nt.assert_equal(ds, docstring)
215 nt.assert_equal(ds, docstring)
215
216
216 #-----------------------------------------------------------------------------
217 #-----------------------------------------------------------------------------
217 # Tests
218 # Tests
218 #-----------------------------------------------------------------------------
219 #-----------------------------------------------------------------------------
219
220
220 def test_calltip_class():
221 def test_calltip_class():
221 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
222 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
222
223
223
224
224 def test_calltip_instance():
225 def test_calltip_instance():
225 c = Call(1)
226 c = Call(1)
226 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
227 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
227
228
228
229
229 def test_calltip_method():
230 def test_calltip_method():
230 c = Call(1)
231 c = Call(1)
231 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
232 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
232
233
233
234
234 def test_calltip_function():
235 def test_calltip_function():
235 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
236 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
236
237
237
238
238 def test_calltip_function2():
239 def test_calltip_function2():
239 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
240 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
240
241
241
242
242 @skipif(sys.version_info >= (3, 5))
243 @skipif(sys.version_info >= (3, 5))
243 def test_calltip_builtin():
244 def test_calltip_builtin():
244 check_calltip(sum, 'sum', None, sum.__doc__)
245 check_calltip(sum, 'sum', None, sum.__doc__)
245
246
246
247
247 def test_calltip_line_magic():
248 def test_calltip_line_magic():
248 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
249 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
249
250
250
251
251 def test_calltip_cell_magic():
252 def test_calltip_cell_magic():
252 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
253 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
253
254
254
255
255 def test_calltip_line_cell_magic():
256 def test_calltip_line_cell_magic():
256 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
257 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
257 "A line/cell magic")
258 "A line/cell magic")
258
259
259
260
260 def test_class_magics():
261 def test_class_magics():
261 cm = SimpleMagics(ip)
262 cm = SimpleMagics(ip)
262 ip.register_magics(cm)
263 ip.register_magics(cm)
263 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
264 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
264 "A class-based line magic")
265 "A class-based line magic")
265 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
266 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
266 "A class-based cell magic")
267 "A class-based cell magic")
267 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
268 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
268 "A class-based line/cell magic")
269 "A class-based line/cell magic")
269
270
270
271
271 def test_info():
272 def test_info():
272 "Check that Inspector.info fills out various fields as expected."
273 "Check that Inspector.info fills out various fields as expected."
273 i = inspector.info(Call, oname='Call')
274 i = inspector.info(Call, oname='Call')
274 nt.assert_equal(i['type_name'], 'type')
275 nt.assert_equal(i['type_name'], 'type')
275 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
276 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
276 nt.assert_equal(i['base_class'], expted_class)
277 nt.assert_equal(i['base_class'], expted_class)
277 nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>")
278 nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>")
278 fname = __file__
279 fname = __file__
279 if fname.endswith(".pyc"):
280 if fname.endswith(".pyc"):
280 fname = fname[:-1]
281 fname = fname[:-1]
281 # case-insensitive comparison needed on some filesystems
282 # case-insensitive comparison needed on some filesystems
282 # e.g. Windows:
283 # e.g. Windows:
283 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
284 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
284 nt.assert_equal(i['definition'], None)
285 nt.assert_equal(i['definition'], None)
285 nt.assert_equal(i['docstring'], Call.__doc__)
286 nt.assert_equal(i['docstring'], Call.__doc__)
286 nt.assert_equal(i['source'], None)
287 nt.assert_equal(i['source'], None)
287 nt.assert_true(i['isclass'])
288 nt.assert_true(i['isclass'])
288 _self_py2 = '' if py3compat.PY3 else 'self, '
289 _self_py2 = '' if py3compat.PY3 else 'self, '
289 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)" % _self_py2)
290 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)" % _self_py2)
290 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
291 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
291
292
292 i = inspector.info(Call, detail_level=1)
293 i = inspector.info(Call, detail_level=1)
293 nt.assert_not_equal(i['source'], None)
294 nt.assert_not_equal(i['source'], None)
294 nt.assert_equal(i['docstring'], None)
295 nt.assert_equal(i['docstring'], None)
295
296
296 c = Call(1)
297 c = Call(1)
297 c.__doc__ = "Modified instance docstring"
298 c.__doc__ = "Modified instance docstring"
298 i = inspector.info(c)
299 i = inspector.info(c)
299 nt.assert_equal(i['type_name'], 'Call')
300 nt.assert_equal(i['type_name'], 'Call')
300 nt.assert_equal(i['docstring'], "Modified instance docstring")
301 nt.assert_equal(i['docstring'], "Modified instance docstring")
301 nt.assert_equal(i['class_docstring'], Call.__doc__)
302 nt.assert_equal(i['class_docstring'], Call.__doc__)
302 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
303 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
303 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
304 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
304
305
305 # Test old-style classes, which for example may not have an __init__ method.
306 # Test old-style classes, which for example may not have an __init__ method.
306 if not py3compat.PY3:
307 if not py3compat.PY3:
307 i = inspector.info(OldStyle)
308 i = inspector.info(OldStyle)
308 nt.assert_equal(i['type_name'], 'classobj')
309 nt.assert_equal(i['type_name'], 'classobj')
309
310
310 i = inspector.info(OldStyle())
311 i = inspector.info(OldStyle())
311 nt.assert_equal(i['type_name'], 'instance')
312 nt.assert_equal(i['type_name'], 'instance')
312 nt.assert_equal(i['docstring'], OldStyle.__doc__)
313 nt.assert_equal(i['docstring'], OldStyle.__doc__)
313
314
314 def test_class_signature():
315 def test_class_signature():
315 info = inspector.info(HasSignature, 'HasSignature')
316 info = inspector.info(HasSignature, 'HasSignature')
316 nt.assert_equal(info['init_definition'], "HasSignature(test)")
317 nt.assert_equal(info['init_definition'], "HasSignature(test)")
317 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
318 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
318
319
319 def test_info_awkward():
320 def test_info_awkward():
320 # Just test that this doesn't throw an error.
321 # Just test that this doesn't throw an error.
321 inspector.info(Awkward())
322 inspector.info(Awkward())
322
323
323 def test_bool_raise():
324 def test_bool_raise():
324 inspector.info(NoBoolCall())
325 inspector.info(NoBoolCall())
325
326
326 def test_info_serialliar():
327 def test_info_serialliar():
327 fib_tracker = [0]
328 fib_tracker = [0]
328 inspector.info(SerialLiar(fib_tracker))
329 inspector.info(SerialLiar(fib_tracker))
329
330
330 # Nested attribute access should be cut off at 100 levels deep to avoid
331 # Nested attribute access should be cut off at 100 levels deep to avoid
331 # infinite loops: https://github.com/ipython/ipython/issues/9122
332 # infinite loops: https://github.com/ipython/ipython/issues/9122
332 nt.assert_less(fib_tracker[0], 9000)
333 nt.assert_less(fib_tracker[0], 9000)
333
334
334 def test_calldef_none():
335 def test_calldef_none():
335 # We should ignore __call__ for all of these.
336 # We should ignore __call__ for all of these.
336 for obj in [f, SimpleClass().method, any, str.upper]:
337 for obj in [f, SimpleClass().method, any, str.upper]:
337 print(obj)
338 print(obj)
338 i = inspector.info(obj)
339 i = inspector.info(obj)
339 nt.assert_is(i['call_def'], None)
340 nt.assert_is(i['call_def'], None)
340
341
341 def f_kwarg(pos, *, kwonly):
342 def f_kwarg(pos, *, kwonly):
342 pass
343 pass
343
344
344 def test_definition_kwonlyargs():
345 def test_definition_kwonlyargs():
345 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
346 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
346 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
347 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
347
348
348 def test_getdoc():
349 def test_getdoc():
349 class A(object):
350 class A(object):
350 """standard docstring"""
351 """standard docstring"""
351 pass
352 pass
352
353
353 class B(object):
354 class B(object):
354 """standard docstring"""
355 """standard docstring"""
355 def getdoc(self):
356 def getdoc(self):
356 return "custom docstring"
357 return "custom docstring"
357
358
358 class C(object):
359 class C(object):
359 """standard docstring"""
360 """standard docstring"""
360 def getdoc(self):
361 def getdoc(self):
361 return None
362 return None
362
363
363 a = A()
364 a = A()
364 b = B()
365 b = B()
365 c = C()
366 c = C()
366
367
367 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
368 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
368 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
369 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
369 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
370 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
370
371
371
372
372 def test_empty_property_has_no_source():
373 def test_empty_property_has_no_source():
373 i = inspector.info(property(), detail_level=1)
374 i = inspector.info(property(), detail_level=1)
374 nt.assert_is(i['source'], None)
375 nt.assert_is(i['source'], None)
375
376
376
377
377 def test_property_sources():
378 def test_property_sources():
378 import zlib
379 import zlib
379
380
380 class A(object):
381 class A(object):
381 @property
382 @property
382 def foo(self):
383 def foo(self):
383 return 'bar'
384 return 'bar'
384
385
385 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
386 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
386
387
387 id = property(id)
388 id = property(id)
388 compress = property(zlib.compress)
389 compress = property(zlib.compress)
389
390
390 i = inspector.info(A.foo, detail_level=1)
391 i = inspector.info(A.foo, detail_level=1)
391 nt.assert_in('def foo(self):', i['source'])
392 nt.assert_in('def foo(self):', i['source'])
392 nt.assert_in('lambda self, v:', i['source'])
393 nt.assert_in('lambda self, v:', i['source'])
393
394
394 i = inspector.info(A.id, detail_level=1)
395 i = inspector.info(A.id, detail_level=1)
395 nt.assert_in('fget = <function id>', i['source'])
396 nt.assert_in('fget = <function id>', i['source'])
396
397
397 i = inspector.info(A.compress, detail_level=1)
398 i = inspector.info(A.compress, detail_level=1)
398 nt.assert_in('fget = <function zlib.compress>', i['source'])
399 nt.assert_in('fget = <function zlib.compress>', i['source'])
399
400
400
401
401 def test_property_docstring_is_in_info_for_detail_level_0():
402 def test_property_docstring_is_in_info_for_detail_level_0():
402 class A(object):
403 class A(object):
403 @property
404 @property
404 def foobar(self):
405 def foobar(self):
405 """This is `foobar` property."""
406 """This is `foobar` property."""
406 pass
407 pass
407
408
408 ip.user_ns['a_obj'] = A()
409 ip.user_ns['a_obj'] = A()
409 nt.assert_equals(
410 nt.assert_equals(
410 'This is `foobar` property.',
411 'This is `foobar` property.',
411 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
412 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
412
413
413 ip.user_ns['a_cls'] = A
414 ip.user_ns['a_cls'] = A
414 nt.assert_equals(
415 nt.assert_equals(
415 'This is `foobar` property.',
416 'This is `foobar` property.',
416 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
417 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
417
418
418
419
419 def test_pdef():
420 def test_pdef():
420 # See gh-1914
421 # See gh-1914
421 def foo(): pass
422 def foo(): pass
422 inspector.pdef(foo, 'foo')
423 inspector.pdef(foo, 'foo')
423
424
424
425
425 def test_pinfo_nonascii():
426 def test_pinfo_nonascii():
426 # See gh-1177
427 # See gh-1177
427 from . import nonascii2
428 from . import nonascii2
428 ip.user_ns['nonascii2'] = nonascii2
429 ip.user_ns['nonascii2'] = nonascii2
429 ip._inspect('pinfo', 'nonascii2', detail_level=1)
430 ip._inspect('pinfo', 'nonascii2', detail_level=1)
430
431
431
432
432 def test_pinfo_magic():
433 def test_pinfo_magic():
433 with AssertPrints('Docstring:'):
434 with AssertPrints('Docstring:'):
434 ip._inspect('pinfo', 'lsmagic', detail_level=0)
435 ip._inspect('pinfo', 'lsmagic', detail_level=0)
435
436
436 with AssertPrints('Source:'):
437 with AssertPrints('Source:'):
437 ip._inspect('pinfo', 'lsmagic', detail_level=1)
438 ip._inspect('pinfo', 'lsmagic', detail_level=1)
438
439
439
440
440 def test_init_colors():
441 def test_init_colors():
441 # ensure colors are not present in signature info
442 # ensure colors are not present in signature info
442 info = inspector.info(HasSignature)
443 info = inspector.info(HasSignature)
443 init_def = info['init_definition']
444 init_def = info['init_definition']
444 nt.assert_not_in('[0m', init_def)
445 nt.assert_not_in('[0m', init_def)
445
446
446
447
447 def test_builtin_init():
448 def test_builtin_init():
448 info = inspector.info(list)
449 info = inspector.info(list)
449 init_def = info['init_definition']
450 init_def = info['init_definition']
450 # Python < 3.4 can't get init definition from builtins,
451 # Python < 3.4 can't get init definition from builtins,
451 # but still exercise the inspection in case of error-raising bugs.
452 # but still exercise the inspection in case of error-raising bugs.
452 if sys.version_info >= (3,4):
453 if sys.version_info >= (3,4):
453 nt.assert_is_not_none(init_def)
454 nt.assert_is_not_none(init_def)
454
455
@@ -1,11 +1,11 b''
1 """Function signature objects for callables.
1 """DEPRECATED: Function signature objects for callables.
2
2
3 Use the standard library version if available, as it is more up to date.
3 Use the standard library version if available, as it is more up to date.
4 Fallback on backport otherwise.
4 Fallback on backport otherwise.
5 """
5 """
6
6
7 import warnings
8 warnings.warn("{} backport for Python 2 is deprecated in IPython 6, which only supports Python 3".format(__name__),
9 DeprecationWarning, stacklevel=2)
7
10
8 try:
11 from inspect import BoundArguments, Parameter, Signature, signature
9 from inspect import BoundArguments, Parameter, Signature, signature
10 except ImportError:
11 from ._signatures import BoundArguments, Parameter, Signature, signature
1 NO CONTENT: file was removed
NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (816 lines changed) Show them Hide them
General Comments 0
You need to be logged in to leave comments. Login now