##// END OF EJS Templates
If object has a getdoc() method, override its normal docstring....
Thomas Kluyver -
Show More
@@ -1,774 +1,770 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 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 __all__ = ['Inspector','InspectColors']
17 __all__ = ['Inspector','InspectColors']
18
18
19 # stdlib modules
19 # stdlib modules
20 import __builtin__
20 import __builtin__
21 import inspect
21 import inspect
22 import linecache
22 import linecache
23 import os
23 import os
24 import sys
24 import sys
25 import types
25 import types
26 from collections import namedtuple
26 from collections import namedtuple
27 try:
27 try:
28 from itertools import izip_longest
28 from itertools import izip_longest
29 except ImportError:
29 except ImportError:
30 from itertools import zip_longest as izip_longest
30 from itertools import zip_longest as izip_longest
31
31
32 # IPython's own
32 # IPython's own
33 from IPython.core import page
33 from IPython.core import page
34 from IPython.testing.skipdoctest import skip_doctest_py3
34 from IPython.testing.skipdoctest import skip_doctest_py3
35 from IPython.utils import PyColorize
35 from IPython.utils import PyColorize
36 from IPython.utils import io
36 from IPython.utils import io
37 from IPython.utils import py3compat
37 from IPython.utils import py3compat
38 from IPython.utils.text import indent
38 from IPython.utils.text import indent
39 from IPython.utils.wildcard import list_namespace
39 from IPython.utils.wildcard import list_namespace
40 from IPython.utils.coloransi import *
40 from IPython.utils.coloransi import *
41
41
42 #****************************************************************************
42 #****************************************************************************
43 # Builtin color schemes
43 # Builtin color schemes
44
44
45 Colors = TermColors # just a shorthand
45 Colors = TermColors # just a shorthand
46
46
47 # Build a few color schemes
47 # Build a few color schemes
48 NoColor = ColorScheme(
48 NoColor = ColorScheme(
49 'NoColor',{
49 'NoColor',{
50 'header' : Colors.NoColor,
50 'header' : Colors.NoColor,
51 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
51 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
52 } )
52 } )
53
53
54 LinuxColors = ColorScheme(
54 LinuxColors = ColorScheme(
55 'Linux',{
55 'Linux',{
56 'header' : Colors.LightRed,
56 'header' : Colors.LightRed,
57 'normal' : Colors.Normal # color off (usu. Colors.Normal)
57 'normal' : Colors.Normal # color off (usu. Colors.Normal)
58 } )
58 } )
59
59
60 LightBGColors = ColorScheme(
60 LightBGColors = ColorScheme(
61 'LightBG',{
61 'LightBG',{
62 'header' : Colors.Red,
62 'header' : Colors.Red,
63 'normal' : Colors.Normal # color off (usu. Colors.Normal)
63 'normal' : Colors.Normal # color off (usu. Colors.Normal)
64 } )
64 } )
65
65
66 # Build table of color schemes (needed by the parser)
66 # Build table of color schemes (needed by the parser)
67 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
67 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
68 'Linux')
68 'Linux')
69
69
70 #****************************************************************************
70 #****************************************************************************
71 # Auxiliary functions and objects
71 # Auxiliary functions and objects
72
72
73 # See the messaging spec for the definition of all these fields. This list
73 # See the messaging spec for the definition of all these fields. This list
74 # effectively defines the order of display
74 # effectively defines the order of display
75 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
75 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
76 'length', 'file', 'definition', 'docstring', 'source',
76 'length', 'file', 'definition', 'docstring', 'source',
77 'init_definition', 'class_docstring', 'init_docstring',
77 'init_definition', 'class_docstring', 'init_docstring',
78 'call_def', 'call_docstring',
78 'call_def', 'call_docstring',
79 # These won't be printed but will be used to determine how to
79 # These won't be printed but will be used to determine how to
80 # format the object
80 # format the object
81 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
81 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
82 ]
82 ]
83
83
84
84
85 def object_info(**kw):
85 def object_info(**kw):
86 """Make an object info dict with all fields present."""
86 """Make an object info dict with all fields present."""
87 infodict = dict(izip_longest(info_fields, [None]))
87 infodict = dict(izip_longest(info_fields, [None]))
88 infodict.update(kw)
88 infodict.update(kw)
89 return infodict
89 return infodict
90
90
91
91
92 def getdoc(obj):
92 def getdoc(obj):
93 """Stable wrapper around inspect.getdoc.
93 """Stable wrapper around inspect.getdoc.
94
94
95 This can't crash because of attribute problems.
95 This can't crash because of attribute problems.
96
96
97 It also attempts to call a getdoc() method on the given object. This
97 It also attempts to call a getdoc() method on the given object. This
98 allows objects which provide their docstrings via non-standard mechanisms
98 allows objects which provide their docstrings via non-standard mechanisms
99 (like Pyro proxies) to still be inspected by ipython's ? system."""
99 (like Pyro proxies) to still be inspected by ipython's ? system."""
100
101 ds = None # default return value
102 try:
103 ds = inspect.getdoc(obj)
104 except:
105 # Harden against an inspect failure, which can occur with
106 # SWIG-wrapped extensions.
107 pass
108 # Allow objects to offer customized documentation via a getdoc method:
100 # Allow objects to offer customized documentation via a getdoc method:
109 try:
101 try:
110 ds2 = obj.getdoc()
102 ds = obj.getdoc()
111 except:
103 except Exception:
112 pass
104 pass
113 else:
105 else:
114 # if we get extra info, we add it to the normal docstring.
106 # if we get extra info, we add it to the normal docstring.
115 if ds is None:
107 if isinstance(ds, basestring):
116 ds = ds2
108 return ds
117 else:
109
118 ds = '%s\n%s' % (ds,ds2)
110 try:
119 return ds
111 return inspect.getdoc(obj)
112 except Exception:
113 # Harden against an inspect failure, which can occur with
114 # SWIG-wrapped extensions.
115 return None
120
116
121
117
122 def getsource(obj,is_binary=False):
118 def getsource(obj,is_binary=False):
123 """Wrapper around inspect.getsource.
119 """Wrapper around inspect.getsource.
124
120
125 This can be modified by other projects to provide customized source
121 This can be modified by other projects to provide customized source
126 extraction.
122 extraction.
127
123
128 Inputs:
124 Inputs:
129
125
130 - obj: an object whose source code we will attempt to extract.
126 - obj: an object whose source code we will attempt to extract.
131
127
132 Optional inputs:
128 Optional inputs:
133
129
134 - is_binary: whether the object is known to come from a binary source.
130 - is_binary: whether the object is known to come from a binary source.
135 This implementation will skip returning any output for binary objects, but
131 This implementation will skip returning any output for binary objects, but
136 custom extractors may know how to meaningfully process them."""
132 custom extractors may know how to meaningfully process them."""
137
133
138 if is_binary:
134 if is_binary:
139 return None
135 return None
140 else:
136 else:
141 # get source if obj was decorated with @decorator
137 # get source if obj was decorated with @decorator
142 if hasattr(obj,"__wrapped__"):
138 if hasattr(obj,"__wrapped__"):
143 obj = obj.__wrapped__
139 obj = obj.__wrapped__
144 try:
140 try:
145 src = inspect.getsource(obj)
141 src = inspect.getsource(obj)
146 except TypeError:
142 except TypeError:
147 if hasattr(obj,'__class__'):
143 if hasattr(obj,'__class__'):
148 src = inspect.getsource(obj.__class__)
144 src = inspect.getsource(obj.__class__)
149 return src
145 return src
150
146
151 def getargspec(obj):
147 def getargspec(obj):
152 """Get the names and default values of a function's arguments.
148 """Get the names and default values of a function's arguments.
153
149
154 A tuple of four things is returned: (args, varargs, varkw, defaults).
150 A tuple of four things is returned: (args, varargs, varkw, defaults).
155 'args' is a list of the argument names (it may contain nested lists).
151 'args' is a list of the argument names (it may contain nested lists).
156 'varargs' and 'varkw' are the names of the * and ** arguments or None.
152 'varargs' and 'varkw' are the names of the * and ** arguments or None.
157 'defaults' is an n-tuple of the default values of the last n arguments.
153 'defaults' is an n-tuple of the default values of the last n arguments.
158
154
159 Modified version of inspect.getargspec from the Python Standard
155 Modified version of inspect.getargspec from the Python Standard
160 Library."""
156 Library."""
161
157
162 if inspect.isfunction(obj):
158 if inspect.isfunction(obj):
163 func_obj = obj
159 func_obj = obj
164 elif inspect.ismethod(obj):
160 elif inspect.ismethod(obj):
165 func_obj = obj.im_func
161 func_obj = obj.im_func
166 elif hasattr(obj, '__call__'):
162 elif hasattr(obj, '__call__'):
167 func_obj = obj.__call__
163 func_obj = obj.__call__
168 else:
164 else:
169 raise TypeError('arg is not a Python function')
165 raise TypeError('arg is not a Python function')
170 args, varargs, varkw = inspect.getargs(func_obj.func_code)
166 args, varargs, varkw = inspect.getargs(func_obj.func_code)
171 return args, varargs, varkw, func_obj.func_defaults
167 return args, varargs, varkw, func_obj.func_defaults
172
168
173
169
174 def format_argspec(argspec):
170 def format_argspec(argspec):
175 """Format argspect, convenience wrapper around inspect's.
171 """Format argspect, convenience wrapper around inspect's.
176
172
177 This takes a dict instead of ordered arguments and calls
173 This takes a dict instead of ordered arguments and calls
178 inspect.format_argspec with the arguments in the necessary order.
174 inspect.format_argspec with the arguments in the necessary order.
179 """
175 """
180 return inspect.formatargspec(argspec['args'], argspec['varargs'],
176 return inspect.formatargspec(argspec['args'], argspec['varargs'],
181 argspec['varkw'], argspec['defaults'])
177 argspec['varkw'], argspec['defaults'])
182
178
183
179
184 def call_tip(oinfo, format_call=True):
180 def call_tip(oinfo, format_call=True):
185 """Extract call tip data from an oinfo dict.
181 """Extract call tip data from an oinfo dict.
186
182
187 Parameters
183 Parameters
188 ----------
184 ----------
189 oinfo : dict
185 oinfo : dict
190
186
191 format_call : bool, optional
187 format_call : bool, optional
192 If True, the call line is formatted and returned as a string. If not, a
188 If True, the call line is formatted and returned as a string. If not, a
193 tuple of (name, argspec) is returned.
189 tuple of (name, argspec) is returned.
194
190
195 Returns
191 Returns
196 -------
192 -------
197 call_info : None, str or (str, dict) tuple.
193 call_info : None, str or (str, dict) tuple.
198 When format_call is True, the whole call information is formattted as a
194 When format_call is True, the whole call information is formattted as a
199 single string. Otherwise, the object's name and its argspec dict are
195 single string. Otherwise, the object's name and its argspec dict are
200 returned. If no call information is available, None is returned.
196 returned. If no call information is available, None is returned.
201
197
202 docstring : str or None
198 docstring : str or None
203 The most relevant docstring for calling purposes is returned, if
199 The most relevant docstring for calling purposes is returned, if
204 available. The priority is: call docstring for callable instances, then
200 available. The priority is: call docstring for callable instances, then
205 constructor docstring for classes, then main object's docstring otherwise
201 constructor docstring for classes, then main object's docstring otherwise
206 (regular functions).
202 (regular functions).
207 """
203 """
208 # Get call definition
204 # Get call definition
209 argspec = oinfo.get('argspec')
205 argspec = oinfo.get('argspec')
210 if argspec is None:
206 if argspec is None:
211 call_line = None
207 call_line = None
212 else:
208 else:
213 # Callable objects will have 'self' as their first argument, prune
209 # Callable objects will have 'self' as their first argument, prune
214 # it out if it's there for clarity (since users do *not* pass an
210 # it out if it's there for clarity (since users do *not* pass an
215 # extra first argument explicitly).
211 # extra first argument explicitly).
216 try:
212 try:
217 has_self = argspec['args'][0] == 'self'
213 has_self = argspec['args'][0] == 'self'
218 except (KeyError, IndexError):
214 except (KeyError, IndexError):
219 pass
215 pass
220 else:
216 else:
221 if has_self:
217 if has_self:
222 argspec['args'] = argspec['args'][1:]
218 argspec['args'] = argspec['args'][1:]
223
219
224 call_line = oinfo['name']+format_argspec(argspec)
220 call_line = oinfo['name']+format_argspec(argspec)
225
221
226 # Now get docstring.
222 # Now get docstring.
227 # The priority is: call docstring, constructor docstring, main one.
223 # The priority is: call docstring, constructor docstring, main one.
228 doc = oinfo.get('call_docstring')
224 doc = oinfo.get('call_docstring')
229 if doc is None:
225 if doc is None:
230 doc = oinfo.get('init_docstring')
226 doc = oinfo.get('init_docstring')
231 if doc is None:
227 if doc is None:
232 doc = oinfo.get('docstring','')
228 doc = oinfo.get('docstring','')
233
229
234 return call_line, doc
230 return call_line, doc
235
231
236
232
237 class Inspector:
233 class Inspector:
238 def __init__(self, color_table=InspectColors,
234 def __init__(self, color_table=InspectColors,
239 code_color_table=PyColorize.ANSICodeColors,
235 code_color_table=PyColorize.ANSICodeColors,
240 scheme='NoColor',
236 scheme='NoColor',
241 str_detail_level=0):
237 str_detail_level=0):
242 self.color_table = color_table
238 self.color_table = color_table
243 self.parser = PyColorize.Parser(code_color_table,out='str')
239 self.parser = PyColorize.Parser(code_color_table,out='str')
244 self.format = self.parser.format
240 self.format = self.parser.format
245 self.str_detail_level = str_detail_level
241 self.str_detail_level = str_detail_level
246 self.set_active_scheme(scheme)
242 self.set_active_scheme(scheme)
247
243
248 def _getdef(self,obj,oname=''):
244 def _getdef(self,obj,oname=''):
249 """Return the definition header for any callable object.
245 """Return the definition header for any callable object.
250
246
251 If any exception is generated, None is returned instead and the
247 If any exception is generated, None is returned instead and the
252 exception is suppressed."""
248 exception is suppressed."""
253
249
254 try:
250 try:
255 # We need a plain string here, NOT unicode!
251 # We need a plain string here, NOT unicode!
256 hdef = oname + inspect.formatargspec(*getargspec(obj))
252 hdef = oname + inspect.formatargspec(*getargspec(obj))
257 return py3compat.unicode_to_str(hdef, 'ascii')
253 return py3compat.unicode_to_str(hdef, 'ascii')
258 except:
254 except:
259 return None
255 return None
260
256
261 def __head(self,h):
257 def __head(self,h):
262 """Return a header string with proper colors."""
258 """Return a header string with proper colors."""
263 return '%s%s%s' % (self.color_table.active_colors.header,h,
259 return '%s%s%s' % (self.color_table.active_colors.header,h,
264 self.color_table.active_colors.normal)
260 self.color_table.active_colors.normal)
265
261
266 def set_active_scheme(self,scheme):
262 def set_active_scheme(self,scheme):
267 self.color_table.set_active_scheme(scheme)
263 self.color_table.set_active_scheme(scheme)
268 self.parser.color_table.set_active_scheme(scheme)
264 self.parser.color_table.set_active_scheme(scheme)
269
265
270 def noinfo(self,msg,oname):
266 def noinfo(self,msg,oname):
271 """Generic message when no information is found."""
267 """Generic message when no information is found."""
272 print 'No %s found' % msg,
268 print 'No %s found' % msg,
273 if oname:
269 if oname:
274 print 'for %s' % oname
270 print 'for %s' % oname
275 else:
271 else:
276 print
272 print
277
273
278 def pdef(self,obj,oname=''):
274 def pdef(self,obj,oname=''):
279 """Print the definition header for any callable object.
275 """Print the definition header for any callable object.
280
276
281 If the object is a class, print the constructor information."""
277 If the object is a class, print the constructor information."""
282
278
283 if not callable(obj):
279 if not callable(obj):
284 print 'Object is not callable.'
280 print 'Object is not callable.'
285 return
281 return
286
282
287 header = ''
283 header = ''
288
284
289 if inspect.isclass(obj):
285 if inspect.isclass(obj):
290 header = self.__head('Class constructor information:\n')
286 header = self.__head('Class constructor information:\n')
291 obj = obj.__init__
287 obj = obj.__init__
292 elif type(obj) is types.InstanceType:
288 elif type(obj) is types.InstanceType:
293 obj = obj.__call__
289 obj = obj.__call__
294
290
295 output = self._getdef(obj,oname)
291 output = self._getdef(obj,oname)
296 if output is None:
292 if output is None:
297 self.noinfo('definition header',oname)
293 self.noinfo('definition header',oname)
298 else:
294 else:
299 print >>io.stdout, header,self.format(output),
295 print >>io.stdout, header,self.format(output),
300
296
301 # In Python 3, all classes are new-style, so they all have __init__.
297 # In Python 3, all classes are new-style, so they all have __init__.
302 @skip_doctest_py3
298 @skip_doctest_py3
303 def pdoc(self,obj,oname='',formatter = None):
299 def pdoc(self,obj,oname='',formatter = None):
304 """Print the docstring for any object.
300 """Print the docstring for any object.
305
301
306 Optional:
302 Optional:
307 -formatter: a function to run the docstring through for specially
303 -formatter: a function to run the docstring through for specially
308 formatted docstrings.
304 formatted docstrings.
309
305
310 Examples
306 Examples
311 --------
307 --------
312
308
313 In [1]: class NoInit:
309 In [1]: class NoInit:
314 ...: pass
310 ...: pass
315
311
316 In [2]: class NoDoc:
312 In [2]: class NoDoc:
317 ...: def __init__(self):
313 ...: def __init__(self):
318 ...: pass
314 ...: pass
319
315
320 In [3]: %pdoc NoDoc
316 In [3]: %pdoc NoDoc
321 No documentation found for NoDoc
317 No documentation found for NoDoc
322
318
323 In [4]: %pdoc NoInit
319 In [4]: %pdoc NoInit
324 No documentation found for NoInit
320 No documentation found for NoInit
325
321
326 In [5]: obj = NoInit()
322 In [5]: obj = NoInit()
327
323
328 In [6]: %pdoc obj
324 In [6]: %pdoc obj
329 No documentation found for obj
325 No documentation found for obj
330
326
331 In [5]: obj2 = NoDoc()
327 In [5]: obj2 = NoDoc()
332
328
333 In [6]: %pdoc obj2
329 In [6]: %pdoc obj2
334 No documentation found for obj2
330 No documentation found for obj2
335 """
331 """
336
332
337 head = self.__head # For convenience
333 head = self.__head # For convenience
338 lines = []
334 lines = []
339 ds = getdoc(obj)
335 ds = getdoc(obj)
340 if formatter:
336 if formatter:
341 ds = formatter(ds)
337 ds = formatter(ds)
342 if ds:
338 if ds:
343 lines.append(head("Class Docstring:"))
339 lines.append(head("Class Docstring:"))
344 lines.append(indent(ds))
340 lines.append(indent(ds))
345 if inspect.isclass(obj) and hasattr(obj, '__init__'):
341 if inspect.isclass(obj) and hasattr(obj, '__init__'):
346 init_ds = getdoc(obj.__init__)
342 init_ds = getdoc(obj.__init__)
347 if init_ds is not None:
343 if init_ds is not None:
348 lines.append(head("Constructor Docstring:"))
344 lines.append(head("Constructor Docstring:"))
349 lines.append(indent(init_ds))
345 lines.append(indent(init_ds))
350 elif hasattr(obj,'__call__'):
346 elif hasattr(obj,'__call__'):
351 call_ds = getdoc(obj.__call__)
347 call_ds = getdoc(obj.__call__)
352 if call_ds:
348 if call_ds:
353 lines.append(head("Calling Docstring:"))
349 lines.append(head("Calling Docstring:"))
354 lines.append(indent(call_ds))
350 lines.append(indent(call_ds))
355
351
356 if not lines:
352 if not lines:
357 self.noinfo('documentation',oname)
353 self.noinfo('documentation',oname)
358 else:
354 else:
359 page.page('\n'.join(lines))
355 page.page('\n'.join(lines))
360
356
361 def psource(self,obj,oname=''):
357 def psource(self,obj,oname=''):
362 """Print the source code for an object."""
358 """Print the source code for an object."""
363
359
364 # Flush the source cache because inspect can return out-of-date source
360 # Flush the source cache because inspect can return out-of-date source
365 linecache.checkcache()
361 linecache.checkcache()
366 try:
362 try:
367 src = getsource(obj)
363 src = getsource(obj)
368 except:
364 except:
369 self.noinfo('source',oname)
365 self.noinfo('source',oname)
370 else:
366 else:
371 page.page(self.format(py3compat.unicode_to_str(src)))
367 page.page(self.format(py3compat.unicode_to_str(src)))
372
368
373 def pfile(self,obj,oname=''):
369 def pfile(self,obj,oname=''):
374 """Show the whole file where an object was defined."""
370 """Show the whole file where an object was defined."""
375
371
376 try:
372 try:
377 try:
373 try:
378 lineno = inspect.getsourcelines(obj)[1]
374 lineno = inspect.getsourcelines(obj)[1]
379 except TypeError:
375 except TypeError:
380 # For instances, try the class object like getsource() does
376 # For instances, try the class object like getsource() does
381 if hasattr(obj,'__class__'):
377 if hasattr(obj,'__class__'):
382 lineno = inspect.getsourcelines(obj.__class__)[1]
378 lineno = inspect.getsourcelines(obj.__class__)[1]
383 # Adjust the inspected object so getabsfile() below works
379 # Adjust the inspected object so getabsfile() below works
384 obj = obj.__class__
380 obj = obj.__class__
385 except:
381 except:
386 self.noinfo('file',oname)
382 self.noinfo('file',oname)
387 return
383 return
388
384
389 # We only reach this point if object was successfully queried
385 # We only reach this point if object was successfully queried
390
386
391 # run contents of file through pager starting at line
387 # run contents of file through pager starting at line
392 # where the object is defined
388 # where the object is defined
393 ofile = inspect.getabsfile(obj)
389 ofile = inspect.getabsfile(obj)
394
390
395 if ofile.endswith(('.so', '.dll', '.pyd')):
391 if ofile.endswith(('.so', '.dll', '.pyd')):
396 print 'File %r is binary, not printing.' % ofile
392 print 'File %r is binary, not printing.' % ofile
397 elif not os.path.isfile(ofile):
393 elif not os.path.isfile(ofile):
398 print 'File %r does not exist, not printing.' % ofile
394 print 'File %r does not exist, not printing.' % ofile
399 else:
395 else:
400 # Print only text files, not extension binaries. Note that
396 # Print only text files, not extension binaries. Note that
401 # getsourcelines returns lineno with 1-offset and page() uses
397 # getsourcelines returns lineno with 1-offset and page() uses
402 # 0-offset, so we must adjust.
398 # 0-offset, so we must adjust.
403 page.page(self.format(open(ofile).read()),lineno-1)
399 page.page(self.format(open(ofile).read()),lineno-1)
404
400
405 def _format_fields(self, fields, title_width=12):
401 def _format_fields(self, fields, title_width=12):
406 """Formats a list of fields for display.
402 """Formats a list of fields for display.
407
403
408 Parameters
404 Parameters
409 ----------
405 ----------
410 fields : list
406 fields : list
411 A list of 2-tuples: (field_title, field_content)
407 A list of 2-tuples: (field_title, field_content)
412 title_width : int
408 title_width : int
413 How many characters to pad titles to. Default 12.
409 How many characters to pad titles to. Default 12.
414 """
410 """
415 out = []
411 out = []
416 header = self.__head
412 header = self.__head
417 for title, content in fields:
413 for title, content in fields:
418 if len(content.splitlines()) > 1:
414 if len(content.splitlines()) > 1:
419 title = header(title + ":") + "\n"
415 title = header(title + ":") + "\n"
420 else:
416 else:
421 title = header((title+":").ljust(title_width))
417 title = header((title+":").ljust(title_width))
422 out.append(title + content)
418 out.append(title + content)
423 return "\n".join(out)
419 return "\n".join(out)
424
420
425 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
421 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
426 pinfo_fields1 = [("Type", "type_name"),
422 pinfo_fields1 = [("Type", "type_name"),
427 ("Base Class", "base_class"),
423 ("Base Class", "base_class"),
428 ("String Form", "string_form"),
424 ("String Form", "string_form"),
429 ("Namespace", "namespace"),
425 ("Namespace", "namespace"),
430 ("Length", "length"),
426 ("Length", "length"),
431 ("File", "file"),
427 ("File", "file"),
432 ("Definition", "definition")]
428 ("Definition", "definition")]
433
429
434 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
430 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
435 ("Constructor Docstring","init_docstring"),
431 ("Constructor Docstring","init_docstring"),
436 ("Call def", "call_def"),
432 ("Call def", "call_def"),
437 ("Call docstring", "call_docstring")]
433 ("Call docstring", "call_docstring")]
438
434
439 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
435 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
440 """Show detailed information about an object.
436 """Show detailed information about an object.
441
437
442 Optional arguments:
438 Optional arguments:
443
439
444 - oname: name of the variable pointing to the object.
440 - oname: name of the variable pointing to the object.
445
441
446 - formatter: special formatter for docstrings (see pdoc)
442 - formatter: special formatter for docstrings (see pdoc)
447
443
448 - info: a structure with some information fields which may have been
444 - info: a structure with some information fields which may have been
449 precomputed already.
445 precomputed already.
450
446
451 - detail_level: if set to 1, more information is given.
447 - detail_level: if set to 1, more information is given.
452 """
448 """
453 info = self.info(obj, oname=oname, formatter=formatter,
449 info = self.info(obj, oname=oname, formatter=formatter,
454 info=info, detail_level=detail_level)
450 info=info, detail_level=detail_level)
455 displayfields = []
451 displayfields = []
456 for title, key in self.pinfo_fields1:
452 for title, key in self.pinfo_fields1:
457 field = info[key]
453 field = info[key]
458 if field is not None:
454 if field is not None:
459 displayfields.append((title, field.rstrip()))
455 displayfields.append((title, field.rstrip()))
460
456
461 # Source or docstring, depending on detail level and whether
457 # Source or docstring, depending on detail level and whether
462 # source found.
458 # source found.
463 if detail_level > 0 and info['source'] is not None:
459 if detail_level > 0 and info['source'] is not None:
464 displayfields.append(("Source", self.format(py3compat.unicode_to_str(info['source']))))
460 displayfields.append(("Source", self.format(py3compat.unicode_to_str(info['source']))))
465 elif info['docstring'] is not None:
461 elif info['docstring'] is not None:
466 displayfields.append(("Docstring", info["docstring"]))
462 displayfields.append(("Docstring", info["docstring"]))
467
463
468 # Constructor info for classes
464 # Constructor info for classes
469 if info['isclass']:
465 if info['isclass']:
470 if info['init_definition'] or info['init_docstring']:
466 if info['init_definition'] or info['init_docstring']:
471 displayfields.append(("Constructor information", ""))
467 displayfields.append(("Constructor information", ""))
472 if info['init_definition'] is not None:
468 if info['init_definition'] is not None:
473 displayfields.append((" Definition",
469 displayfields.append((" Definition",
474 info['init_definition'].rstrip()))
470 info['init_definition'].rstrip()))
475 if info['init_docstring'] is not None:
471 if info['init_docstring'] is not None:
476 displayfields.append((" Docstring",
472 displayfields.append((" Docstring",
477 indent(info['init_docstring'])))
473 indent(info['init_docstring'])))
478
474
479 # Info for objects:
475 # Info for objects:
480 else:
476 else:
481 for title, key in self.pinfo_fields_obj:
477 for title, key in self.pinfo_fields_obj:
482 field = info[key]
478 field = info[key]
483 if field is not None:
479 if field is not None:
484 displayfields.append((title, field.rstrip()))
480 displayfields.append((title, field.rstrip()))
485
481
486 # Finally send to printer/pager:
482 # Finally send to printer/pager:
487 if displayfields:
483 if displayfields:
488 page.page(self._format_fields(displayfields))
484 page.page(self._format_fields(displayfields))
489
485
490 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
486 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
491 """Compute a dict with detailed information about an object.
487 """Compute a dict with detailed information about an object.
492
488
493 Optional arguments:
489 Optional arguments:
494
490
495 - oname: name of the variable pointing to the object.
491 - oname: name of the variable pointing to the object.
496
492
497 - formatter: special formatter for docstrings (see pdoc)
493 - formatter: special formatter for docstrings (see pdoc)
498
494
499 - info: a structure with some information fields which may have been
495 - info: a structure with some information fields which may have been
500 precomputed already.
496 precomputed already.
501
497
502 - detail_level: if set to 1, more information is given.
498 - detail_level: if set to 1, more information is given.
503 """
499 """
504
500
505 obj_type = type(obj)
501 obj_type = type(obj)
506
502
507 header = self.__head
503 header = self.__head
508 if info is None:
504 if info is None:
509 ismagic = 0
505 ismagic = 0
510 isalias = 0
506 isalias = 0
511 ospace = ''
507 ospace = ''
512 else:
508 else:
513 ismagic = info.ismagic
509 ismagic = info.ismagic
514 isalias = info.isalias
510 isalias = info.isalias
515 ospace = info.namespace
511 ospace = info.namespace
516
512
517 # Get docstring, special-casing aliases:
513 # Get docstring, special-casing aliases:
518 if isalias:
514 if isalias:
519 if not callable(obj):
515 if not callable(obj):
520 try:
516 try:
521 ds = "Alias to the system command:\n %s" % obj[1]
517 ds = "Alias to the system command:\n %s" % obj[1]
522 except:
518 except:
523 ds = "Alias: " + str(obj)
519 ds = "Alias: " + str(obj)
524 else:
520 else:
525 ds = "Alias to " + str(obj)
521 ds = "Alias to " + str(obj)
526 if obj.__doc__:
522 if obj.__doc__:
527 ds += "\nDocstring:\n" + obj.__doc__
523 ds += "\nDocstring:\n" + obj.__doc__
528 else:
524 else:
529 ds = getdoc(obj)
525 ds = getdoc(obj)
530 if ds is None:
526 if ds is None:
531 ds = '<no docstring>'
527 ds = '<no docstring>'
532 if formatter is not None:
528 if formatter is not None:
533 ds = formatter(ds)
529 ds = formatter(ds)
534
530
535 # store output in a dict, we initialize it here and fill it as we go
531 # store output in a dict, we initialize it here and fill it as we go
536 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
532 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
537
533
538 string_max = 200 # max size of strings to show (snipped if longer)
534 string_max = 200 # max size of strings to show (snipped if longer)
539 shalf = int((string_max -5)/2)
535 shalf = int((string_max -5)/2)
540
536
541 if ismagic:
537 if ismagic:
542 obj_type_name = 'Magic function'
538 obj_type_name = 'Magic function'
543 elif isalias:
539 elif isalias:
544 obj_type_name = 'System alias'
540 obj_type_name = 'System alias'
545 else:
541 else:
546 obj_type_name = obj_type.__name__
542 obj_type_name = obj_type.__name__
547 out['type_name'] = obj_type_name
543 out['type_name'] = obj_type_name
548
544
549 try:
545 try:
550 bclass = obj.__class__
546 bclass = obj.__class__
551 out['base_class'] = str(bclass)
547 out['base_class'] = str(bclass)
552 except: pass
548 except: pass
553
549
554 # String form, but snip if too long in ? form (full in ??)
550 # String form, but snip if too long in ? form (full in ??)
555 if detail_level >= self.str_detail_level:
551 if detail_level >= self.str_detail_level:
556 try:
552 try:
557 ostr = str(obj)
553 ostr = str(obj)
558 str_head = 'string_form'
554 str_head = 'string_form'
559 if not detail_level and len(ostr)>string_max:
555 if not detail_level and len(ostr)>string_max:
560 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
556 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
561 ostr = ("\n" + " " * len(str_head.expandtabs())).\
557 ostr = ("\n" + " " * len(str_head.expandtabs())).\
562 join(q.strip() for q in ostr.split("\n"))
558 join(q.strip() for q in ostr.split("\n"))
563 out[str_head] = ostr
559 out[str_head] = ostr
564 except:
560 except:
565 pass
561 pass
566
562
567 if ospace:
563 if ospace:
568 out['namespace'] = ospace
564 out['namespace'] = ospace
569
565
570 # Length (for strings and lists)
566 # Length (for strings and lists)
571 try:
567 try:
572 out['length'] = str(len(obj))
568 out['length'] = str(len(obj))
573 except: pass
569 except: pass
574
570
575 # Filename where object was defined
571 # Filename where object was defined
576 binary_file = False
572 binary_file = False
577 try:
573 try:
578 try:
574 try:
579 fname = inspect.getabsfile(obj)
575 fname = inspect.getabsfile(obj)
580 except TypeError:
576 except TypeError:
581 # For an instance, the file that matters is where its class was
577 # For an instance, the file that matters is where its class was
582 # declared.
578 # declared.
583 if hasattr(obj,'__class__'):
579 if hasattr(obj,'__class__'):
584 fname = inspect.getabsfile(obj.__class__)
580 fname = inspect.getabsfile(obj.__class__)
585 if fname.endswith('<string>'):
581 if fname.endswith('<string>'):
586 fname = 'Dynamically generated function. No source code available.'
582 fname = 'Dynamically generated function. No source code available.'
587 if fname.endswith(('.so', '.dll', '.pyd')):
583 if fname.endswith(('.so', '.dll', '.pyd')):
588 binary_file = True
584 binary_file = True
589 out['file'] = fname
585 out['file'] = fname
590 except:
586 except:
591 # if anything goes wrong, we don't want to show source, so it's as
587 # if anything goes wrong, we don't want to show source, so it's as
592 # if the file was binary
588 # if the file was binary
593 binary_file = True
589 binary_file = True
594
590
595 # reconstruct the function definition and print it:
591 # reconstruct the function definition and print it:
596 defln = self._getdef(obj, oname)
592 defln = self._getdef(obj, oname)
597 if defln:
593 if defln:
598 out['definition'] = self.format(defln)
594 out['definition'] = self.format(defln)
599
595
600 # Docstrings only in detail 0 mode, since source contains them (we
596 # Docstrings only in detail 0 mode, since source contains them (we
601 # avoid repetitions). If source fails, we add them back, see below.
597 # avoid repetitions). If source fails, we add them back, see below.
602 if ds and detail_level == 0:
598 if ds and detail_level == 0:
603 out['docstring'] = ds
599 out['docstring'] = ds
604
600
605 # Original source code for any callable
601 # Original source code for any callable
606 if detail_level:
602 if detail_level:
607 # Flush the source cache because inspect can return out-of-date
603 # Flush the source cache because inspect can return out-of-date
608 # source
604 # source
609 linecache.checkcache()
605 linecache.checkcache()
610 source = None
606 source = None
611 try:
607 try:
612 try:
608 try:
613 source = getsource(obj,binary_file)
609 source = getsource(obj,binary_file)
614 except TypeError:
610 except TypeError:
615 if hasattr(obj,'__class__'):
611 if hasattr(obj,'__class__'):
616 source = getsource(obj.__class__,binary_file)
612 source = getsource(obj.__class__,binary_file)
617 if source is not None:
613 if source is not None:
618 out['source'] = source.rstrip()
614 out['source'] = source.rstrip()
619 except Exception:
615 except Exception:
620 pass
616 pass
621
617
622 if ds and source is None:
618 if ds and source is None:
623 out['docstring'] = ds
619 out['docstring'] = ds
624
620
625
621
626 # Constructor docstring for classes
622 # Constructor docstring for classes
627 if inspect.isclass(obj):
623 if inspect.isclass(obj):
628 out['isclass'] = True
624 out['isclass'] = True
629 # reconstruct the function definition and print it:
625 # reconstruct the function definition and print it:
630 try:
626 try:
631 obj_init = obj.__init__
627 obj_init = obj.__init__
632 except AttributeError:
628 except AttributeError:
633 init_def = init_ds = None
629 init_def = init_ds = None
634 else:
630 else:
635 init_def = self._getdef(obj_init,oname)
631 init_def = self._getdef(obj_init,oname)
636 init_ds = getdoc(obj_init)
632 init_ds = getdoc(obj_init)
637 # Skip Python's auto-generated docstrings
633 # Skip Python's auto-generated docstrings
638 if init_ds and \
634 if init_ds and \
639 init_ds.startswith('x.__init__(...) initializes'):
635 init_ds.startswith('x.__init__(...) initializes'):
640 init_ds = None
636 init_ds = None
641
637
642 if init_def or init_ds:
638 if init_def or init_ds:
643 if init_def:
639 if init_def:
644 out['init_definition'] = self.format(init_def)
640 out['init_definition'] = self.format(init_def)
645 if init_ds:
641 if init_ds:
646 out['init_docstring'] = init_ds
642 out['init_docstring'] = init_ds
647
643
648 # and class docstring for instances:
644 # and class docstring for instances:
649 else:
645 else:
650 # First, check whether the instance docstring is identical to the
646 # First, check whether the instance docstring is identical to the
651 # class one, and print it separately if they don't coincide. In
647 # class one, and print it separately if they don't coincide. In
652 # most cases they will, but it's nice to print all the info for
648 # most cases they will, but it's nice to print all the info for
653 # objects which use instance-customized docstrings.
649 # objects which use instance-customized docstrings.
654 if ds:
650 if ds:
655 try:
651 try:
656 cls = getattr(obj,'__class__')
652 cls = getattr(obj,'__class__')
657 except:
653 except:
658 class_ds = None
654 class_ds = None
659 else:
655 else:
660 class_ds = getdoc(cls)
656 class_ds = getdoc(cls)
661 # Skip Python's auto-generated docstrings
657 # Skip Python's auto-generated docstrings
662 if class_ds and \
658 if class_ds and \
663 (class_ds.startswith('function(code, globals[,') or \
659 (class_ds.startswith('function(code, globals[,') or \
664 class_ds.startswith('instancemethod(function, instance,') or \
660 class_ds.startswith('instancemethod(function, instance,') or \
665 class_ds.startswith('module(name[,') ):
661 class_ds.startswith('module(name[,') ):
666 class_ds = None
662 class_ds = None
667 if class_ds and ds != class_ds:
663 if class_ds and ds != class_ds:
668 out['class_docstring'] = class_ds
664 out['class_docstring'] = class_ds
669
665
670 # Next, try to show constructor docstrings
666 # Next, try to show constructor docstrings
671 try:
667 try:
672 init_ds = getdoc(obj.__init__)
668 init_ds = getdoc(obj.__init__)
673 # Skip Python's auto-generated docstrings
669 # Skip Python's auto-generated docstrings
674 if init_ds and \
670 if init_ds and \
675 init_ds.startswith('x.__init__(...) initializes'):
671 init_ds.startswith('x.__init__(...) initializes'):
676 init_ds = None
672 init_ds = None
677 except AttributeError:
673 except AttributeError:
678 init_ds = None
674 init_ds = None
679 if init_ds:
675 if init_ds:
680 out['init_docstring'] = init_ds
676 out['init_docstring'] = init_ds
681
677
682 # Call form docstring for callable instances
678 # Call form docstring for callable instances
683 if hasattr(obj, '__call__'):
679 if hasattr(obj, '__call__'):
684 call_def = self._getdef(obj.__call__, oname)
680 call_def = self._getdef(obj.__call__, oname)
685 if call_def is not None:
681 if call_def is not None:
686 out['call_def'] = self.format(call_def)
682 out['call_def'] = self.format(call_def)
687 call_ds = getdoc(obj.__call__)
683 call_ds = getdoc(obj.__call__)
688 # Skip Python's auto-generated docstrings
684 # Skip Python's auto-generated docstrings
689 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
685 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
690 call_ds = None
686 call_ds = None
691 if call_ds:
687 if call_ds:
692 out['call_docstring'] = call_ds
688 out['call_docstring'] = call_ds
693
689
694 # Compute the object's argspec as a callable. The key is to decide
690 # Compute the object's argspec as a callable. The key is to decide
695 # whether to pull it from the object itself, from its __init__ or
691 # whether to pull it from the object itself, from its __init__ or
696 # from its __call__ method.
692 # from its __call__ method.
697
693
698 if inspect.isclass(obj):
694 if inspect.isclass(obj):
699 # Old-style classes need not have an __init__
695 # Old-style classes need not have an __init__
700 callable_obj = getattr(obj, "__init__", None)
696 callable_obj = getattr(obj, "__init__", None)
701 elif callable(obj):
697 elif callable(obj):
702 callable_obj = obj
698 callable_obj = obj
703 else:
699 else:
704 callable_obj = None
700 callable_obj = None
705
701
706 if callable_obj:
702 if callable_obj:
707 try:
703 try:
708 args, varargs, varkw, defaults = getargspec(callable_obj)
704 args, varargs, varkw, defaults = getargspec(callable_obj)
709 except (TypeError, AttributeError):
705 except (TypeError, AttributeError):
710 # For extensions/builtins we can't retrieve the argspec
706 # For extensions/builtins we can't retrieve the argspec
711 pass
707 pass
712 else:
708 else:
713 out['argspec'] = dict(args=args, varargs=varargs,
709 out['argspec'] = dict(args=args, varargs=varargs,
714 varkw=varkw, defaults=defaults)
710 varkw=varkw, defaults=defaults)
715
711
716 return object_info(**out)
712 return object_info(**out)
717
713
718
714
719 def psearch(self,pattern,ns_table,ns_search=[],
715 def psearch(self,pattern,ns_table,ns_search=[],
720 ignore_case=False,show_all=False):
716 ignore_case=False,show_all=False):
721 """Search namespaces with wildcards for objects.
717 """Search namespaces with wildcards for objects.
722
718
723 Arguments:
719 Arguments:
724
720
725 - pattern: string containing shell-like wildcards to use in namespace
721 - pattern: string containing shell-like wildcards to use in namespace
726 searches and optionally a type specification to narrow the search to
722 searches and optionally a type specification to narrow the search to
727 objects of that type.
723 objects of that type.
728
724
729 - ns_table: dict of name->namespaces for search.
725 - ns_table: dict of name->namespaces for search.
730
726
731 Optional arguments:
727 Optional arguments:
732
728
733 - ns_search: list of namespace names to include in search.
729 - ns_search: list of namespace names to include in search.
734
730
735 - ignore_case(False): make the search case-insensitive.
731 - ignore_case(False): make the search case-insensitive.
736
732
737 - show_all(False): show all names, including those starting with
733 - show_all(False): show all names, including those starting with
738 underscores.
734 underscores.
739 """
735 """
740 #print 'ps pattern:<%r>' % pattern # dbg
736 #print 'ps pattern:<%r>' % pattern # dbg
741
737
742 # defaults
738 # defaults
743 type_pattern = 'all'
739 type_pattern = 'all'
744 filter = ''
740 filter = ''
745
741
746 cmds = pattern.split()
742 cmds = pattern.split()
747 len_cmds = len(cmds)
743 len_cmds = len(cmds)
748 if len_cmds == 1:
744 if len_cmds == 1:
749 # Only filter pattern given
745 # Only filter pattern given
750 filter = cmds[0]
746 filter = cmds[0]
751 elif len_cmds == 2:
747 elif len_cmds == 2:
752 # Both filter and type specified
748 # Both filter and type specified
753 filter,type_pattern = cmds
749 filter,type_pattern = cmds
754 else:
750 else:
755 raise ValueError('invalid argument string for psearch: <%s>' %
751 raise ValueError('invalid argument string for psearch: <%s>' %
756 pattern)
752 pattern)
757
753
758 # filter search namespaces
754 # filter search namespaces
759 for name in ns_search:
755 for name in ns_search:
760 if name not in ns_table:
756 if name not in ns_table:
761 raise ValueError('invalid namespace <%s>. Valid names: %s' %
757 raise ValueError('invalid namespace <%s>. Valid names: %s' %
762 (name,ns_table.keys()))
758 (name,ns_table.keys()))
763
759
764 #print 'type_pattern:',type_pattern # dbg
760 #print 'type_pattern:',type_pattern # dbg
765 search_result = []
761 search_result = []
766 for ns_name in ns_search:
762 for ns_name in ns_search:
767 ns = ns_table[ns_name]
763 ns = ns_table[ns_name]
768 tmp_res = list(list_namespace(ns,type_pattern,filter,
764 tmp_res = list(list_namespace(ns,type_pattern,filter,
769 ignore_case=ignore_case,
765 ignore_case=ignore_case,
770 show_all=show_all))
766 show_all=show_all))
771 search_result.extend(tmp_res)
767 search_result.extend(tmp_res)
772 search_result.sort()
768 search_result.sort()
773
769
774 page.page('\n'.join(search_result))
770 page.page('\n'.join(search_result))
General Comments 0
You need to be logged in to leave comments. Login now