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