##// END OF EJS Templates
Use the more powerful signatures module to display function argument signatures. In particular this works better for functions wrapped with functools.wraps (at least on Python >= 3.4)
Erik M. Bray -
Show More
@@ -1,918 +1,919 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 from __future__ import print_function
13 from __future__ import print_function
14
14
15 __all__ = ['Inspector','InspectColors']
15 __all__ = ['Inspector','InspectColors']
16
16
17 # stdlib modules
17 # stdlib modules
18 import inspect
18 import inspect
19 import linecache
19 import linecache
20 import os
20 import os
21 from textwrap import dedent
21 from textwrap import dedent
22 import types
22 import types
23 import io as stdlib_io
23 import io as stdlib_io
24
24
25 try:
25 try:
26 from itertools import izip_longest
26 from itertools import izip_longest
27 except ImportError:
27 except ImportError:
28 from itertools import zip_longest as izip_longest
28 from itertools import zip_longest as izip_longest
29
29
30 # IPython's own
30 # IPython's own
31 from IPython.core import page
31 from IPython.core import page
32 from IPython.lib.pretty import pretty
32 from IPython.lib.pretty import pretty
33 from IPython.testing.skipdoctest import skip_doctest_py3
33 from IPython.testing.skipdoctest import skip_doctest_py3
34 from IPython.utils import PyColorize
34 from IPython.utils import PyColorize
35 from IPython.utils import io
35 from IPython.utils import io
36 from IPython.utils import openpy
36 from IPython.utils import openpy
37 from IPython.utils import py3compat
37 from IPython.utils import py3compat
38 from IPython.utils.dir2 import safe_hasattr
38 from IPython.utils.dir2 import safe_hasattr
39 from IPython.utils.text import indent
39 from IPython.utils.text import indent
40 from IPython.utils.wildcard import list_namespace
40 from IPython.utils.wildcard import list_namespace
41 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
42 from IPython.utils.py3compat import cast_unicode, string_types, PY3
42 from IPython.utils.py3compat import cast_unicode, string_types, PY3
43 from IPython.utils.signatures import signature
43
44
44 # builtin docstrings to ignore
45 # builtin docstrings to ignore
45 _func_call_docstring = types.FunctionType.__call__.__doc__
46 _func_call_docstring = types.FunctionType.__call__.__doc__
46 _object_init_docstring = object.__init__.__doc__
47 _object_init_docstring = object.__init__.__doc__
47 _builtin_type_docstrings = {
48 _builtin_type_docstrings = {
48 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
49 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
49 types.FunctionType, property)
50 types.FunctionType, property)
50 }
51 }
51
52
52 _builtin_func_type = type(all)
53 _builtin_func_type = type(all)
53 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
54 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
54 #****************************************************************************
55 #****************************************************************************
55 # Builtin color schemes
56 # Builtin color schemes
56
57
57 Colors = TermColors # just a shorthand
58 Colors = TermColors # just a shorthand
58
59
59 # Build a few color schemes
60 # Build a few color schemes
60 NoColor = ColorScheme(
61 NoColor = ColorScheme(
61 'NoColor',{
62 'NoColor',{
62 'header' : Colors.NoColor,
63 'header' : Colors.NoColor,
63 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
64 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
64 } )
65 } )
65
66
66 LinuxColors = ColorScheme(
67 LinuxColors = ColorScheme(
67 'Linux',{
68 'Linux',{
68 'header' : Colors.LightRed,
69 'header' : Colors.LightRed,
69 'normal' : Colors.Normal # color off (usu. Colors.Normal)
70 'normal' : Colors.Normal # color off (usu. Colors.Normal)
70 } )
71 } )
71
72
72 LightBGColors = ColorScheme(
73 LightBGColors = ColorScheme(
73 'LightBG',{
74 'LightBG',{
74 'header' : Colors.Red,
75 'header' : Colors.Red,
75 'normal' : Colors.Normal # color off (usu. Colors.Normal)
76 'normal' : Colors.Normal # color off (usu. Colors.Normal)
76 } )
77 } )
77
78
78 # Build table of color schemes (needed by the parser)
79 # Build table of color schemes (needed by the parser)
79 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
80 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
80 'Linux')
81 'Linux')
81
82
82 #****************************************************************************
83 #****************************************************************************
83 # Auxiliary functions and objects
84 # Auxiliary functions and objects
84
85
85 # See the messaging spec for the definition of all these fields. This list
86 # See the messaging spec for the definition of all these fields. This list
86 # effectively defines the order of display
87 # effectively defines the order of display
87 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
88 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
88 'length', 'file', 'definition', 'docstring', 'source',
89 'length', 'file', 'definition', 'docstring', 'source',
89 'init_definition', 'class_docstring', 'init_docstring',
90 'init_definition', 'class_docstring', 'init_docstring',
90 'call_def', 'call_docstring',
91 'call_def', 'call_docstring',
91 # These won't be printed but will be used to determine how to
92 # These won't be printed but will be used to determine how to
92 # format the object
93 # format the object
93 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
94 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
94 ]
95 ]
95
96
96
97
97 def object_info(**kw):
98 def object_info(**kw):
98 """Make an object info dict with all fields present."""
99 """Make an object info dict with all fields present."""
99 infodict = dict(izip_longest(info_fields, [None]))
100 infodict = dict(izip_longest(info_fields, [None]))
100 infodict.update(kw)
101 infodict.update(kw)
101 return infodict
102 return infodict
102
103
103
104
104 def get_encoding(obj):
105 def get_encoding(obj):
105 """Get encoding for python source file defining obj
106 """Get encoding for python source file defining obj
106
107
107 Returns None if obj is not defined in a sourcefile.
108 Returns None if obj is not defined in a sourcefile.
108 """
109 """
109 ofile = find_file(obj)
110 ofile = find_file(obj)
110 # run contents of file through pager starting at line where the object
111 # run contents of file through pager starting at line where the object
111 # is defined, as long as the file isn't binary and is actually on the
112 # is defined, as long as the file isn't binary and is actually on the
112 # filesystem.
113 # filesystem.
113 if ofile is None:
114 if ofile is None:
114 return None
115 return None
115 elif ofile.endswith(('.so', '.dll', '.pyd')):
116 elif ofile.endswith(('.so', '.dll', '.pyd')):
116 return None
117 return None
117 elif not os.path.isfile(ofile):
118 elif not os.path.isfile(ofile):
118 return None
119 return None
119 else:
120 else:
120 # Print only text files, not extension binaries. Note that
121 # Print only text files, not extension binaries. Note that
121 # getsourcelines returns lineno with 1-offset and page() uses
122 # getsourcelines returns lineno with 1-offset and page() uses
122 # 0-offset, so we must adjust.
123 # 0-offset, so we must adjust.
123 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
124 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
124 encoding, lines = openpy.detect_encoding(buffer.readline)
125 encoding, lines = openpy.detect_encoding(buffer.readline)
125 return encoding
126 return encoding
126
127
127 def getdoc(obj):
128 def getdoc(obj):
128 """Stable wrapper around inspect.getdoc.
129 """Stable wrapper around inspect.getdoc.
129
130
130 This can't crash because of attribute problems.
131 This can't crash because of attribute problems.
131
132
132 It also attempts to call a getdoc() method on the given object. This
133 It also attempts to call a getdoc() method on the given object. This
133 allows objects which provide their docstrings via non-standard mechanisms
134 allows objects which provide their docstrings via non-standard mechanisms
134 (like Pyro proxies) to still be inspected by ipython's ? system."""
135 (like Pyro proxies) to still be inspected by ipython's ? system."""
135 # Allow objects to offer customized documentation via a getdoc method:
136 # Allow objects to offer customized documentation via a getdoc method:
136 try:
137 try:
137 ds = obj.getdoc()
138 ds = obj.getdoc()
138 except Exception:
139 except Exception:
139 pass
140 pass
140 else:
141 else:
141 # if we get extra info, we add it to the normal docstring.
142 # if we get extra info, we add it to the normal docstring.
142 if isinstance(ds, string_types):
143 if isinstance(ds, string_types):
143 return inspect.cleandoc(ds)
144 return inspect.cleandoc(ds)
144
145
145 try:
146 try:
146 docstr = inspect.getdoc(obj)
147 docstr = inspect.getdoc(obj)
147 encoding = get_encoding(obj)
148 encoding = get_encoding(obj)
148 return py3compat.cast_unicode(docstr, encoding=encoding)
149 return py3compat.cast_unicode(docstr, encoding=encoding)
149 except Exception:
150 except Exception:
150 # Harden against an inspect failure, which can occur with
151 # Harden against an inspect failure, which can occur with
151 # SWIG-wrapped extensions.
152 # SWIG-wrapped extensions.
152 raise
153 raise
153 return None
154 return None
154
155
155
156
156 def getsource(obj, oname=''):
157 def getsource(obj, oname=''):
157 """Wrapper around inspect.getsource.
158 """Wrapper around inspect.getsource.
158
159
159 This can be modified by other projects to provide customized source
160 This can be modified by other projects to provide customized source
160 extraction.
161 extraction.
161
162
162 Parameters
163 Parameters
163 ----------
164 ----------
164 obj : object
165 obj : object
165 an object whose source code we will attempt to extract
166 an object whose source code we will attempt to extract
166 oname : str
167 oname : str
167 (optional) a name under which the object is known
168 (optional) a name under which the object is known
168
169
169 Returns
170 Returns
170 -------
171 -------
171 src : unicode or None
172 src : unicode or None
172
173
173 """
174 """
174
175
175 if isinstance(obj, property):
176 if isinstance(obj, property):
176 sources = []
177 sources = []
177 for attrname in ['fget', 'fset', 'fdel']:
178 for attrname in ['fget', 'fset', 'fdel']:
178 fn = getattr(obj, attrname)
179 fn = getattr(obj, attrname)
179 if fn is not None:
180 if fn is not None:
180 encoding = get_encoding(fn)
181 encoding = get_encoding(fn)
181 oname_prefix = ('%s.' % oname) if oname else ''
182 oname_prefix = ('%s.' % oname) if oname else ''
182 sources.append(cast_unicode(
183 sources.append(cast_unicode(
183 ''.join(('# ', oname_prefix, attrname)),
184 ''.join(('# ', oname_prefix, attrname)),
184 encoding=encoding))
185 encoding=encoding))
185 if inspect.isfunction(fn):
186 if inspect.isfunction(fn):
186 sources.append(dedent(getsource(fn)))
187 sources.append(dedent(getsource(fn)))
187 else:
188 else:
188 # Default str/repr only prints function name,
189 # Default str/repr only prints function name,
189 # pretty.pretty prints module name too.
190 # pretty.pretty prints module name too.
190 sources.append(cast_unicode(
191 sources.append(cast_unicode(
191 '%s%s = %s\n' % (
192 '%s%s = %s\n' % (
192 oname_prefix, attrname, pretty(fn)),
193 oname_prefix, attrname, pretty(fn)),
193 encoding=encoding))
194 encoding=encoding))
194 if sources:
195 if sources:
195 return '\n'.join(sources)
196 return '\n'.join(sources)
196 else:
197 else:
197 return None
198 return None
198
199
199 else:
200 else:
200 # Get source for non-property objects.
201 # Get source for non-property objects.
201
202
202 # '__wrapped__' attribute is used by some decorators (e.g. ones defined
203 # '__wrapped__' attribute is used by some decorators (e.g. ones defined
203 # functools) to provide access to the decorated function.
204 # functools) to provide access to the decorated function.
204 if hasattr(obj, "__wrapped__"):
205 if hasattr(obj, "__wrapped__"):
205 obj = obj.__wrapped__
206 obj = obj.__wrapped__
206
207
207 try:
208 try:
208 src = inspect.getsource(obj)
209 src = inspect.getsource(obj)
209 except TypeError:
210 except TypeError:
210 # The object itself provided no meaningful source, try looking for
211 # The object itself provided no meaningful source, try looking for
211 # its class definition instead.
212 # its class definition instead.
212 if hasattr(obj, '__class__'):
213 if hasattr(obj, '__class__'):
213 try:
214 try:
214 src = inspect.getsource(obj.__class__)
215 src = inspect.getsource(obj.__class__)
215 except TypeError:
216 except TypeError:
216 return None
217 return None
217
218
218 encoding = get_encoding(obj)
219 encoding = get_encoding(obj)
219 return cast_unicode(src, encoding=encoding)
220 return cast_unicode(src, encoding=encoding)
220
221
221
222
222 def is_simple_callable(obj):
223 def is_simple_callable(obj):
223 """True if obj is a function ()"""
224 """True if obj is a function ()"""
224 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
225 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
225 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
226 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
226
227
227
228
228 def getargspec(obj):
229 def getargspec(obj):
229 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
230 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
230 :func:inspect.getargspec` on Python 2.
231 :func:inspect.getargspec` on Python 2.
231
232
232 In addition to functions and methods, this can also handle objects with a
233 In addition to functions and methods, this can also handle objects with a
233 ``__call__`` attribute.
234 ``__call__`` attribute.
234 """
235 """
235 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
236 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
236 obj = obj.__call__
237 obj = obj.__call__
237
238
238 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
239 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
239
240
240
241
241 def format_argspec(argspec):
242 def format_argspec(argspec):
242 """Format argspect, convenience wrapper around inspect's.
243 """Format argspect, convenience wrapper around inspect's.
243
244
244 This takes a dict instead of ordered arguments and calls
245 This takes a dict instead of ordered arguments and calls
245 inspect.format_argspec with the arguments in the necessary order.
246 inspect.format_argspec with the arguments in the necessary order.
246 """
247 """
247 return inspect.formatargspec(argspec['args'], argspec['varargs'],
248 return inspect.formatargspec(argspec['args'], argspec['varargs'],
248 argspec['varkw'], argspec['defaults'])
249 argspec['varkw'], argspec['defaults'])
249
250
250
251
251 def call_tip(oinfo, format_call=True):
252 def call_tip(oinfo, format_call=True):
252 """Extract call tip data from an oinfo dict.
253 """Extract call tip data from an oinfo dict.
253
254
254 Parameters
255 Parameters
255 ----------
256 ----------
256 oinfo : dict
257 oinfo : dict
257
258
258 format_call : bool, optional
259 format_call : bool, optional
259 If True, the call line is formatted and returned as a string. If not, a
260 If True, the call line is formatted and returned as a string. If not, a
260 tuple of (name, argspec) is returned.
261 tuple of (name, argspec) is returned.
261
262
262 Returns
263 Returns
263 -------
264 -------
264 call_info : None, str or (str, dict) tuple.
265 call_info : None, str or (str, dict) tuple.
265 When format_call is True, the whole call information is formattted as a
266 When format_call is True, the whole call information is formattted as a
266 single string. Otherwise, the object's name and its argspec dict are
267 single string. Otherwise, the object's name and its argspec dict are
267 returned. If no call information is available, None is returned.
268 returned. If no call information is available, None is returned.
268
269
269 docstring : str or None
270 docstring : str or None
270 The most relevant docstring for calling purposes is returned, if
271 The most relevant docstring for calling purposes is returned, if
271 available. The priority is: call docstring for callable instances, then
272 available. The priority is: call docstring for callable instances, then
272 constructor docstring for classes, then main object's docstring otherwise
273 constructor docstring for classes, then main object's docstring otherwise
273 (regular functions).
274 (regular functions).
274 """
275 """
275 # Get call definition
276 # Get call definition
276 argspec = oinfo.get('argspec')
277 argspec = oinfo.get('argspec')
277 if argspec is None:
278 if argspec is None:
278 call_line = None
279 call_line = None
279 else:
280 else:
280 # Callable objects will have 'self' as their first argument, prune
281 # Callable objects will have 'self' as their first argument, prune
281 # it out if it's there for clarity (since users do *not* pass an
282 # it out if it's there for clarity (since users do *not* pass an
282 # extra first argument explicitly).
283 # extra first argument explicitly).
283 try:
284 try:
284 has_self = argspec['args'][0] == 'self'
285 has_self = argspec['args'][0] == 'self'
285 except (KeyError, IndexError):
286 except (KeyError, IndexError):
286 pass
287 pass
287 else:
288 else:
288 if has_self:
289 if has_self:
289 argspec['args'] = argspec['args'][1:]
290 argspec['args'] = argspec['args'][1:]
290
291
291 call_line = oinfo['name']+format_argspec(argspec)
292 call_line = oinfo['name']+format_argspec(argspec)
292
293
293 # Now get docstring.
294 # Now get docstring.
294 # The priority is: call docstring, constructor docstring, main one.
295 # The priority is: call docstring, constructor docstring, main one.
295 doc = oinfo.get('call_docstring')
296 doc = oinfo.get('call_docstring')
296 if doc is None:
297 if doc is None:
297 doc = oinfo.get('init_docstring')
298 doc = oinfo.get('init_docstring')
298 if doc is None:
299 if doc is None:
299 doc = oinfo.get('docstring','')
300 doc = oinfo.get('docstring','')
300
301
301 return call_line, doc
302 return call_line, doc
302
303
303
304
304 def find_file(obj):
305 def find_file(obj):
305 """Find the absolute path to the file where an object was defined.
306 """Find the absolute path to the file where an object was defined.
306
307
307 This is essentially a robust wrapper around `inspect.getabsfile`.
308 This is essentially a robust wrapper around `inspect.getabsfile`.
308
309
309 Returns None if no file can be found.
310 Returns None if no file can be found.
310
311
311 Parameters
312 Parameters
312 ----------
313 ----------
313 obj : any Python object
314 obj : any Python object
314
315
315 Returns
316 Returns
316 -------
317 -------
317 fname : str
318 fname : str
318 The absolute path to the file where the object was defined.
319 The absolute path to the file where the object was defined.
319 """
320 """
320 # get source if obj was decorated with @decorator
321 # get source if obj was decorated with @decorator
321 if safe_hasattr(obj, '__wrapped__'):
322 if safe_hasattr(obj, '__wrapped__'):
322 obj = obj.__wrapped__
323 obj = obj.__wrapped__
323
324
324 fname = None
325 fname = None
325 try:
326 try:
326 fname = inspect.getabsfile(obj)
327 fname = inspect.getabsfile(obj)
327 except TypeError:
328 except TypeError:
328 # For an instance, the file that matters is where its class was
329 # For an instance, the file that matters is where its class was
329 # declared.
330 # declared.
330 if hasattr(obj, '__class__'):
331 if hasattr(obj, '__class__'):
331 try:
332 try:
332 fname = inspect.getabsfile(obj.__class__)
333 fname = inspect.getabsfile(obj.__class__)
333 except TypeError:
334 except TypeError:
334 # Can happen for builtins
335 # Can happen for builtins
335 pass
336 pass
336 except:
337 except:
337 pass
338 pass
338 return cast_unicode(fname)
339 return cast_unicode(fname)
339
340
340
341
341 def find_source_lines(obj):
342 def find_source_lines(obj):
342 """Find the line number in a file where an object was defined.
343 """Find the line number in a file where an object was defined.
343
344
344 This is essentially a robust wrapper around `inspect.getsourcelines`.
345 This is essentially a robust wrapper around `inspect.getsourcelines`.
345
346
346 Returns None if no file can be found.
347 Returns None if no file can be found.
347
348
348 Parameters
349 Parameters
349 ----------
350 ----------
350 obj : any Python object
351 obj : any Python object
351
352
352 Returns
353 Returns
353 -------
354 -------
354 lineno : int
355 lineno : int
355 The line number where the object definition starts.
356 The line number where the object definition starts.
356 """
357 """
357 # get source if obj was decorated with @decorator
358 # get source if obj was decorated with @decorator
358 if safe_hasattr(obj, '__wrapped__'):
359 if safe_hasattr(obj, '__wrapped__'):
359 obj = obj.__wrapped__
360 obj = obj.__wrapped__
360
361
361 try:
362 try:
362 try:
363 try:
363 lineno = inspect.getsourcelines(obj)[1]
364 lineno = inspect.getsourcelines(obj)[1]
364 except TypeError:
365 except TypeError:
365 # For instances, try the class object like getsource() does
366 # For instances, try the class object like getsource() does
366 if hasattr(obj, '__class__'):
367 if hasattr(obj, '__class__'):
367 lineno = inspect.getsourcelines(obj.__class__)[1]
368 lineno = inspect.getsourcelines(obj.__class__)[1]
368 else:
369 else:
369 lineno = None
370 lineno = None
370 except:
371 except:
371 return None
372 return None
372
373
373 return lineno
374 return lineno
374
375
375
376
376 class Inspector:
377 class Inspector:
377 def __init__(self, color_table=InspectColors,
378 def __init__(self, color_table=InspectColors,
378 code_color_table=PyColorize.ANSICodeColors,
379 code_color_table=PyColorize.ANSICodeColors,
379 scheme='NoColor',
380 scheme='NoColor',
380 str_detail_level=0):
381 str_detail_level=0):
381 self.color_table = color_table
382 self.color_table = color_table
382 self.parser = PyColorize.Parser(code_color_table,out='str')
383 self.parser = PyColorize.Parser(code_color_table,out='str')
383 self.format = self.parser.format
384 self.format = self.parser.format
384 self.str_detail_level = str_detail_level
385 self.str_detail_level = str_detail_level
385 self.set_active_scheme(scheme)
386 self.set_active_scheme(scheme)
386
387
387 def _getdef(self,obj,oname=''):
388 def _getdef(self,obj,oname=''):
388 """Return the call signature for any callable object.
389 """Return the call signature for any callable object.
389
390
390 If any exception is generated, None is returned instead and the
391 If any exception is generated, None is returned instead and the
391 exception is suppressed."""
392 exception is suppressed."""
392 try:
393 try:
393 hdef = oname + inspect.formatargspec(*getargspec(obj))
394 hdef = oname + str(signature(obj))
394 return cast_unicode(hdef)
395 return cast_unicode(hdef)
395 except:
396 except:
396 return None
397 return None
397
398
398 def __head(self,h):
399 def __head(self,h):
399 """Return a header string with proper colors."""
400 """Return a header string with proper colors."""
400 return '%s%s%s' % (self.color_table.active_colors.header,h,
401 return '%s%s%s' % (self.color_table.active_colors.header,h,
401 self.color_table.active_colors.normal)
402 self.color_table.active_colors.normal)
402
403
403 def set_active_scheme(self, scheme):
404 def set_active_scheme(self, scheme):
404 self.color_table.set_active_scheme(scheme)
405 self.color_table.set_active_scheme(scheme)
405 self.parser.color_table.set_active_scheme(scheme)
406 self.parser.color_table.set_active_scheme(scheme)
406
407
407 def noinfo(self, msg, oname):
408 def noinfo(self, msg, oname):
408 """Generic message when no information is found."""
409 """Generic message when no information is found."""
409 print('No %s found' % msg, end=' ')
410 print('No %s found' % msg, end=' ')
410 if oname:
411 if oname:
411 print('for %s' % oname)
412 print('for %s' % oname)
412 else:
413 else:
413 print()
414 print()
414
415
415 def pdef(self, obj, oname=''):
416 def pdef(self, obj, oname=''):
416 """Print the call signature for any callable object.
417 """Print the call signature for any callable object.
417
418
418 If the object is a class, print the constructor information."""
419 If the object is a class, print the constructor information."""
419
420
420 if not callable(obj):
421 if not callable(obj):
421 print('Object is not callable.')
422 print('Object is not callable.')
422 return
423 return
423
424
424 header = ''
425 header = ''
425
426
426 if inspect.isclass(obj):
427 if inspect.isclass(obj):
427 header = self.__head('Class constructor information:\n')
428 header = self.__head('Class constructor information:\n')
428 obj = obj.__init__
429 obj = obj.__init__
429 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
430 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
430 obj = obj.__call__
431 obj = obj.__call__
431
432
432 output = self._getdef(obj,oname)
433 output = self._getdef(obj,oname)
433 if output is None:
434 if output is None:
434 self.noinfo('definition header',oname)
435 self.noinfo('definition header',oname)
435 else:
436 else:
436 print(header,self.format(output), end=' ', file=io.stdout)
437 print(header,self.format(output), end=' ', file=io.stdout)
437
438
438 # In Python 3, all classes are new-style, so they all have __init__.
439 # In Python 3, all classes are new-style, so they all have __init__.
439 @skip_doctest_py3
440 @skip_doctest_py3
440 def pdoc(self,obj,oname='',formatter = None):
441 def pdoc(self,obj,oname='',formatter = None):
441 """Print the docstring for any object.
442 """Print the docstring for any object.
442
443
443 Optional:
444 Optional:
444 -formatter: a function to run the docstring through for specially
445 -formatter: a function to run the docstring through for specially
445 formatted docstrings.
446 formatted docstrings.
446
447
447 Examples
448 Examples
448 --------
449 --------
449
450
450 In [1]: class NoInit:
451 In [1]: class NoInit:
451 ...: pass
452 ...: pass
452
453
453 In [2]: class NoDoc:
454 In [2]: class NoDoc:
454 ...: def __init__(self):
455 ...: def __init__(self):
455 ...: pass
456 ...: pass
456
457
457 In [3]: %pdoc NoDoc
458 In [3]: %pdoc NoDoc
458 No documentation found for NoDoc
459 No documentation found for NoDoc
459
460
460 In [4]: %pdoc NoInit
461 In [4]: %pdoc NoInit
461 No documentation found for NoInit
462 No documentation found for NoInit
462
463
463 In [5]: obj = NoInit()
464 In [5]: obj = NoInit()
464
465
465 In [6]: %pdoc obj
466 In [6]: %pdoc obj
466 No documentation found for obj
467 No documentation found for obj
467
468
468 In [5]: obj2 = NoDoc()
469 In [5]: obj2 = NoDoc()
469
470
470 In [6]: %pdoc obj2
471 In [6]: %pdoc obj2
471 No documentation found for obj2
472 No documentation found for obj2
472 """
473 """
473
474
474 head = self.__head # For convenience
475 head = self.__head # For convenience
475 lines = []
476 lines = []
476 ds = getdoc(obj)
477 ds = getdoc(obj)
477 if formatter:
478 if formatter:
478 ds = formatter(ds)
479 ds = formatter(ds)
479 if ds:
480 if ds:
480 lines.append(head("Class docstring:"))
481 lines.append(head("Class docstring:"))
481 lines.append(indent(ds))
482 lines.append(indent(ds))
482 if inspect.isclass(obj) and hasattr(obj, '__init__'):
483 if inspect.isclass(obj) and hasattr(obj, '__init__'):
483 init_ds = getdoc(obj.__init__)
484 init_ds = getdoc(obj.__init__)
484 if init_ds is not None:
485 if init_ds is not None:
485 lines.append(head("Init docstring:"))
486 lines.append(head("Init docstring:"))
486 lines.append(indent(init_ds))
487 lines.append(indent(init_ds))
487 elif hasattr(obj,'__call__'):
488 elif hasattr(obj,'__call__'):
488 call_ds = getdoc(obj.__call__)
489 call_ds = getdoc(obj.__call__)
489 if call_ds:
490 if call_ds:
490 lines.append(head("Call docstring:"))
491 lines.append(head("Call docstring:"))
491 lines.append(indent(call_ds))
492 lines.append(indent(call_ds))
492
493
493 if not lines:
494 if not lines:
494 self.noinfo('documentation',oname)
495 self.noinfo('documentation',oname)
495 else:
496 else:
496 page.page('\n'.join(lines))
497 page.page('\n'.join(lines))
497
498
498 def psource(self, obj, oname=''):
499 def psource(self, obj, oname=''):
499 """Print the source code for an object."""
500 """Print the source code for an object."""
500
501
501 # Flush the source cache because inspect can return out-of-date source
502 # Flush the source cache because inspect can return out-of-date source
502 linecache.checkcache()
503 linecache.checkcache()
503 try:
504 try:
504 src = getsource(obj, oname=oname)
505 src = getsource(obj, oname=oname)
505 except Exception:
506 except Exception:
506 src = None
507 src = None
507
508
508 if src is None:
509 if src is None:
509 self.noinfo('source', oname)
510 self.noinfo('source', oname)
510 else:
511 else:
511 page.page(self.format(src))
512 page.page(self.format(src))
512
513
513 def pfile(self, obj, oname=''):
514 def pfile(self, obj, oname=''):
514 """Show the whole file where an object was defined."""
515 """Show the whole file where an object was defined."""
515
516
516 lineno = find_source_lines(obj)
517 lineno = find_source_lines(obj)
517 if lineno is None:
518 if lineno is None:
518 self.noinfo('file', oname)
519 self.noinfo('file', oname)
519 return
520 return
520
521
521 ofile = find_file(obj)
522 ofile = find_file(obj)
522 # run contents of file through pager starting at line where the object
523 # run contents of file through pager starting at line where the object
523 # is defined, as long as the file isn't binary and is actually on the
524 # is defined, as long as the file isn't binary and is actually on the
524 # filesystem.
525 # filesystem.
525 if ofile.endswith(('.so', '.dll', '.pyd')):
526 if ofile.endswith(('.so', '.dll', '.pyd')):
526 print('File %r is binary, not printing.' % ofile)
527 print('File %r is binary, not printing.' % ofile)
527 elif not os.path.isfile(ofile):
528 elif not os.path.isfile(ofile):
528 print('File %r does not exist, not printing.' % ofile)
529 print('File %r does not exist, not printing.' % ofile)
529 else:
530 else:
530 # Print only text files, not extension binaries. Note that
531 # Print only text files, not extension binaries. Note that
531 # getsourcelines returns lineno with 1-offset and page() uses
532 # getsourcelines returns lineno with 1-offset and page() uses
532 # 0-offset, so we must adjust.
533 # 0-offset, so we must adjust.
533 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
534 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
534
535
535 def _format_fields(self, fields, title_width=0):
536 def _format_fields(self, fields, title_width=0):
536 """Formats a list of fields for display.
537 """Formats a list of fields for display.
537
538
538 Parameters
539 Parameters
539 ----------
540 ----------
540 fields : list
541 fields : list
541 A list of 2-tuples: (field_title, field_content)
542 A list of 2-tuples: (field_title, field_content)
542 title_width : int
543 title_width : int
543 How many characters to pad titles to. Default to longest title.
544 How many characters to pad titles to. Default to longest title.
544 """
545 """
545 out = []
546 out = []
546 header = self.__head
547 header = self.__head
547 if title_width == 0:
548 if title_width == 0:
548 title_width = max(len(title) + 2 for title, _ in fields)
549 title_width = max(len(title) + 2 for title, _ in fields)
549 for title, content in fields:
550 for title, content in fields:
550 if len(content.splitlines()) > 1:
551 if len(content.splitlines()) > 1:
551 title = header(title + ":") + "\n"
552 title = header(title + ":") + "\n"
552 else:
553 else:
553 title = header((title+":").ljust(title_width))
554 title = header((title+":").ljust(title_width))
554 out.append(cast_unicode(title) + cast_unicode(content))
555 out.append(cast_unicode(title) + cast_unicode(content))
555 return "\n".join(out)
556 return "\n".join(out)
556
557
557 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
558 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
558 pinfo_fields1 = [("Type", "type_name"),
559 pinfo_fields1 = [("Type", "type_name"),
559 ]
560 ]
560
561
561 pinfo_fields2 = [("String form", "string_form"),
562 pinfo_fields2 = [("String form", "string_form"),
562 ]
563 ]
563
564
564 pinfo_fields3 = [("Length", "length"),
565 pinfo_fields3 = [("Length", "length"),
565 ("File", "file"),
566 ("File", "file"),
566 ("Definition", "definition"),
567 ("Definition", "definition"),
567 ]
568 ]
568
569
569 pinfo_fields_obj = [("Class docstring", "class_docstring"),
570 pinfo_fields_obj = [("Class docstring", "class_docstring"),
570 ("Init docstring", "init_docstring"),
571 ("Init docstring", "init_docstring"),
571 ("Call def", "call_def"),
572 ("Call def", "call_def"),
572 ("Call docstring", "call_docstring")]
573 ("Call docstring", "call_docstring")]
573
574
574 def _format_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
575 def _format_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
575 """Format an info dict as text"""
576 """Format an info dict as text"""
576 info = self.info(obj, oname=oname, formatter=formatter,
577 info = self.info(obj, oname=oname, formatter=formatter,
577 info=info, detail_level=detail_level)
578 info=info, detail_level=detail_level)
578 displayfields = []
579 displayfields = []
579 def add_fields(fields):
580 def add_fields(fields):
580 for title, key in fields:
581 for title, key in fields:
581 field = info[key]
582 field = info[key]
582 if field is not None:
583 if field is not None:
583 displayfields.append((title, field.rstrip()))
584 displayfields.append((title, field.rstrip()))
584
585
585 add_fields(self.pinfo_fields1)
586 add_fields(self.pinfo_fields1)
586
587
587 # Base class for old-style instances
588 # Base class for old-style instances
588 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
589 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
589 displayfields.append(("Base Class", info['base_class'].rstrip()))
590 displayfields.append(("Base Class", info['base_class'].rstrip()))
590
591
591 add_fields(self.pinfo_fields2)
592 add_fields(self.pinfo_fields2)
592
593
593 # Namespace
594 # Namespace
594 if info['namespace'] != 'Interactive':
595 if info['namespace'] != 'Interactive':
595 displayfields.append(("Namespace", info['namespace'].rstrip()))
596 displayfields.append(("Namespace", info['namespace'].rstrip()))
596
597
597 add_fields(self.pinfo_fields3)
598 add_fields(self.pinfo_fields3)
598 if info['isclass'] and info['init_definition']:
599 if info['isclass'] and info['init_definition']:
599 displayfields.append(("Init definition",
600 displayfields.append(("Init definition",
600 info['init_definition'].rstrip()))
601 info['init_definition'].rstrip()))
601
602
602 # Source or docstring, depending on detail level and whether
603 # Source or docstring, depending on detail level and whether
603 # source found.
604 # source found.
604 if detail_level > 0 and info['source'] is not None:
605 if detail_level > 0 and info['source'] is not None:
605 displayfields.append(("Source",
606 displayfields.append(("Source",
606 self.format(cast_unicode(info['source']))))
607 self.format(cast_unicode(info['source']))))
607 elif info['docstring'] is not None:
608 elif info['docstring'] is not None:
608 displayfields.append(("Docstring", info["docstring"]))
609 displayfields.append(("Docstring", info["docstring"]))
609
610
610 # Constructor info for classes
611 # Constructor info for classes
611 if info['isclass']:
612 if info['isclass']:
612 if info['init_docstring'] is not None:
613 if info['init_docstring'] is not None:
613 displayfields.append(("Init docstring",
614 displayfields.append(("Init docstring",
614 info['init_docstring']))
615 info['init_docstring']))
615
616
616 # Info for objects:
617 # Info for objects:
617 else:
618 else:
618 add_fields(self.pinfo_fields_obj)
619 add_fields(self.pinfo_fields_obj)
619
620
620 if displayfields:
621 if displayfields:
621 return self._format_fields(displayfields)
622 return self._format_fields(displayfields)
622 else:
623 else:
623 return u''
624 return u''
624
625
625 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0):
626 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0):
626 """Show detailed information about an object.
627 """Show detailed information about an object.
627
628
628 Optional arguments:
629 Optional arguments:
629
630
630 - oname: name of the variable pointing to the object.
631 - oname: name of the variable pointing to the object.
631
632
632 - formatter: special formatter for docstrings (see pdoc)
633 - formatter: special formatter for docstrings (see pdoc)
633
634
634 - info: a structure with some information fields which may have been
635 - info: a structure with some information fields which may have been
635 precomputed already.
636 precomputed already.
636
637
637 - detail_level: if set to 1, more information is given.
638 - detail_level: if set to 1, more information is given.
638 """
639 """
639 text = self._format_info(obj, oname, formatter, info, detail_level)
640 text = self._format_info(obj, oname, formatter, info, detail_level)
640 if text:
641 if text:
641 page.page(text)
642 page.page(text)
642
643
643 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
644 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
644 """Compute a dict with detailed information about an object.
645 """Compute a dict with detailed information about an object.
645
646
646 Optional arguments:
647 Optional arguments:
647
648
648 - oname: name of the variable pointing to the object.
649 - oname: name of the variable pointing to the object.
649
650
650 - formatter: special formatter for docstrings (see pdoc)
651 - formatter: special formatter for docstrings (see pdoc)
651
652
652 - info: a structure with some information fields which may have been
653 - info: a structure with some information fields which may have been
653 precomputed already.
654 precomputed already.
654
655
655 - detail_level: if set to 1, more information is given.
656 - detail_level: if set to 1, more information is given.
656 """
657 """
657
658
658 obj_type = type(obj)
659 obj_type = type(obj)
659
660
660 if info is None:
661 if info is None:
661 ismagic = 0
662 ismagic = 0
662 isalias = 0
663 isalias = 0
663 ospace = ''
664 ospace = ''
664 else:
665 else:
665 ismagic = info.ismagic
666 ismagic = info.ismagic
666 isalias = info.isalias
667 isalias = info.isalias
667 ospace = info.namespace
668 ospace = info.namespace
668
669
669 # Get docstring, special-casing aliases:
670 # Get docstring, special-casing aliases:
670 if isalias:
671 if isalias:
671 if not callable(obj):
672 if not callable(obj):
672 try:
673 try:
673 ds = "Alias to the system command:\n %s" % obj[1]
674 ds = "Alias to the system command:\n %s" % obj[1]
674 except:
675 except:
675 ds = "Alias: " + str(obj)
676 ds = "Alias: " + str(obj)
676 else:
677 else:
677 ds = "Alias to " + str(obj)
678 ds = "Alias to " + str(obj)
678 if obj.__doc__:
679 if obj.__doc__:
679 ds += "\nDocstring:\n" + obj.__doc__
680 ds += "\nDocstring:\n" + obj.__doc__
680 else:
681 else:
681 ds = getdoc(obj)
682 ds = getdoc(obj)
682 if ds is None:
683 if ds is None:
683 ds = '<no docstring>'
684 ds = '<no docstring>'
684 if formatter is not None:
685 if formatter is not None:
685 ds = formatter(ds)
686 ds = formatter(ds)
686
687
687 # store output in a dict, we initialize it here and fill it as we go
688 # store output in a dict, we initialize it here and fill it as we go
688 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
689 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
689
690
690 string_max = 200 # max size of strings to show (snipped if longer)
691 string_max = 200 # max size of strings to show (snipped if longer)
691 shalf = int((string_max -5)/2)
692 shalf = int((string_max -5)/2)
692
693
693 if ismagic:
694 if ismagic:
694 obj_type_name = 'Magic function'
695 obj_type_name = 'Magic function'
695 elif isalias:
696 elif isalias:
696 obj_type_name = 'System alias'
697 obj_type_name = 'System alias'
697 else:
698 else:
698 obj_type_name = obj_type.__name__
699 obj_type_name = obj_type.__name__
699 out['type_name'] = obj_type_name
700 out['type_name'] = obj_type_name
700
701
701 try:
702 try:
702 bclass = obj.__class__
703 bclass = obj.__class__
703 out['base_class'] = str(bclass)
704 out['base_class'] = str(bclass)
704 except: pass
705 except: pass
705
706
706 # String form, but snip if too long in ? form (full in ??)
707 # String form, but snip if too long in ? form (full in ??)
707 if detail_level >= self.str_detail_level:
708 if detail_level >= self.str_detail_level:
708 try:
709 try:
709 ostr = str(obj)
710 ostr = str(obj)
710 str_head = 'string_form'
711 str_head = 'string_form'
711 if not detail_level and len(ostr)>string_max:
712 if not detail_level and len(ostr)>string_max:
712 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
713 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
713 ostr = ("\n" + " " * len(str_head.expandtabs())).\
714 ostr = ("\n" + " " * len(str_head.expandtabs())).\
714 join(q.strip() for q in ostr.split("\n"))
715 join(q.strip() for q in ostr.split("\n"))
715 out[str_head] = ostr
716 out[str_head] = ostr
716 except:
717 except:
717 pass
718 pass
718
719
719 if ospace:
720 if ospace:
720 out['namespace'] = ospace
721 out['namespace'] = ospace
721
722
722 # Length (for strings and lists)
723 # Length (for strings and lists)
723 try:
724 try:
724 out['length'] = str(len(obj))
725 out['length'] = str(len(obj))
725 except: pass
726 except: pass
726
727
727 # Filename where object was defined
728 # Filename where object was defined
728 binary_file = False
729 binary_file = False
729 fname = find_file(obj)
730 fname = find_file(obj)
730 if fname is None:
731 if fname is None:
731 # if anything goes wrong, we don't want to show source, so it's as
732 # if anything goes wrong, we don't want to show source, so it's as
732 # if the file was binary
733 # if the file was binary
733 binary_file = True
734 binary_file = True
734 else:
735 else:
735 if fname.endswith(('.so', '.dll', '.pyd')):
736 if fname.endswith(('.so', '.dll', '.pyd')):
736 binary_file = True
737 binary_file = True
737 elif fname.endswith('<string>'):
738 elif fname.endswith('<string>'):
738 fname = 'Dynamically generated function. No source code available.'
739 fname = 'Dynamically generated function. No source code available.'
739 out['file'] = fname
740 out['file'] = fname
740
741
741 # Original source code for a callable, class or property.
742 # Original source code for a callable, class or property.
742 if detail_level:
743 if detail_level:
743 # Flush the source cache because inspect can return out-of-date
744 # Flush the source cache because inspect can return out-of-date
744 # source
745 # source
745 linecache.checkcache()
746 linecache.checkcache()
746 try:
747 try:
747 if isinstance(obj, property) or not binary_file:
748 if isinstance(obj, property) or not binary_file:
748 src = getsource(obj, oname)
749 src = getsource(obj, oname)
749 if src is not None:
750 if src is not None:
750 src = src.rstrip()
751 src = src.rstrip()
751 out['source'] = src
752 out['source'] = src
752
753
753 except Exception:
754 except Exception:
754 pass
755 pass
755
756
756 # Add docstring only if no source is to be shown (avoid repetitions).
757 # Add docstring only if no source is to be shown (avoid repetitions).
757 if ds and out.get('source', None) is None:
758 if ds and out.get('source', None) is None:
758 out['docstring'] = ds
759 out['docstring'] = ds
759
760
760 # Constructor docstring for classes
761 # Constructor docstring for classes
761 if inspect.isclass(obj):
762 if inspect.isclass(obj):
762 out['isclass'] = True
763 out['isclass'] = True
763 # reconstruct the function definition and print it:
764 # reconstruct the function definition and print it:
764 try:
765 try:
765 obj_init = obj.__init__
766 obj_init = obj.__init__
766 except AttributeError:
767 except AttributeError:
767 init_def = init_ds = None
768 init_def = init_ds = None
768 else:
769 else:
769 init_def = self._getdef(obj_init,oname)
770 init_def = self._getdef(obj_init,oname)
770 init_ds = getdoc(obj_init)
771 init_ds = getdoc(obj_init)
771 # Skip Python's auto-generated docstrings
772 # Skip Python's auto-generated docstrings
772 if init_ds == _object_init_docstring:
773 if init_ds == _object_init_docstring:
773 init_ds = None
774 init_ds = None
774
775
775 if init_def or init_ds:
776 if init_def or init_ds:
776 if init_def:
777 if init_def:
777 out['init_definition'] = self.format(init_def)
778 out['init_definition'] = self.format(init_def)
778 if init_ds:
779 if init_ds:
779 out['init_docstring'] = init_ds
780 out['init_docstring'] = init_ds
780
781
781 # and class docstring for instances:
782 # and class docstring for instances:
782 else:
783 else:
783 # reconstruct the function definition and print it:
784 # reconstruct the function definition and print it:
784 defln = self._getdef(obj, oname)
785 defln = self._getdef(obj, oname)
785 if defln:
786 if defln:
786 out['definition'] = self.format(defln)
787 out['definition'] = self.format(defln)
787
788
788 # First, check whether the instance docstring is identical to the
789 # First, check whether the instance docstring is identical to the
789 # class one, and print it separately if they don't coincide. In
790 # class one, and print it separately if they don't coincide. In
790 # most cases they will, but it's nice to print all the info for
791 # most cases they will, but it's nice to print all the info for
791 # objects which use instance-customized docstrings.
792 # objects which use instance-customized docstrings.
792 if ds:
793 if ds:
793 try:
794 try:
794 cls = getattr(obj,'__class__')
795 cls = getattr(obj,'__class__')
795 except:
796 except:
796 class_ds = None
797 class_ds = None
797 else:
798 else:
798 class_ds = getdoc(cls)
799 class_ds = getdoc(cls)
799 # Skip Python's auto-generated docstrings
800 # Skip Python's auto-generated docstrings
800 if class_ds in _builtin_type_docstrings:
801 if class_ds in _builtin_type_docstrings:
801 class_ds = None
802 class_ds = None
802 if class_ds and ds != class_ds:
803 if class_ds and ds != class_ds:
803 out['class_docstring'] = class_ds
804 out['class_docstring'] = class_ds
804
805
805 # Next, try to show constructor docstrings
806 # Next, try to show constructor docstrings
806 try:
807 try:
807 init_ds = getdoc(obj.__init__)
808 init_ds = getdoc(obj.__init__)
808 # Skip Python's auto-generated docstrings
809 # Skip Python's auto-generated docstrings
809 if init_ds == _object_init_docstring:
810 if init_ds == _object_init_docstring:
810 init_ds = None
811 init_ds = None
811 except AttributeError:
812 except AttributeError:
812 init_ds = None
813 init_ds = None
813 if init_ds:
814 if init_ds:
814 out['init_docstring'] = init_ds
815 out['init_docstring'] = init_ds
815
816
816 # Call form docstring for callable instances
817 # Call form docstring for callable instances
817 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
818 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
818 call_def = self._getdef(obj.__call__, oname)
819 call_def = self._getdef(obj.__call__, oname)
819 if call_def:
820 if call_def:
820 call_def = self.format(call_def)
821 call_def = self.format(call_def)
821 # it may never be the case that call def and definition differ,
822 # it may never be the case that call def and definition differ,
822 # but don't include the same signature twice
823 # but don't include the same signature twice
823 if call_def != out.get('definition'):
824 if call_def != out.get('definition'):
824 out['call_def'] = call_def
825 out['call_def'] = call_def
825 call_ds = getdoc(obj.__call__)
826 call_ds = getdoc(obj.__call__)
826 # Skip Python's auto-generated docstrings
827 # Skip Python's auto-generated docstrings
827 if call_ds == _func_call_docstring:
828 if call_ds == _func_call_docstring:
828 call_ds = None
829 call_ds = None
829 if call_ds:
830 if call_ds:
830 out['call_docstring'] = call_ds
831 out['call_docstring'] = call_ds
831
832
832 # Compute the object's argspec as a callable. The key is to decide
833 # Compute the object's argspec as a callable. The key is to decide
833 # whether to pull it from the object itself, from its __init__ or
834 # whether to pull it from the object itself, from its __init__ or
834 # from its __call__ method.
835 # from its __call__ method.
835
836
836 if inspect.isclass(obj):
837 if inspect.isclass(obj):
837 # Old-style classes need not have an __init__
838 # Old-style classes need not have an __init__
838 callable_obj = getattr(obj, "__init__", None)
839 callable_obj = getattr(obj, "__init__", None)
839 elif callable(obj):
840 elif callable(obj):
840 callable_obj = obj
841 callable_obj = obj
841 else:
842 else:
842 callable_obj = None
843 callable_obj = None
843
844
844 if callable_obj:
845 if callable_obj:
845 try:
846 try:
846 argspec = getargspec(callable_obj)
847 argspec = getargspec(callable_obj)
847 except (TypeError, AttributeError):
848 except (TypeError, AttributeError):
848 # For extensions/builtins we can't retrieve the argspec
849 # For extensions/builtins we can't retrieve the argspec
849 pass
850 pass
850 else:
851 else:
851 # named tuples' _asdict() method returns an OrderedDict, but we
852 # named tuples' _asdict() method returns an OrderedDict, but we
852 # we want a normal
853 # we want a normal
853 out['argspec'] = argspec_dict = dict(argspec._asdict())
854 out['argspec'] = argspec_dict = dict(argspec._asdict())
854 # We called this varkw before argspec became a named tuple.
855 # We called this varkw before argspec became a named tuple.
855 # With getfullargspec it's also called varkw.
856 # With getfullargspec it's also called varkw.
856 if 'varkw' not in argspec_dict:
857 if 'varkw' not in argspec_dict:
857 argspec_dict['varkw'] = argspec_dict.pop('keywords')
858 argspec_dict['varkw'] = argspec_dict.pop('keywords')
858
859
859 return object_info(**out)
860 return object_info(**out)
860
861
861 def psearch(self,pattern,ns_table,ns_search=[],
862 def psearch(self,pattern,ns_table,ns_search=[],
862 ignore_case=False,show_all=False):
863 ignore_case=False,show_all=False):
863 """Search namespaces with wildcards for objects.
864 """Search namespaces with wildcards for objects.
864
865
865 Arguments:
866 Arguments:
866
867
867 - pattern: string containing shell-like wildcards to use in namespace
868 - pattern: string containing shell-like wildcards to use in namespace
868 searches and optionally a type specification to narrow the search to
869 searches and optionally a type specification to narrow the search to
869 objects of that type.
870 objects of that type.
870
871
871 - ns_table: dict of name->namespaces for search.
872 - ns_table: dict of name->namespaces for search.
872
873
873 Optional arguments:
874 Optional arguments:
874
875
875 - ns_search: list of namespace names to include in search.
876 - ns_search: list of namespace names to include in search.
876
877
877 - ignore_case(False): make the search case-insensitive.
878 - ignore_case(False): make the search case-insensitive.
878
879
879 - show_all(False): show all names, including those starting with
880 - show_all(False): show all names, including those starting with
880 underscores.
881 underscores.
881 """
882 """
882 #print 'ps pattern:<%r>' % pattern # dbg
883 #print 'ps pattern:<%r>' % pattern # dbg
883
884
884 # defaults
885 # defaults
885 type_pattern = 'all'
886 type_pattern = 'all'
886 filter = ''
887 filter = ''
887
888
888 cmds = pattern.split()
889 cmds = pattern.split()
889 len_cmds = len(cmds)
890 len_cmds = len(cmds)
890 if len_cmds == 1:
891 if len_cmds == 1:
891 # Only filter pattern given
892 # Only filter pattern given
892 filter = cmds[0]
893 filter = cmds[0]
893 elif len_cmds == 2:
894 elif len_cmds == 2:
894 # Both filter and type specified
895 # Both filter and type specified
895 filter,type_pattern = cmds
896 filter,type_pattern = cmds
896 else:
897 else:
897 raise ValueError('invalid argument string for psearch: <%s>' %
898 raise ValueError('invalid argument string for psearch: <%s>' %
898 pattern)
899 pattern)
899
900
900 # filter search namespaces
901 # filter search namespaces
901 for name in ns_search:
902 for name in ns_search:
902 if name not in ns_table:
903 if name not in ns_table:
903 raise ValueError('invalid namespace <%s>. Valid names: %s' %
904 raise ValueError('invalid namespace <%s>. Valid names: %s' %
904 (name,ns_table.keys()))
905 (name,ns_table.keys()))
905
906
906 #print 'type_pattern:',type_pattern # dbg
907 #print 'type_pattern:',type_pattern # dbg
907 search_result, namespaces_seen = set(), set()
908 search_result, namespaces_seen = set(), set()
908 for ns_name in ns_search:
909 for ns_name in ns_search:
909 ns = ns_table[ns_name]
910 ns = ns_table[ns_name]
910 # Normally, locals and globals are the same, so we just check one.
911 # Normally, locals and globals are the same, so we just check one.
911 if id(ns) in namespaces_seen:
912 if id(ns) in namespaces_seen:
912 continue
913 continue
913 namespaces_seen.add(id(ns))
914 namespaces_seen.add(id(ns))
914 tmp_res = list_namespace(ns, type_pattern, filter,
915 tmp_res = list_namespace(ns, type_pattern, filter,
915 ignore_case=ignore_case, show_all=show_all)
916 ignore_case=ignore_case, show_all=show_all)
916 search_result.update(tmp_res)
917 search_result.update(tmp_res)
917
918
918 page.page('\n'.join(sorted(search_result)))
919 page.page('\n'.join(sorted(search_result)))
General Comments 0
You need to be logged in to leave comments. Login now