##// END OF EJS Templates
Remove unused import
Fernando Perez -
Show More
@@ -1,610 +1,610 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 2843 2007-10-15 21:22:32Z fperez $
9 $Id: OInspect.py 2843 2007-10-15 21:22:32Z 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
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 try:
158 try:
159 src = inspect.getsource(obj)
159 src = inspect.getsource(obj)
160 except TypeError:
160 except TypeError:
161 if hasattr(obj,'__class__'):
161 if hasattr(obj,'__class__'):
162 src = inspect.getsource(obj.__class__)
162 src = inspect.getsource(obj.__class__)
163 return src
163 return src
164
164
165 #****************************************************************************
165 #****************************************************************************
166 # Class definitions
166 # Class definitions
167
167
168 class myStringIO(StringIO.StringIO):
168 class myStringIO(StringIO.StringIO):
169 """Adds a writeln method to normal StringIO."""
169 """Adds a writeln method to normal StringIO."""
170 def writeln(self,*arg,**kw):
170 def writeln(self,*arg,**kw):
171 """Does a write() and then a write('\n')"""
171 """Does a write() and then a write('\n')"""
172 self.write(*arg,**kw)
172 self.write(*arg,**kw)
173 self.write('\n')
173 self.write('\n')
174
174
175 class Inspector:
175 class Inspector:
176 def __init__(self,color_table,code_color_table,scheme,
176 def __init__(self,color_table,code_color_table,scheme,
177 str_detail_level=0):
177 str_detail_level=0):
178 self.color_table = color_table
178 self.color_table = color_table
179 self.parser = PyColorize.Parser(code_color_table,out='str')
179 self.parser = PyColorize.Parser(code_color_table,out='str')
180 self.format = self.parser.format
180 self.format = self.parser.format
181 self.str_detail_level = str_detail_level
181 self.str_detail_level = str_detail_level
182 self.set_active_scheme(scheme)
182 self.set_active_scheme(scheme)
183
183
184 def __getargspec(self,obj):
184 def __getargspec(self,obj):
185 """Get the names and default values of a function's arguments.
185 """Get the names and default values of a function's arguments.
186
186
187 A tuple of four things is returned: (args, varargs, varkw, defaults).
187 A tuple of four things is returned: (args, varargs, varkw, defaults).
188 'args' is a list of the argument names (it may contain nested lists).
188 'args' is a list of the argument names (it may contain nested lists).
189 'varargs' and 'varkw' are the names of the * and ** arguments or None.
189 'varargs' and 'varkw' are the names of the * and ** arguments or None.
190 'defaults' is an n-tuple of the default values of the last n arguments.
190 'defaults' is an n-tuple of the default values of the last n arguments.
191
191
192 Modified version of inspect.getargspec from the Python Standard
192 Modified version of inspect.getargspec from the Python Standard
193 Library."""
193 Library."""
194
194
195 if inspect.isfunction(obj):
195 if inspect.isfunction(obj):
196 func_obj = obj
196 func_obj = obj
197 elif inspect.ismethod(obj):
197 elif inspect.ismethod(obj):
198 func_obj = obj.im_func
198 func_obj = obj.im_func
199 else:
199 else:
200 raise TypeError, 'arg is not a Python function'
200 raise TypeError, 'arg is not a Python function'
201 args, varargs, varkw = inspect.getargs(func_obj.func_code)
201 args, varargs, varkw = inspect.getargs(func_obj.func_code)
202 return args, varargs, varkw, func_obj.func_defaults
202 return args, varargs, varkw, func_obj.func_defaults
203
203
204 def __getdef(self,obj,oname=''):
204 def __getdef(self,obj,oname=''):
205 """Return the definition header for any callable object.
205 """Return the definition header for any callable object.
206
206
207 If any exception is generated, None is returned instead and the
207 If any exception is generated, None is returned instead and the
208 exception is suppressed."""
208 exception is suppressed."""
209
209
210 try:
210 try:
211 return oname + inspect.formatargspec(*self.__getargspec(obj))
211 return oname + inspect.formatargspec(*self.__getargspec(obj))
212 except:
212 except:
213 return None
213 return None
214
214
215 def __head(self,h):
215 def __head(self,h):
216 """Return a header string with proper colors."""
216 """Return a header string with proper colors."""
217 return '%s%s%s' % (self.color_table.active_colors.header,h,
217 return '%s%s%s' % (self.color_table.active_colors.header,h,
218 self.color_table.active_colors.normal)
218 self.color_table.active_colors.normal)
219
219
220 def set_active_scheme(self,scheme):
220 def set_active_scheme(self,scheme):
221 self.color_table.set_active_scheme(scheme)
221 self.color_table.set_active_scheme(scheme)
222 self.parser.color_table.set_active_scheme(scheme)
222 self.parser.color_table.set_active_scheme(scheme)
223
223
224 def noinfo(self,msg,oname):
224 def noinfo(self,msg,oname):
225 """Generic message when no information is found."""
225 """Generic message when no information is found."""
226 print 'No %s found' % msg,
226 print 'No %s found' % msg,
227 if oname:
227 if oname:
228 print 'for %s' % oname
228 print 'for %s' % oname
229 else:
229 else:
230 print
230 print
231
231
232 def pdef(self,obj,oname=''):
232 def pdef(self,obj,oname=''):
233 """Print the definition header for any callable object.
233 """Print the definition header for any callable object.
234
234
235 If the object is a class, print the constructor information."""
235 If the object is a class, print the constructor information."""
236
236
237 if not callable(obj):
237 if not callable(obj):
238 print 'Object is not callable.'
238 print 'Object is not callable.'
239 return
239 return
240
240
241 header = ''
241 header = ''
242
242
243 if inspect.isclass(obj):
243 if inspect.isclass(obj):
244 header = self.__head('Class constructor information:\n')
244 header = self.__head('Class constructor information:\n')
245 obj = obj.__init__
245 obj = obj.__init__
246 elif type(obj) is types.InstanceType:
246 elif type(obj) is types.InstanceType:
247 obj = obj.__call__
247 obj = obj.__call__
248
248
249 output = self.__getdef(obj,oname)
249 output = self.__getdef(obj,oname)
250 if output is None:
250 if output is None:
251 self.noinfo('definition header',oname)
251 self.noinfo('definition header',oname)
252 else:
252 else:
253 print >>Term.cout, header,self.format(output),
253 print >>Term.cout, header,self.format(output),
254
254
255 def pdoc(self,obj,oname='',formatter = None):
255 def pdoc(self,obj,oname='',formatter = None):
256 """Print the docstring for any object.
256 """Print the docstring for any object.
257
257
258 Optional:
258 Optional:
259 -formatter: a function to run the docstring through for specially
259 -formatter: a function to run the docstring through for specially
260 formatted docstrings."""
260 formatted docstrings."""
261
261
262 head = self.__head # so that itpl can find it even if private
262 head = self.__head # so that itpl can find it even if private
263 ds = getdoc(obj)
263 ds = getdoc(obj)
264 if formatter:
264 if formatter:
265 ds = formatter(ds)
265 ds = formatter(ds)
266 if inspect.isclass(obj):
266 if inspect.isclass(obj):
267 init_ds = getdoc(obj.__init__)
267 init_ds = getdoc(obj.__init__)
268 output = itpl('$head("Class Docstring:")\n'
268 output = itpl('$head("Class Docstring:")\n'
269 '$indent(ds)\n'
269 '$indent(ds)\n'
270 '$head("Constructor Docstring"):\n'
270 '$head("Constructor Docstring"):\n'
271 '$indent(init_ds)')
271 '$indent(init_ds)')
272 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
272 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
273 and hasattr(obj,'__call__'):
273 and hasattr(obj,'__call__'):
274 call_ds = getdoc(obj.__call__)
274 call_ds = getdoc(obj.__call__)
275 if call_ds:
275 if call_ds:
276 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
276 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
277 '$head("Calling Docstring:")\n$indent(call_ds)')
277 '$head("Calling Docstring:")\n$indent(call_ds)')
278 else:
278 else:
279 output = ds
279 output = ds
280 else:
280 else:
281 output = ds
281 output = ds
282 if output is None:
282 if output is None:
283 self.noinfo('documentation',oname)
283 self.noinfo('documentation',oname)
284 return
284 return
285 page(output)
285 page(output)
286
286
287 def psource(self,obj,oname=''):
287 def psource(self,obj,oname=''):
288 """Print the source code for an object."""
288 """Print the source code for an object."""
289
289
290 # Flush the source cache because inspect can return out-of-date source
290 # Flush the source cache because inspect can return out-of-date source
291 linecache.checkcache()
291 linecache.checkcache()
292 try:
292 try:
293 src = getsource(obj)
293 src = getsource(obj)
294 except:
294 except:
295 self.noinfo('source',oname)
295 self.noinfo('source',oname)
296 else:
296 else:
297 page(self.format(src))
297 page(self.format(src))
298
298
299 def pfile(self,obj,oname=''):
299 def pfile(self,obj,oname=''):
300 """Show the whole file where an object was defined."""
300 """Show the whole file where an object was defined."""
301
301
302 try:
302 try:
303 try:
303 try:
304 lineno = inspect.getsourcelines(obj)[1]
304 lineno = inspect.getsourcelines(obj)[1]
305 except TypeError:
305 except TypeError:
306 # For instances, try the class object like getsource() does
306 # For instances, try the class object like getsource() does
307 if hasattr(obj,'__class__'):
307 if hasattr(obj,'__class__'):
308 lineno = inspect.getsourcelines(obj.__class__)[1]
308 lineno = inspect.getsourcelines(obj.__class__)[1]
309 # Adjust the inspected object so getabsfile() below works
309 # Adjust the inspected object so getabsfile() below works
310 obj = obj.__class__
310 obj = obj.__class__
311 except:
311 except:
312 self.noinfo('file',oname)
312 self.noinfo('file',oname)
313 return
313 return
314
314
315 # We only reach this point if object was successfully queried
315 # We only reach this point if object was successfully queried
316
316
317 # run contents of file through pager starting at line
317 # run contents of file through pager starting at line
318 # where the object is defined
318 # where the object is defined
319 ofile = inspect.getabsfile(obj)
319 ofile = inspect.getabsfile(obj)
320
320
321 if (ofile.endswith('.so') or ofile.endswith('.dll')):
321 if (ofile.endswith('.so') or ofile.endswith('.dll')):
322 print 'File %r is binary, not printing.' % ofile
322 print 'File %r is binary, not printing.' % ofile
323 elif not os.path.isfile(ofile):
323 elif not os.path.isfile(ofile):
324 print 'File %r does not exist, not printing.' % ofile
324 print 'File %r does not exist, not printing.' % ofile
325 else:
325 else:
326 # Print only text files, not extension binaries. Note that
326 # Print only text files, not extension binaries. Note that
327 # getsourcelines returns lineno with 1-offset and page() uses
327 # getsourcelines returns lineno with 1-offset and page() uses
328 # 0-offset, so we must adjust.
328 # 0-offset, so we must adjust.
329 page(self.format(open(ofile).read()),lineno-1)
329 page(self.format(open(ofile).read()),lineno-1)
330
330
331 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
331 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
332 """Show detailed information about an object.
332 """Show detailed information about an object.
333
333
334 Optional arguments:
334 Optional arguments:
335
335
336 - oname: name of the variable pointing to the object.
336 - oname: name of the variable pointing to the object.
337
337
338 - formatter: special formatter for docstrings (see pdoc)
338 - formatter: special formatter for docstrings (see pdoc)
339
339
340 - info: a structure with some information fields which may have been
340 - info: a structure with some information fields which may have been
341 precomputed already.
341 precomputed already.
342
342
343 - detail_level: if set to 1, more information is given.
343 - detail_level: if set to 1, more information is given.
344 """
344 """
345
345
346 obj_type = type(obj)
346 obj_type = type(obj)
347
347
348 header = self.__head
348 header = self.__head
349 if info is None:
349 if info is None:
350 ismagic = 0
350 ismagic = 0
351 isalias = 0
351 isalias = 0
352 ospace = ''
352 ospace = ''
353 else:
353 else:
354 ismagic = info.ismagic
354 ismagic = info.ismagic
355 isalias = info.isalias
355 isalias = info.isalias
356 ospace = info.namespace
356 ospace = info.namespace
357 # Get docstring, special-casing aliases:
357 # Get docstring, special-casing aliases:
358 if isalias:
358 if isalias:
359 if not callable(obj):
359 if not callable(obj):
360 try:
360 try:
361 ds = "Alias to the system command:\n %s" % obj[1]
361 ds = "Alias to the system command:\n %s" % obj[1]
362 except:
362 except:
363 ds = "Alias: " + str(obj)
363 ds = "Alias: " + str(obj)
364 else:
364 else:
365 ds = "Alias to " + str(obj)
365 ds = "Alias to " + str(obj)
366 if obj.__doc__:
366 if obj.__doc__:
367 ds += "\nDocstring:\n" + obj.__doc__
367 ds += "\nDocstring:\n" + obj.__doc__
368 else:
368 else:
369 ds = getdoc(obj)
369 ds = getdoc(obj)
370 if ds is None:
370 if ds is None:
371 ds = '<no docstring>'
371 ds = '<no docstring>'
372 if formatter is not None:
372 if formatter is not None:
373 ds = formatter(ds)
373 ds = formatter(ds)
374
374
375 # store output in a list which gets joined with \n at the end.
375 # store output in a list which gets joined with \n at the end.
376 out = myStringIO()
376 out = myStringIO()
377
377
378 string_max = 200 # max size of strings to show (snipped if longer)
378 string_max = 200 # max size of strings to show (snipped if longer)
379 shalf = int((string_max -5)/2)
379 shalf = int((string_max -5)/2)
380
380
381 if ismagic:
381 if ismagic:
382 obj_type_name = 'Magic function'
382 obj_type_name = 'Magic function'
383 elif isalias:
383 elif isalias:
384 obj_type_name = 'System alias'
384 obj_type_name = 'System alias'
385 else:
385 else:
386 obj_type_name = obj_type.__name__
386 obj_type_name = obj_type.__name__
387 out.writeln(header('Type:\t\t')+obj_type_name)
387 out.writeln(header('Type:\t\t')+obj_type_name)
388
388
389 try:
389 try:
390 bclass = obj.__class__
390 bclass = obj.__class__
391 out.writeln(header('Base Class:\t')+str(bclass))
391 out.writeln(header('Base Class:\t')+str(bclass))
392 except: pass
392 except: pass
393
393
394 # String form, but snip if too long in ? form (full in ??)
394 # String form, but snip if too long in ? form (full in ??)
395 if detail_level >= self.str_detail_level:
395 if detail_level >= self.str_detail_level:
396 try:
396 try:
397 ostr = str(obj)
397 ostr = str(obj)
398 str_head = 'String Form:'
398 str_head = 'String Form:'
399 if not detail_level and len(ostr)>string_max:
399 if not detail_level and len(ostr)>string_max:
400 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
400 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
401 ostr = ("\n" + " " * len(str_head.expandtabs())).\
401 ostr = ("\n" + " " * len(str_head.expandtabs())).\
402 join(map(string.strip,ostr.split("\n")))
402 join(map(string.strip,ostr.split("\n")))
403 if ostr.find('\n') > -1:
403 if ostr.find('\n') > -1:
404 # Print multi-line strings starting at the next line.
404 # Print multi-line strings starting at the next line.
405 str_sep = '\n'
405 str_sep = '\n'
406 else:
406 else:
407 str_sep = '\t'
407 str_sep = '\t'
408 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
408 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
409 except:
409 except:
410 pass
410 pass
411
411
412 if ospace:
412 if ospace:
413 out.writeln(header('Namespace:\t')+ospace)
413 out.writeln(header('Namespace:\t')+ospace)
414
414
415 # Length (for strings and lists)
415 # Length (for strings and lists)
416 try:
416 try:
417 length = str(len(obj))
417 length = str(len(obj))
418 out.writeln(header('Length:\t\t')+length)
418 out.writeln(header('Length:\t\t')+length)
419 except: pass
419 except: pass
420
420
421 # Filename where object was defined
421 # Filename where object was defined
422 binary_file = False
422 binary_file = False
423 try:
423 try:
424 try:
424 try:
425 fname = inspect.getabsfile(obj)
425 fname = inspect.getabsfile(obj)
426 except TypeError:
426 except TypeError:
427 # For an instance, the file that matters is where its class was
427 # For an instance, the file that matters is where its class was
428 # declared.
428 # declared.
429 if hasattr(obj,'__class__'):
429 if hasattr(obj,'__class__'):
430 fname = inspect.getabsfile(obj.__class__)
430 fname = inspect.getabsfile(obj.__class__)
431 if fname.endswith('<string>'):
431 if fname.endswith('<string>'):
432 fname = 'Dynamically generated function. No source code available.'
432 fname = 'Dynamically generated function. No source code available.'
433 if (fname.endswith('.so') or fname.endswith('.dll')):
433 if (fname.endswith('.so') or fname.endswith('.dll')):
434 binary_file = True
434 binary_file = True
435 out.writeln(header('File:\t\t')+fname)
435 out.writeln(header('File:\t\t')+fname)
436 except:
436 except:
437 # if anything goes wrong, we don't want to show source, so it's as
437 # if anything goes wrong, we don't want to show source, so it's as
438 # if the file was binary
438 # if the file was binary
439 binary_file = True
439 binary_file = True
440
440
441 # reconstruct the function definition and print it:
441 # reconstruct the function definition and print it:
442 defln = self.__getdef(obj,oname)
442 defln = self.__getdef(obj,oname)
443 if defln:
443 if defln:
444 out.write(header('Definition:\t')+self.format(defln))
444 out.write(header('Definition:\t')+self.format(defln))
445
445
446 # Docstrings only in detail 0 mode, since source contains them (we
446 # Docstrings only in detail 0 mode, since source contains them (we
447 # avoid repetitions). If source fails, we add them back, see below.
447 # avoid repetitions). If source fails, we add them back, see below.
448 if ds and detail_level == 0:
448 if ds and detail_level == 0:
449 out.writeln(header('Docstring:\n') + indent(ds))
449 out.writeln(header('Docstring:\n') + indent(ds))
450
450
451 # Original source code for any callable
451 # Original source code for any callable
452 if detail_level:
452 if detail_level:
453 # Flush the source cache because inspect can return out-of-date
453 # Flush the source cache because inspect can return out-of-date
454 # source
454 # source
455 linecache.checkcache()
455 linecache.checkcache()
456 source_success = False
456 source_success = False
457 try:
457 try:
458 try:
458 try:
459 src = getsource(obj,binary_file)
459 src = getsource(obj,binary_file)
460 except TypeError:
460 except TypeError:
461 if hasattr(obj,'__class__'):
461 if hasattr(obj,'__class__'):
462 src = getsource(obj.__class__,binary_file)
462 src = getsource(obj.__class__,binary_file)
463 if src is not None:
463 if src is not None:
464 source = self.format(src)
464 source = self.format(src)
465 out.write(header('Source:\n')+source.rstrip())
465 out.write(header('Source:\n')+source.rstrip())
466 source_success = True
466 source_success = True
467 except Exception, msg:
467 except Exception, msg:
468 pass
468 pass
469
469
470 if ds and not source_success:
470 if ds and not source_success:
471 out.writeln(header('Docstring [source file open failed]:\n')
471 out.writeln(header('Docstring [source file open failed]:\n')
472 + indent(ds))
472 + indent(ds))
473
473
474 # Constructor docstring for classes
474 # Constructor docstring for classes
475 if inspect.isclass(obj):
475 if inspect.isclass(obj):
476 # reconstruct the function definition and print it:
476 # reconstruct the function definition and print it:
477 try:
477 try:
478 obj_init = obj.__init__
478 obj_init = obj.__init__
479 except AttributeError:
479 except AttributeError:
480 init_def = init_ds = None
480 init_def = init_ds = None
481 else:
481 else:
482 init_def = self.__getdef(obj_init,oname)
482 init_def = self.__getdef(obj_init,oname)
483 init_ds = getdoc(obj_init)
483 init_ds = getdoc(obj_init)
484 # Skip Python's auto-generated docstrings
484 # Skip Python's auto-generated docstrings
485 if init_ds and \
485 if init_ds and \
486 init_ds.startswith('x.__init__(...) initializes'):
486 init_ds.startswith('x.__init__(...) initializes'):
487 init_ds = None
487 init_ds = None
488
488
489 if init_def or init_ds:
489 if init_def or init_ds:
490 out.writeln(header('\nConstructor information:'))
490 out.writeln(header('\nConstructor information:'))
491 if init_def:
491 if init_def:
492 out.write(header('Definition:\t')+ self.format(init_def))
492 out.write(header('Definition:\t')+ self.format(init_def))
493 if init_ds:
493 if init_ds:
494 out.writeln(header('Docstring:\n') + indent(init_ds))
494 out.writeln(header('Docstring:\n') + indent(init_ds))
495 # and class docstring for instances:
495 # and class docstring for instances:
496 elif obj_type is types.InstanceType or \
496 elif obj_type is types.InstanceType or \
497 isinstance(obj,object):
497 isinstance(obj,object):
498
498
499 # First, check whether the instance docstring is identical to the
499 # First, check whether the instance docstring is identical to the
500 # class one, and print it separately if they don't coincide. In
500 # class one, and print it separately if they don't coincide. In
501 # most cases they will, but it's nice to print all the info for
501 # most cases they will, but it's nice to print all the info for
502 # objects which use instance-customized docstrings.
502 # objects which use instance-customized docstrings.
503 if ds:
503 if ds:
504 try:
504 try:
505 cls = getattr(obj,'__class__')
505 cls = getattr(obj,'__class__')
506 except:
506 except:
507 class_ds = None
507 class_ds = None
508 else:
508 else:
509 class_ds = getdoc(cls)
509 class_ds = getdoc(cls)
510 # Skip Python's auto-generated docstrings
510 # Skip Python's auto-generated docstrings
511 if class_ds and \
511 if class_ds and \
512 (class_ds.startswith('function(code, globals[,') or \
512 (class_ds.startswith('function(code, globals[,') or \
513 class_ds.startswith('instancemethod(function, instance,') or \
513 class_ds.startswith('instancemethod(function, instance,') or \
514 class_ds.startswith('module(name[,') ):
514 class_ds.startswith('module(name[,') ):
515 class_ds = None
515 class_ds = None
516 if class_ds and ds != class_ds:
516 if class_ds and ds != class_ds:
517 out.writeln(header('Class Docstring:\n') +
517 out.writeln(header('Class Docstring:\n') +
518 indent(class_ds))
518 indent(class_ds))
519
519
520 # Next, try to show constructor docstrings
520 # Next, try to show constructor docstrings
521 try:
521 try:
522 init_ds = getdoc(obj.__init__)
522 init_ds = getdoc(obj.__init__)
523 # Skip Python's auto-generated docstrings
523 # Skip Python's auto-generated docstrings
524 if init_ds and \
524 if init_ds and \
525 init_ds.startswith('x.__init__(...) initializes'):
525 init_ds.startswith('x.__init__(...) initializes'):
526 init_ds = None
526 init_ds = None
527 except AttributeError:
527 except AttributeError:
528 init_ds = None
528 init_ds = None
529 if init_ds:
529 if init_ds:
530 out.writeln(header('Constructor Docstring:\n') +
530 out.writeln(header('Constructor Docstring:\n') +
531 indent(init_ds))
531 indent(init_ds))
532
532
533 # Call form docstring for callable instances
533 # Call form docstring for callable instances
534 if hasattr(obj,'__call__'):
534 if hasattr(obj,'__call__'):
535 #out.writeln(header('Callable:\t')+'Yes')
535 #out.writeln(header('Callable:\t')+'Yes')
536 call_def = self.__getdef(obj.__call__,oname)
536 call_def = self.__getdef(obj.__call__,oname)
537 #if call_def is None:
537 #if call_def is None:
538 # out.writeln(header('Call def:\t')+
538 # out.writeln(header('Call def:\t')+
539 # 'Calling definition not available.')
539 # 'Calling definition not available.')
540 if call_def is not None:
540 if call_def is not None:
541 out.writeln(header('Call def:\t')+self.format(call_def))
541 out.writeln(header('Call def:\t')+self.format(call_def))
542 call_ds = getdoc(obj.__call__)
542 call_ds = getdoc(obj.__call__)
543 # Skip Python's auto-generated docstrings
543 # Skip Python's auto-generated docstrings
544 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
544 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
545 call_ds = None
545 call_ds = None
546 if call_ds:
546 if call_ds:
547 out.writeln(header('Call docstring:\n') + indent(call_ds))
547 out.writeln(header('Call docstring:\n') + indent(call_ds))
548
548
549 # Finally send to printer/pager
549 # Finally send to printer/pager
550 output = out.getvalue()
550 output = out.getvalue()
551 if output:
551 if output:
552 page(output)
552 page(output)
553 # end pinfo
553 # end pinfo
554
554
555 def psearch(self,pattern,ns_table,ns_search=[],
555 def psearch(self,pattern,ns_table,ns_search=[],
556 ignore_case=False,show_all=False):
556 ignore_case=False,show_all=False):
557 """Search namespaces with wildcards for objects.
557 """Search namespaces with wildcards for objects.
558
558
559 Arguments:
559 Arguments:
560
560
561 - pattern: string containing shell-like wildcards to use in namespace
561 - pattern: string containing shell-like wildcards to use in namespace
562 searches and optionally a type specification to narrow the search to
562 searches and optionally a type specification to narrow the search to
563 objects of that type.
563 objects of that type.
564
564
565 - ns_table: dict of name->namespaces for search.
565 - ns_table: dict of name->namespaces for search.
566
566
567 Optional arguments:
567 Optional arguments:
568
568
569 - ns_search: list of namespace names to include in search.
569 - ns_search: list of namespace names to include in search.
570
570
571 - ignore_case(False): make the search case-insensitive.
571 - ignore_case(False): make the search case-insensitive.
572
572
573 - show_all(False): show all names, including those starting with
573 - show_all(False): show all names, including those starting with
574 underscores.
574 underscores.
575 """
575 """
576 #print 'ps pattern:<%r>' % pattern # dbg
576 #print 'ps pattern:<%r>' % pattern # dbg
577
577
578 # defaults
578 # defaults
579 type_pattern = 'all'
579 type_pattern = 'all'
580 filter = ''
580 filter = ''
581
581
582 cmds = pattern.split()
582 cmds = pattern.split()
583 len_cmds = len(cmds)
583 len_cmds = len(cmds)
584 if len_cmds == 1:
584 if len_cmds == 1:
585 # Only filter pattern given
585 # Only filter pattern given
586 filter = cmds[0]
586 filter = cmds[0]
587 elif len_cmds == 2:
587 elif len_cmds == 2:
588 # Both filter and type specified
588 # Both filter and type specified
589 filter,type_pattern = cmds
589 filter,type_pattern = cmds
590 else:
590 else:
591 raise ValueError('invalid argument string for psearch: <%s>' %
591 raise ValueError('invalid argument string for psearch: <%s>' %
592 pattern)
592 pattern)
593
593
594 # filter search namespaces
594 # filter search namespaces
595 for name in ns_search:
595 for name in ns_search:
596 if name not in ns_table:
596 if name not in ns_table:
597 raise ValueError('invalid namespace <%s>. Valid names: %s' %
597 raise ValueError('invalid namespace <%s>. Valid names: %s' %
598 (name,ns_table.keys()))
598 (name,ns_table.keys()))
599
599
600 #print 'type_pattern:',type_pattern # dbg
600 #print 'type_pattern:',type_pattern # dbg
601 search_result = []
601 search_result = []
602 for ns_name in ns_search:
602 for ns_name in ns_search:
603 ns = ns_table[ns_name]
603 ns = ns_table[ns_name]
604 tmp_res = list(list_namespace(ns,type_pattern,filter,
604 tmp_res = list(list_namespace(ns,type_pattern,filter,
605 ignore_case=ignore_case,
605 ignore_case=ignore_case,
606 show_all=show_all))
606 show_all=show_all))
607 search_result.extend(tmp_res)
607 search_result.extend(tmp_res)
608 search_result.sort()
608 search_result.sort()
609
609
610 page('\n'.join(search_result))
610 page('\n'.join(search_result))
General Comments 0
You need to be logged in to leave comments. Login now