##// END OF EJS Templates
Oinspect.py: Only show docstring for nonexisting/binary files...
vivainio -
Show More

The requested changes are too big and content was truncated. Show full diff

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