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