##// END OF EJS Templates
Small fix to prevent the display of auto-generated module docstrings that have no useful info
fperez -
Show More
@@ -1,568 +1,569 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 $Id: OInspect.py 2573 2007-08-01 14:55:46Z vivainio $
9 $Id: OInspect.py 2584 2007-08-05 18:16:31Z fperez $
10 """
10 """
11
11
12 #*****************************************************************************
12 #*****************************************************************************
13 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
13 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #*****************************************************************************
17 #*****************************************************************************
18
18
19 from IPython import Release
19 from IPython import Release
20 __author__ = '%s <%s>' % Release.authors['Fernando']
20 __author__ = '%s <%s>' % Release.authors['Fernando']
21 __license__ = Release.license
21 __license__ = Release.license
22
22
23 __all__ = ['Inspector','InspectColors']
23 __all__ = ['Inspector','InspectColors']
24
24
25 # stdlib modules
25 # stdlib modules
26 import __builtin__
26 import __builtin__
27 import inspect
27 import inspect
28 import linecache
28 import linecache
29 import string
29 import string
30 import StringIO
30 import StringIO
31 import types
31 import types
32 import os
32 import os
33 import sys
33 import sys
34 # IPython's own
34 # IPython's own
35 from IPython import PyColorize
35 from IPython import PyColorize
36 from IPython.genutils import page,indent,Term,mkdict
36 from IPython.genutils import page,indent,Term,mkdict
37 from IPython.Itpl import itpl
37 from IPython.Itpl import itpl
38 from IPython.wildcard import list_namespace
38 from IPython.wildcard import list_namespace
39 from IPython.ColorANSI import *
39 from IPython.ColorANSI import *
40
40
41 #****************************************************************************
41 #****************************************************************************
42 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
42 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
43 # simply monkeypatch inspect with code copied from python 2.4.
43 # simply monkeypatch inspect with code copied from python 2.4.
44 if sys.version_info[:2] == (2,3):
44 if sys.version_info[:2] == (2,3):
45 from inspect import ismodule, getabsfile, modulesbyfile
45 from inspect import ismodule, getabsfile, modulesbyfile
46 def getmodule(object):
46 def getmodule(object):
47 """Return the module an object was defined in, or None if not found."""
47 """Return the module an object was defined in, or None if not found."""
48 if ismodule(object):
48 if ismodule(object):
49 return object
49 return object
50 if hasattr(object, '__module__'):
50 if hasattr(object, '__module__'):
51 return sys.modules.get(object.__module__)
51 return sys.modules.get(object.__module__)
52 try:
52 try:
53 file = getabsfile(object)
53 file = getabsfile(object)
54 except TypeError:
54 except TypeError:
55 return None
55 return None
56 if file in modulesbyfile:
56 if file in modulesbyfile:
57 return sys.modules.get(modulesbyfile[file])
57 return sys.modules.get(modulesbyfile[file])
58 for module in sys.modules.values():
58 for module in sys.modules.values():
59 if hasattr(module, '__file__'):
59 if hasattr(module, '__file__'):
60 modulesbyfile[
60 modulesbyfile[
61 os.path.realpath(
61 os.path.realpath(
62 getabsfile(module))] = module.__name__
62 getabsfile(module))] = module.__name__
63 if file in modulesbyfile:
63 if file in modulesbyfile:
64 return sys.modules.get(modulesbyfile[file])
64 return sys.modules.get(modulesbyfile[file])
65 main = sys.modules['__main__']
65 main = sys.modules['__main__']
66 if not hasattr(object, '__name__'):
66 if not hasattr(object, '__name__'):
67 return None
67 return None
68 if hasattr(main, object.__name__):
68 if hasattr(main, object.__name__):
69 mainobject = getattr(main, object.__name__)
69 mainobject = getattr(main, object.__name__)
70 if mainobject is object:
70 if mainobject is object:
71 return main
71 return main
72 builtin = sys.modules['__builtin__']
72 builtin = sys.modules['__builtin__']
73 if hasattr(builtin, object.__name__):
73 if hasattr(builtin, object.__name__):
74 builtinobject = getattr(builtin, object.__name__)
74 builtinobject = getattr(builtin, object.__name__)
75 if builtinobject is object:
75 if builtinobject is object:
76 return builtin
76 return builtin
77
77
78 inspect.getmodule = getmodule
78 inspect.getmodule = getmodule
79
79
80 #****************************************************************************
80 #****************************************************************************
81 # Builtin color schemes
81 # Builtin color schemes
82
82
83 Colors = TermColors # just a shorthand
83 Colors = TermColors # just a shorthand
84
84
85 # Build a few color schemes
85 # Build a few color schemes
86 NoColor = ColorScheme(
86 NoColor = ColorScheme(
87 'NoColor',{
87 'NoColor',{
88 'header' : Colors.NoColor,
88 'header' : Colors.NoColor,
89 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
89 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
90 } )
90 } )
91
91
92 LinuxColors = ColorScheme(
92 LinuxColors = ColorScheme(
93 'Linux',{
93 'Linux',{
94 'header' : Colors.LightRed,
94 'header' : Colors.LightRed,
95 'normal' : Colors.Normal # color off (usu. Colors.Normal)
95 'normal' : Colors.Normal # color off (usu. Colors.Normal)
96 } )
96 } )
97
97
98 LightBGColors = ColorScheme(
98 LightBGColors = ColorScheme(
99 'LightBG',{
99 'LightBG',{
100 'header' : Colors.Red,
100 'header' : Colors.Red,
101 'normal' : Colors.Normal # color off (usu. Colors.Normal)
101 'normal' : Colors.Normal # color off (usu. Colors.Normal)
102 } )
102 } )
103
103
104 # Build table of color schemes (needed by the parser)
104 # Build table of color schemes (needed by the parser)
105 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
105 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
106 'Linux')
106 'Linux')
107
107
108 #****************************************************************************
108 #****************************************************************************
109 # Auxiliary functions
109 # Auxiliary functions
110 def getdoc(obj):
110 def getdoc(obj):
111 """Stable wrapper around inspect.getdoc.
111 """Stable wrapper around inspect.getdoc.
112
112
113 This can't crash because of attribute problems.
113 This can't crash because of attribute problems.
114
114
115 It also attempts to call a getdoc() method on the given object. This
115 It also attempts to call a getdoc() method on the given object. This
116 allows objects which provide their docstrings via non-standard mechanisms
116 allows objects which provide their docstrings via non-standard mechanisms
117 (like Pyro proxies) to still be inspected by ipython's ? system."""
117 (like Pyro proxies) to still be inspected by ipython's ? system."""
118
118
119 ds = None # default return value
119 ds = None # default return value
120 try:
120 try:
121 ds = inspect.getdoc(obj)
121 ds = inspect.getdoc(obj)
122 except:
122 except:
123 # Harden against an inspect failure, which can occur with
123 # Harden against an inspect failure, which can occur with
124 # SWIG-wrapped extensions.
124 # SWIG-wrapped extensions.
125 pass
125 pass
126 # Allow objects to offer customized documentation via a getdoc method:
126 # Allow objects to offer customized documentation via a getdoc method:
127 try:
127 try:
128 ds2 = obj.getdoc()
128 ds2 = obj.getdoc()
129 except:
129 except:
130 pass
130 pass
131 else:
131 else:
132 # if we get extra info, we add it to the normal docstring.
132 # if we get extra info, we add it to the normal docstring.
133 if ds is None:
133 if ds is None:
134 ds = ds2
134 ds = ds2
135 else:
135 else:
136 ds = '%s\n%s' % (ds,ds2)
136 ds = '%s\n%s' % (ds,ds2)
137 return ds
137 return ds
138
138
139 def getsource(obj,is_binary=False):
139 def getsource(obj,is_binary=False):
140 """Wrapper around inspect.getsource.
140 """Wrapper around inspect.getsource.
141
141
142 This can be modified by other projects to provide customized source
142 This can be modified by other projects to provide customized source
143 extraction.
143 extraction.
144
144
145 Inputs:
145 Inputs:
146
146
147 - obj: an object whose source code we will attempt to extract.
147 - obj: an object whose source code we will attempt to extract.
148
148
149 Optional inputs:
149 Optional inputs:
150
150
151 - is_binary: whether the object is known to come from a binary source.
151 - is_binary: whether the object is known to come from a binary source.
152 This implementation will skip returning any output for binary objects, but
152 This implementation will skip returning any output for binary objects, but
153 custom extractors may know how to meaningfully process them."""
153 custom extractors may know how to meaningfully process them."""
154
154
155 if is_binary:
155 if is_binary:
156 return None
156 return None
157 else:
157 else:
158 return inspect.getsource(obj)
158 return inspect.getsource(obj)
159
159
160 #****************************************************************************
160 #****************************************************************************
161 # Class definitions
161 # Class definitions
162
162
163 class myStringIO(StringIO.StringIO):
163 class myStringIO(StringIO.StringIO):
164 """Adds a writeln method to normal StringIO."""
164 """Adds a writeln method to normal StringIO."""
165 def writeln(self,*arg,**kw):
165 def writeln(self,*arg,**kw):
166 """Does a write() and then a write('\n')"""
166 """Does a write() and then a write('\n')"""
167 self.write(*arg,**kw)
167 self.write(*arg,**kw)
168 self.write('\n')
168 self.write('\n')
169
169
170 class Inspector:
170 class Inspector:
171 def __init__(self,color_table,code_color_table,scheme,
171 def __init__(self,color_table,code_color_table,scheme,
172 str_detail_level=0):
172 str_detail_level=0):
173 self.color_table = color_table
173 self.color_table = color_table
174 self.parser = PyColorize.Parser(code_color_table,out='str')
174 self.parser = PyColorize.Parser(code_color_table,out='str')
175 self.format = self.parser.format
175 self.format = self.parser.format
176 self.str_detail_level = str_detail_level
176 self.str_detail_level = str_detail_level
177 self.set_active_scheme(scheme)
177 self.set_active_scheme(scheme)
178
178
179 def __getargspec(self,obj):
179 def __getargspec(self,obj):
180 """Get the names and default values of a function's arguments.
180 """Get the names and default values of a function's arguments.
181
181
182 A tuple of four things is returned: (args, varargs, varkw, defaults).
182 A tuple of four things is returned: (args, varargs, varkw, defaults).
183 'args' is a list of the argument names (it may contain nested lists).
183 'args' is a list of the argument names (it may contain nested lists).
184 'varargs' and 'varkw' are the names of the * and ** arguments or None.
184 'varargs' and 'varkw' are the names of the * and ** arguments or None.
185 'defaults' is an n-tuple of the default values of the last n arguments.
185 'defaults' is an n-tuple of the default values of the last n arguments.
186
186
187 Modified version of inspect.getargspec from the Python Standard
187 Modified version of inspect.getargspec from the Python Standard
188 Library."""
188 Library."""
189
189
190 if inspect.isfunction(obj):
190 if inspect.isfunction(obj):
191 func_obj = obj
191 func_obj = obj
192 elif inspect.ismethod(obj):
192 elif inspect.ismethod(obj):
193 func_obj = obj.im_func
193 func_obj = obj.im_func
194 else:
194 else:
195 raise TypeError, 'arg is not a Python function'
195 raise TypeError, 'arg is not a Python function'
196 args, varargs, varkw = inspect.getargs(func_obj.func_code)
196 args, varargs, varkw = inspect.getargs(func_obj.func_code)
197 return args, varargs, varkw, func_obj.func_defaults
197 return args, varargs, varkw, func_obj.func_defaults
198
198
199 def __getdef(self,obj,oname=''):
199 def __getdef(self,obj,oname=''):
200 """Return the definition header for any callable object.
200 """Return the definition header for any callable object.
201
201
202 If any exception is generated, None is returned instead and the
202 If any exception is generated, None is returned instead and the
203 exception is suppressed."""
203 exception is suppressed."""
204
204
205 try:
205 try:
206 return oname + inspect.formatargspec(*self.__getargspec(obj))
206 return oname + inspect.formatargspec(*self.__getargspec(obj))
207 except:
207 except:
208 return None
208 return None
209
209
210 def __head(self,h):
210 def __head(self,h):
211 """Return a header string with proper colors."""
211 """Return a header string with proper colors."""
212 return '%s%s%s' % (self.color_table.active_colors.header,h,
212 return '%s%s%s' % (self.color_table.active_colors.header,h,
213 self.color_table.active_colors.normal)
213 self.color_table.active_colors.normal)
214
214
215 def set_active_scheme(self,scheme):
215 def set_active_scheme(self,scheme):
216 self.color_table.set_active_scheme(scheme)
216 self.color_table.set_active_scheme(scheme)
217 self.parser.color_table.set_active_scheme(scheme)
217 self.parser.color_table.set_active_scheme(scheme)
218
218
219 def noinfo(self,msg,oname):
219 def noinfo(self,msg,oname):
220 """Generic message when no information is found."""
220 """Generic message when no information is found."""
221 print 'No %s found' % msg,
221 print 'No %s found' % msg,
222 if oname:
222 if oname:
223 print 'for %s' % oname
223 print 'for %s' % oname
224 else:
224 else:
225 print
225 print
226
226
227 def pdef(self,obj,oname=''):
227 def pdef(self,obj,oname=''):
228 """Print the definition header for any callable object.
228 """Print the definition header for any callable object.
229
229
230 If the object is a class, print the constructor information."""
230 If the object is a class, print the constructor information."""
231
231
232 if not callable(obj):
232 if not callable(obj):
233 print 'Object is not callable.'
233 print 'Object is not callable.'
234 return
234 return
235
235
236 header = ''
236 header = ''
237
237
238 if inspect.isclass(obj):
238 if inspect.isclass(obj):
239 header = self.__head('Class constructor information:\n')
239 header = self.__head('Class constructor information:\n')
240 obj = obj.__init__
240 obj = obj.__init__
241 elif type(obj) is types.InstanceType or \
241 elif type(obj) is types.InstanceType or \
242 isinstance(obj,object):
242 isinstance(obj,object):
243 obj = obj.__call__
243 obj = obj.__call__
244
244
245 output = self.__getdef(obj,oname)
245 output = self.__getdef(obj,oname)
246 if output is None:
246 if output is None:
247 self.noinfo('definition header',oname)
247 self.noinfo('definition header',oname)
248 else:
248 else:
249 print >>Term.cout, header,self.format(output),
249 print >>Term.cout, header,self.format(output),
250
250
251 def pdoc(self,obj,oname='',formatter = None):
251 def pdoc(self,obj,oname='',formatter = None):
252 """Print the docstring for any object.
252 """Print the docstring for any object.
253
253
254 Optional:
254 Optional:
255 -formatter: a function to run the docstring through for specially
255 -formatter: a function to run the docstring through for specially
256 formatted docstrings."""
256 formatted docstrings."""
257
257
258 head = self.__head # so that itpl can find it even if private
258 head = self.__head # so that itpl can find it even if private
259 ds = getdoc(obj)
259 ds = getdoc(obj)
260 if formatter:
260 if formatter:
261 ds = formatter(ds)
261 ds = formatter(ds)
262 if inspect.isclass(obj):
262 if inspect.isclass(obj):
263 init_ds = getdoc(obj.__init__)
263 init_ds = getdoc(obj.__init__)
264 output = itpl('$head("Class Docstring:")\n'
264 output = itpl('$head("Class Docstring:")\n'
265 '$indent(ds)\n'
265 '$indent(ds)\n'
266 '$head("Constructor Docstring"):\n'
266 '$head("Constructor Docstring"):\n'
267 '$indent(init_ds)')
267 '$indent(init_ds)')
268 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
268 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
269 and hasattr(obj,'__call__'):
269 and hasattr(obj,'__call__'):
270 call_ds = getdoc(obj.__call__)
270 call_ds = getdoc(obj.__call__)
271 if call_ds:
271 if call_ds:
272 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
272 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
273 '$head("Calling Docstring:")\n$indent(call_ds)')
273 '$head("Calling Docstring:")\n$indent(call_ds)')
274 else:
274 else:
275 output = ds
275 output = ds
276 else:
276 else:
277 output = ds
277 output = ds
278 if output is None:
278 if output is None:
279 self.noinfo('documentation',oname)
279 self.noinfo('documentation',oname)
280 return
280 return
281 page(output)
281 page(output)
282
282
283 def psource(self,obj,oname=''):
283 def psource(self,obj,oname=''):
284 """Print the source code for an object."""
284 """Print the source code for an object."""
285
285
286 # Flush the source cache because inspect can return out-of-date source
286 # Flush the source cache because inspect can return out-of-date source
287 linecache.checkcache()
287 linecache.checkcache()
288 try:
288 try:
289 src = getsource(obj)
289 src = getsource(obj)
290 except:
290 except:
291 self.noinfo('source',oname)
291 self.noinfo('source',oname)
292 else:
292 else:
293 page(self.format(src))
293 page(self.format(src))
294
294
295 def pfile(self,obj,oname=''):
295 def pfile(self,obj,oname=''):
296 """Show the whole file where an object was defined."""
296 """Show the whole file where an object was defined."""
297 try:
297 try:
298 sourcelines,lineno = inspect.getsourcelines(obj)
298 sourcelines,lineno = inspect.getsourcelines(obj)
299 except:
299 except:
300 self.noinfo('file',oname)
300 self.noinfo('file',oname)
301 else:
301 else:
302 # run contents of file through pager starting at line
302 # run contents of file through pager starting at line
303 # where the object is defined
303 # where the object is defined
304 ofile = inspect.getabsfile(obj)
304 ofile = inspect.getabsfile(obj)
305
305
306 if (ofile.endswith('.so') or ofile.endswith('.dll')):
306 if (ofile.endswith('.so') or ofile.endswith('.dll')):
307 print 'File %r is binary, not printing.' % ofile
307 print 'File %r is binary, not printing.' % ofile
308 elif not os.path.isfile(ofile):
308 elif not os.path.isfile(ofile):
309 print 'File %r does not exist, not printing.' % ofile
309 print 'File %r does not exist, not printing.' % ofile
310 else:
310 else:
311 # Print only text files, not extension binaries.
311 # Print only text files, not extension binaries.
312 page(self.format(open(ofile).read()),lineno)
312 page(self.format(open(ofile).read()),lineno)
313 #page(self.format(open(inspect.getabsfile(obj)).read()),lineno)
313 #page(self.format(open(inspect.getabsfile(obj)).read()),lineno)
314
314
315 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
315 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
316 """Show detailed information about an object.
316 """Show detailed information about an object.
317
317
318 Optional arguments:
318 Optional arguments:
319
319
320 - oname: name of the variable pointing to the object.
320 - oname: name of the variable pointing to the object.
321
321
322 - formatter: special formatter for docstrings (see pdoc)
322 - formatter: special formatter for docstrings (see pdoc)
323
323
324 - info: a structure with some information fields which may have been
324 - info: a structure with some information fields which may have been
325 precomputed already.
325 precomputed already.
326
326
327 - detail_level: if set to 1, more information is given.
327 - detail_level: if set to 1, more information is given.
328 """
328 """
329
329
330 obj_type = type(obj)
330 obj_type = type(obj)
331
331
332 header = self.__head
332 header = self.__head
333 if info is None:
333 if info is None:
334 ismagic = 0
334 ismagic = 0
335 isalias = 0
335 isalias = 0
336 ospace = ''
336 ospace = ''
337 else:
337 else:
338 ismagic = info.ismagic
338 ismagic = info.ismagic
339 isalias = info.isalias
339 isalias = info.isalias
340 ospace = info.namespace
340 ospace = info.namespace
341 # Get docstring, special-casing aliases:
341 # Get docstring, special-casing aliases:
342 if isalias:
342 if isalias:
343 if not callable(obj):
343 if not callable(obj):
344 ds = "Alias to the system command:\n %s" % obj[1]
344 ds = "Alias to the system command:\n %s" % obj[1]
345 else:
345 else:
346 ds = "Alias to " + str(obj)
346 ds = "Alias to " + str(obj)
347 else:
347 else:
348 ds = getdoc(obj)
348 ds = getdoc(obj)
349 if ds is None:
349 if ds is None:
350 ds = '<no docstring>'
350 ds = '<no docstring>'
351 if formatter is not None:
351 if formatter is not None:
352 ds = formatter(ds)
352 ds = formatter(ds)
353
353
354 # store output in a list which gets joined with \n at the end.
354 # store output in a list which gets joined with \n at the end.
355 out = myStringIO()
355 out = myStringIO()
356
356
357 string_max = 200 # max size of strings to show (snipped if longer)
357 string_max = 200 # max size of strings to show (snipped if longer)
358 shalf = int((string_max -5)/2)
358 shalf = int((string_max -5)/2)
359
359
360 if ismagic:
360 if ismagic:
361 obj_type_name = 'Magic function'
361 obj_type_name = 'Magic function'
362 elif isalias:
362 elif isalias:
363 obj_type_name = 'System alias'
363 obj_type_name = 'System alias'
364 else:
364 else:
365 obj_type_name = obj_type.__name__
365 obj_type_name = obj_type.__name__
366 out.writeln(header('Type:\t\t')+obj_type_name)
366 out.writeln(header('Type:\t\t')+obj_type_name)
367
367
368 try:
368 try:
369 bclass = obj.__class__
369 bclass = obj.__class__
370 out.writeln(header('Base Class:\t')+str(bclass))
370 out.writeln(header('Base Class:\t')+str(bclass))
371 except: pass
371 except: pass
372
372
373 # String form, but snip if too long in ? form (full in ??)
373 # String form, but snip if too long in ? form (full in ??)
374 if detail_level >= self.str_detail_level:
374 if detail_level >= self.str_detail_level:
375 try:
375 try:
376 ostr = str(obj)
376 ostr = str(obj)
377 str_head = 'String Form:'
377 str_head = 'String Form:'
378 if not detail_level and len(ostr)>string_max:
378 if not detail_level and len(ostr)>string_max:
379 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
379 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
380 ostr = ("\n" + " " * len(str_head.expandtabs())).\
380 ostr = ("\n" + " " * len(str_head.expandtabs())).\
381 join(map(string.strip,ostr.split("\n")))
381 join(map(string.strip,ostr.split("\n")))
382 if ostr.find('\n') > -1:
382 if ostr.find('\n') > -1:
383 # Print multi-line strings starting at the next line.
383 # Print multi-line strings starting at the next line.
384 str_sep = '\n'
384 str_sep = '\n'
385 else:
385 else:
386 str_sep = '\t'
386 str_sep = '\t'
387 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
387 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
388 except:
388 except:
389 pass
389 pass
390
390
391 if ospace:
391 if ospace:
392 out.writeln(header('Namespace:\t')+ospace)
392 out.writeln(header('Namespace:\t')+ospace)
393
393
394 # Length (for strings and lists)
394 # Length (for strings and lists)
395 try:
395 try:
396 length = str(len(obj))
396 length = str(len(obj))
397 out.writeln(header('Length:\t\t')+length)
397 out.writeln(header('Length:\t\t')+length)
398 except: pass
398 except: pass
399
399
400 # Filename where object was defined
400 # Filename where object was defined
401 binary_file = False
401 binary_file = False
402 try:
402 try:
403 fname = inspect.getabsfile(obj)
403 fname = inspect.getabsfile(obj)
404 if fname.endswith('<string>'):
404 if fname.endswith('<string>'):
405 fname = 'Dynamically generated function. No source code available.'
405 fname = 'Dynamically generated function. No source code available.'
406 if (fname.endswith('.so') or fname.endswith('.dll') or
406 if (fname.endswith('.so') or fname.endswith('.dll') or
407 not os.path.isfile(fname)):
407 not os.path.isfile(fname)):
408 binary_file = True
408 binary_file = True
409 out.writeln(header('File:\t\t')+fname)
409 out.writeln(header('File:\t\t')+fname)
410 except:
410 except:
411 # if anything goes wrong, we don't want to show source, so it's as
411 # if anything goes wrong, we don't want to show source, so it's as
412 # if the file was binary
412 # if the file was binary
413 binary_file = True
413 binary_file = True
414
414
415 # reconstruct the function definition and print it:
415 # reconstruct the function definition and print it:
416 defln = self.__getdef(obj,oname)
416 defln = self.__getdef(obj,oname)
417 if defln:
417 if defln:
418 out.write(header('Definition:\t')+self.format(defln))
418 out.write(header('Definition:\t')+self.format(defln))
419
419
420 # Docstrings only in detail 0 mode, since source contains them (we
420 # Docstrings only in detail 0 mode, since source contains them (we
421 # avoid repetitions). If source fails, we add them back, see below.
421 # avoid repetitions). If source fails, we add them back, see below.
422 if ds and detail_level == 0:
422 if ds and detail_level == 0:
423 out.writeln(header('Docstring:\n') + indent(ds))
423 out.writeln(header('Docstring:\n') + indent(ds))
424
424
425
425
426 # Original source code for any callable
426 # Original source code for any callable
427 if detail_level:
427 if detail_level:
428 # Flush the source cache because inspect can return out-of-date source
428 # Flush the source cache because inspect can return out-of-date source
429 linecache.checkcache()
429 linecache.checkcache()
430 source_success = False
430 source_success = False
431 try:
431 try:
432 source = self.format(getsource(obj,binary_file))
432 source = self.format(getsource(obj,binary_file))
433 if source:
433 if source:
434 out.write(header('Source:\n')+source.rstrip())
434 out.write(header('Source:\n')+source.rstrip())
435 source_success = True
435 source_success = True
436 except Exception, msg:
436 except Exception, msg:
437 pass
437 pass
438
438
439 if ds and not source_success:
439 if ds and not source_success:
440 out.writeln(header('Docstring [source file open failed]:\n')
440 out.writeln(header('Docstring [source file open failed]:\n')
441 + indent(ds))
441 + indent(ds))
442
442
443 # Constructor docstring for classes
443 # Constructor docstring for classes
444 if inspect.isclass(obj):
444 if inspect.isclass(obj):
445 # reconstruct the function definition and print it:
445 # reconstruct the function definition and print it:
446 try:
446 try:
447 obj_init = obj.__init__
447 obj_init = obj.__init__
448 except AttributeError:
448 except AttributeError:
449 init_def = init_ds = None
449 init_def = init_ds = None
450 else:
450 else:
451 init_def = self.__getdef(obj_init,oname)
451 init_def = self.__getdef(obj_init,oname)
452 init_ds = getdoc(obj_init)
452 init_ds = getdoc(obj_init)
453
453
454 if init_def or init_ds:
454 if init_def or init_ds:
455 out.writeln(header('\nConstructor information:'))
455 out.writeln(header('\nConstructor information:'))
456 if init_def:
456 if init_def:
457 out.write(header('Definition:\t')+ self.format(init_def))
457 out.write(header('Definition:\t')+ self.format(init_def))
458 if init_ds:
458 if init_ds:
459 out.writeln(header('Docstring:\n') + indent(init_ds))
459 out.writeln(header('Docstring:\n') + indent(init_ds))
460 # and class docstring for instances:
460 # and class docstring for instances:
461 elif obj_type is types.InstanceType or \
461 elif obj_type is types.InstanceType or \
462 isinstance(obj,object):
462 isinstance(obj,object):
463
463
464 # First, check whether the instance docstring is identical to the
464 # First, check whether the instance docstring is identical to the
465 # class one, and print it separately if they don't coincide. In
465 # class one, and print it separately if they don't coincide. In
466 # most cases they will, but it's nice to print all the info for
466 # most cases they will, but it's nice to print all the info for
467 # objects which use instance-customized docstrings.
467 # objects which use instance-customized docstrings.
468 if ds:
468 if ds:
469 class_ds = getdoc(obj.__class__)
469 class_ds = getdoc(obj.__class__)
470 # Skip Python's auto-generated docstrings
470 # Skip Python's auto-generated docstrings
471 if class_ds and \
471 if class_ds and \
472 (class_ds.startswith('function(code, globals[,') or \
472 (class_ds.startswith('function(code, globals[,') or \
473 class_ds.startswith('instancemethod(function, instance,')):
473 class_ds.startswith('instancemethod(function, instance,') or \
474 class_ds.startswith('module(name[,') ):
474 class_ds = None
475 class_ds = None
475 if class_ds and ds != class_ds:
476 if class_ds and ds != class_ds:
476 out.writeln(header('Class Docstring:\n') +
477 out.writeln(header('Class Docstring:\n') +
477 indent(class_ds))
478 indent(class_ds))
478
479
479 # Next, try to show constructor docstrings
480 # Next, try to show constructor docstrings
480 try:
481 try:
481 init_ds = getdoc(obj.__init__)
482 init_ds = getdoc(obj.__init__)
482 # Skip Python's auto-generated docstrings
483 # Skip Python's auto-generated docstrings
483 if init_ds.startswith('x.__init__(...) initializes x'):
484 if init_ds.startswith('x.__init__(...) initializes x'):
484 init_ds = None
485 init_ds = None
485 except AttributeError:
486 except AttributeError:
486 init_ds = None
487 init_ds = None
487 if init_ds:
488 if init_ds:
488 out.writeln(header('Constructor Docstring:\n') +
489 out.writeln(header('Constructor Docstring:\n') +
489 indent(init_ds))
490 indent(init_ds))
490
491
491 # Call form docstring for callable instances
492 # Call form docstring for callable instances
492 if hasattr(obj,'__call__'):
493 if hasattr(obj,'__call__'):
493 #out.writeln(header('Callable:\t')+'Yes')
494 #out.writeln(header('Callable:\t')+'Yes')
494 call_def = self.__getdef(obj.__call__,oname)
495 call_def = self.__getdef(obj.__call__,oname)
495 #if call_def is None:
496 #if call_def is None:
496 # out.writeln(header('Call def:\t')+
497 # out.writeln(header('Call def:\t')+
497 # 'Calling definition not available.')
498 # 'Calling definition not available.')
498 if call_def is not None:
499 if call_def is not None:
499 out.writeln(header('Call def:\t')+self.format(call_def))
500 out.writeln(header('Call def:\t')+self.format(call_def))
500 call_ds = getdoc(obj.__call__)
501 call_ds = getdoc(obj.__call__)
501 # Skip Python's auto-generated docstrings
502 # Skip Python's auto-generated docstrings
502 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
503 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
503 call_ds = None
504 call_ds = None
504 if call_ds:
505 if call_ds:
505 out.writeln(header('Call docstring:\n') + indent(call_ds))
506 out.writeln(header('Call docstring:\n') + indent(call_ds))
506
507
507 # Finally send to printer/pager
508 # Finally send to printer/pager
508 output = out.getvalue()
509 output = out.getvalue()
509 if output:
510 if output:
510 page(output)
511 page(output)
511 # end pinfo
512 # end pinfo
512
513
513 def psearch(self,pattern,ns_table,ns_search=[],
514 def psearch(self,pattern,ns_table,ns_search=[],
514 ignore_case=False,show_all=False):
515 ignore_case=False,show_all=False):
515 """Search namespaces with wildcards for objects.
516 """Search namespaces with wildcards for objects.
516
517
517 Arguments:
518 Arguments:
518
519
519 - pattern: string containing shell-like wildcards to use in namespace
520 - pattern: string containing shell-like wildcards to use in namespace
520 searches and optionally a type specification to narrow the search to
521 searches and optionally a type specification to narrow the search to
521 objects of that type.
522 objects of that type.
522
523
523 - ns_table: dict of name->namespaces for search.
524 - ns_table: dict of name->namespaces for search.
524
525
525 Optional arguments:
526 Optional arguments:
526
527
527 - ns_search: list of namespace names to include in search.
528 - ns_search: list of namespace names to include in search.
528
529
529 - ignore_case(False): make the search case-insensitive.
530 - ignore_case(False): make the search case-insensitive.
530
531
531 - show_all(False): show all names, including those starting with
532 - show_all(False): show all names, including those starting with
532 underscores.
533 underscores.
533 """
534 """
534 #print 'ps pattern:<%r>' % pattern # dbg
535 #print 'ps pattern:<%r>' % pattern # dbg
535
536
536 # defaults
537 # defaults
537 type_pattern = 'all'
538 type_pattern = 'all'
538 filter = ''
539 filter = ''
539
540
540 cmds = pattern.split()
541 cmds = pattern.split()
541 len_cmds = len(cmds)
542 len_cmds = len(cmds)
542 if len_cmds == 1:
543 if len_cmds == 1:
543 # Only filter pattern given
544 # Only filter pattern given
544 filter = cmds[0]
545 filter = cmds[0]
545 elif len_cmds == 2:
546 elif len_cmds == 2:
546 # Both filter and type specified
547 # Both filter and type specified
547 filter,type_pattern = cmds
548 filter,type_pattern = cmds
548 else:
549 else:
549 raise ValueError('invalid argument string for psearch: <%s>' %
550 raise ValueError('invalid argument string for psearch: <%s>' %
550 pattern)
551 pattern)
551
552
552 # filter search namespaces
553 # filter search namespaces
553 for name in ns_search:
554 for name in ns_search:
554 if name not in ns_table:
555 if name not in ns_table:
555 raise ValueError('invalid namespace <%s>. Valid names: %s' %
556 raise ValueError('invalid namespace <%s>. Valid names: %s' %
556 (name,ns_table.keys()))
557 (name,ns_table.keys()))
557
558
558 #print 'type_pattern:',type_pattern # dbg
559 #print 'type_pattern:',type_pattern # dbg
559 search_result = []
560 search_result = []
560 for ns_name in ns_search:
561 for ns_name in ns_search:
561 ns = ns_table[ns_name]
562 ns = ns_table[ns_name]
562 tmp_res = list(list_namespace(ns,type_pattern,filter,
563 tmp_res = list(list_namespace(ns,type_pattern,filter,
563 ignore_case=ignore_case,
564 ignore_case=ignore_case,
564 show_all=show_all))
565 show_all=show_all))
565 search_result.extend(tmp_res)
566 search_result.extend(tmp_res)
566 search_result.sort()
567 search_result.sort()
567
568
568 page('\n'.join(search_result))
569 page('\n'.join(search_result))
General Comments 0
You need to be logged in to leave comments. Login now