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