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