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