##// END OF EJS Templates
Further removal of string module from core.
Thomas Kluyver -
Show More
@@ -1,892 +1,891 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 StringIO
21 import StringIO
22 import inspect
22 import inspect
23 import linecache
23 import linecache
24 import os
24 import os
25 import string
26 import sys
25 import sys
27 import types
26 import types
28 from collections import namedtuple
27 from collections import namedtuple
29 from itertools import izip_longest
28 from itertools import izip_longest
30
29
31 # IPython's own
30 # IPython's own
32 from IPython.core import page
31 from IPython.core import page
33 from IPython.external.Itpl import itpl
32 from IPython.external.Itpl import itpl
34 from IPython.utils import PyColorize
33 from IPython.utils import PyColorize
35 import IPython.utils.io
34 import IPython.utils.io
36 from IPython.utils.text import indent
35 from IPython.utils.text import indent
37 from IPython.utils.wildcard import list_namespace
36 from IPython.utils.wildcard import list_namespace
38 from IPython.utils.coloransi import *
37 from IPython.utils.coloransi import *
39
38
40 #****************************************************************************
39 #****************************************************************************
41 # Builtin color schemes
40 # Builtin color schemes
42
41
43 Colors = TermColors # just a shorthand
42 Colors = TermColors # just a shorthand
44
43
45 # Build a few color schemes
44 # Build a few color schemes
46 NoColor = ColorScheme(
45 NoColor = ColorScheme(
47 'NoColor',{
46 'NoColor',{
48 'header' : Colors.NoColor,
47 'header' : Colors.NoColor,
49 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
48 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
50 } )
49 } )
51
50
52 LinuxColors = ColorScheme(
51 LinuxColors = ColorScheme(
53 'Linux',{
52 'Linux',{
54 'header' : Colors.LightRed,
53 'header' : Colors.LightRed,
55 'normal' : Colors.Normal # color off (usu. Colors.Normal)
54 'normal' : Colors.Normal # color off (usu. Colors.Normal)
56 } )
55 } )
57
56
58 LightBGColors = ColorScheme(
57 LightBGColors = ColorScheme(
59 'LightBG',{
58 'LightBG',{
60 'header' : Colors.Red,
59 'header' : Colors.Red,
61 'normal' : Colors.Normal # color off (usu. Colors.Normal)
60 'normal' : Colors.Normal # color off (usu. Colors.Normal)
62 } )
61 } )
63
62
64 # Build table of color schemes (needed by the parser)
63 # Build table of color schemes (needed by the parser)
65 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
64 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
66 'Linux')
65 'Linux')
67
66
68 #****************************************************************************
67 #****************************************************************************
69 # Auxiliary functions and objects
68 # Auxiliary functions and objects
70
69
71 # See the messaging spec for the definition of all these fields. This list
70 # See the messaging spec for the definition of all these fields. This list
72 # effectively defines the order of display
71 # effectively defines the order of display
73 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
72 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
74 'length', 'file', 'definition', 'docstring', 'source',
73 'length', 'file', 'definition', 'docstring', 'source',
75 'init_definition', 'class_docstring', 'init_docstring',
74 'init_definition', 'class_docstring', 'init_docstring',
76 'call_def', 'call_docstring',
75 'call_def', 'call_docstring',
77 # These won't be printed but will be used to determine how to
76 # These won't be printed but will be used to determine how to
78 # format the object
77 # format the object
79 'ismagic', 'isalias', 'argspec', 'found', 'name',
78 'ismagic', 'isalias', 'argspec', 'found', 'name',
80 ]
79 ]
81
80
82
81
83 def object_info(**kw):
82 def object_info(**kw):
84 """Make an object info dict with all fields present."""
83 """Make an object info dict with all fields present."""
85 infodict = dict(izip_longest(info_fields, [None]))
84 infodict = dict(izip_longest(info_fields, [None]))
86 infodict.update(kw)
85 infodict.update(kw)
87 return infodict
86 return infodict
88
87
89
88
90 def getdoc(obj):
89 def getdoc(obj):
91 """Stable wrapper around inspect.getdoc.
90 """Stable wrapper around inspect.getdoc.
92
91
93 This can't crash because of attribute problems.
92 This can't crash because of attribute problems.
94
93
95 It also attempts to call a getdoc() method on the given object. This
94 It also attempts to call a getdoc() method on the given object. This
96 allows objects which provide their docstrings via non-standard mechanisms
95 allows objects which provide their docstrings via non-standard mechanisms
97 (like Pyro proxies) to still be inspected by ipython's ? system."""
96 (like Pyro proxies) to still be inspected by ipython's ? system."""
98
97
99 ds = None # default return value
98 ds = None # default return value
100 try:
99 try:
101 ds = inspect.getdoc(obj)
100 ds = inspect.getdoc(obj)
102 except:
101 except:
103 # Harden against an inspect failure, which can occur with
102 # Harden against an inspect failure, which can occur with
104 # SWIG-wrapped extensions.
103 # SWIG-wrapped extensions.
105 pass
104 pass
106 # Allow objects to offer customized documentation via a getdoc method:
105 # Allow objects to offer customized documentation via a getdoc method:
107 try:
106 try:
108 ds2 = obj.getdoc()
107 ds2 = obj.getdoc()
109 except:
108 except:
110 pass
109 pass
111 else:
110 else:
112 # if we get extra info, we add it to the normal docstring.
111 # if we get extra info, we add it to the normal docstring.
113 if ds is None:
112 if ds is None:
114 ds = ds2
113 ds = ds2
115 else:
114 else:
116 ds = '%s\n%s' % (ds,ds2)
115 ds = '%s\n%s' % (ds,ds2)
117 return ds
116 return ds
118
117
119
118
120 def getsource(obj,is_binary=False):
119 def getsource(obj,is_binary=False):
121 """Wrapper around inspect.getsource.
120 """Wrapper around inspect.getsource.
122
121
123 This can be modified by other projects to provide customized source
122 This can be modified by other projects to provide customized source
124 extraction.
123 extraction.
125
124
126 Inputs:
125 Inputs:
127
126
128 - obj: an object whose source code we will attempt to extract.
127 - obj: an object whose source code we will attempt to extract.
129
128
130 Optional inputs:
129 Optional inputs:
131
130
132 - is_binary: whether the object is known to come from a binary source.
131 - is_binary: whether the object is known to come from a binary source.
133 This implementation will skip returning any output for binary objects, but
132 This implementation will skip returning any output for binary objects, but
134 custom extractors may know how to meaningfully process them."""
133 custom extractors may know how to meaningfully process them."""
135
134
136 if is_binary:
135 if is_binary:
137 return None
136 return None
138 else:
137 else:
139 try:
138 try:
140 src = inspect.getsource(obj)
139 src = inspect.getsource(obj)
141 except TypeError:
140 except TypeError:
142 if hasattr(obj,'__class__'):
141 if hasattr(obj,'__class__'):
143 src = inspect.getsource(obj.__class__)
142 src = inspect.getsource(obj.__class__)
144 return src
143 return src
145
144
146 def getargspec(obj):
145 def getargspec(obj):
147 """Get the names and default values of a function's arguments.
146 """Get the names and default values of a function's arguments.
148
147
149 A tuple of four things is returned: (args, varargs, varkw, defaults).
148 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).
149 '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.
150 '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.
151 'defaults' is an n-tuple of the default values of the last n arguments.
153
152
154 Modified version of inspect.getargspec from the Python Standard
153 Modified version of inspect.getargspec from the Python Standard
155 Library."""
154 Library."""
156
155
157 if inspect.isfunction(obj):
156 if inspect.isfunction(obj):
158 func_obj = obj
157 func_obj = obj
159 elif inspect.ismethod(obj):
158 elif inspect.ismethod(obj):
160 func_obj = obj.im_func
159 func_obj = obj.im_func
161 elif hasattr(obj, '__call__'):
160 elif hasattr(obj, '__call__'):
162 func_obj = obj.__call__
161 func_obj = obj.__call__
163 else:
162 else:
164 raise TypeError('arg is not a Python function')
163 raise TypeError('arg is not a Python function')
165 args, varargs, varkw = inspect.getargs(func_obj.func_code)
164 args, varargs, varkw = inspect.getargs(func_obj.func_code)
166 return args, varargs, varkw, func_obj.func_defaults
165 return args, varargs, varkw, func_obj.func_defaults
167
166
168
167
169 def format_argspec(argspec):
168 def format_argspec(argspec):
170 """Format argspect, convenience wrapper around inspect's.
169 """Format argspect, convenience wrapper around inspect's.
171
170
172 This takes a dict instead of ordered arguments and calls
171 This takes a dict instead of ordered arguments and calls
173 inspect.format_argspec with the arguments in the necessary order.
172 inspect.format_argspec with the arguments in the necessary order.
174 """
173 """
175 return inspect.formatargspec(argspec['args'], argspec['varargs'],
174 return inspect.formatargspec(argspec['args'], argspec['varargs'],
176 argspec['varkw'], argspec['defaults'])
175 argspec['varkw'], argspec['defaults'])
177
176
178
177
179 def call_tip(oinfo, format_call=True):
178 def call_tip(oinfo, format_call=True):
180 """Extract call tip data from an oinfo dict.
179 """Extract call tip data from an oinfo dict.
181
180
182 Parameters
181 Parameters
183 ----------
182 ----------
184 oinfo : dict
183 oinfo : dict
185
184
186 format_call : bool, optional
185 format_call : bool, optional
187 If True, the call line is formatted and returned as a string. If not, a
186 If True, the call line is formatted and returned as a string. If not, a
188 tuple of (name, argspec) is returned.
187 tuple of (name, argspec) is returned.
189
188
190 Returns
189 Returns
191 -------
190 -------
192 call_info : None, str or (str, dict) tuple.
191 call_info : None, str or (str, dict) tuple.
193 When format_call is True, the whole call information is formattted as a
192 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
193 single string. Otherwise, the object's name and its argspec dict are
195 returned. If no call information is available, None is returned.
194 returned. If no call information is available, None is returned.
196
195
197 docstring : str or None
196 docstring : str or None
198 The most relevant docstring for calling purposes is returned, if
197 The most relevant docstring for calling purposes is returned, if
199 available. The priority is: call docstring for callable instances, then
198 available. The priority is: call docstring for callable instances, then
200 constructor docstring for classes, then main object's docstring otherwise
199 constructor docstring for classes, then main object's docstring otherwise
201 (regular functions).
200 (regular functions).
202 """
201 """
203 # Get call definition
202 # Get call definition
204 argspec = oinfo['argspec']
203 argspec = oinfo['argspec']
205 if argspec is None:
204 if argspec is None:
206 call_line = None
205 call_line = None
207 else:
206 else:
208 # Callable objects will have 'self' as their first argument, prune
207 # 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
208 # it out if it's there for clarity (since users do *not* pass an
210 # extra first argument explicitly).
209 # extra first argument explicitly).
211 try:
210 try:
212 has_self = argspec['args'][0] == 'self'
211 has_self = argspec['args'][0] == 'self'
213 except (KeyError, IndexError):
212 except (KeyError, IndexError):
214 pass
213 pass
215 else:
214 else:
216 if has_self:
215 if has_self:
217 argspec['args'] = argspec['args'][1:]
216 argspec['args'] = argspec['args'][1:]
218
217
219 call_line = oinfo['name']+format_argspec(argspec)
218 call_line = oinfo['name']+format_argspec(argspec)
220
219
221 # Now get docstring.
220 # Now get docstring.
222 # The priority is: call docstring, constructor docstring, main one.
221 # The priority is: call docstring, constructor docstring, main one.
223 doc = oinfo['call_docstring']
222 doc = oinfo['call_docstring']
224 if doc is None:
223 if doc is None:
225 doc = oinfo['init_docstring']
224 doc = oinfo['init_docstring']
226 if doc is None:
225 if doc is None:
227 doc = oinfo['docstring']
226 doc = oinfo['docstring']
228
227
229 return call_line, doc
228 return call_line, doc
230
229
231 #****************************************************************************
230 #****************************************************************************
232 # Class definitions
231 # Class definitions
233
232
234 class myStringIO(StringIO.StringIO):
233 class myStringIO(StringIO.StringIO):
235 """Adds a writeln method to normal StringIO."""
234 """Adds a writeln method to normal StringIO."""
236 def writeln(self,*arg,**kw):
235 def writeln(self,*arg,**kw):
237 """Does a write() and then a write('\n')"""
236 """Does a write() and then a write('\n')"""
238 self.write(*arg,**kw)
237 self.write(*arg,**kw)
239 self.write('\n')
238 self.write('\n')
240
239
241
240
242 class Inspector:
241 class Inspector:
243 def __init__(self, color_table=InspectColors,
242 def __init__(self, color_table=InspectColors,
244 code_color_table=PyColorize.ANSICodeColors,
243 code_color_table=PyColorize.ANSICodeColors,
245 scheme='NoColor',
244 scheme='NoColor',
246 str_detail_level=0):
245 str_detail_level=0):
247 self.color_table = color_table
246 self.color_table = color_table
248 self.parser = PyColorize.Parser(code_color_table,out='str')
247 self.parser = PyColorize.Parser(code_color_table,out='str')
249 self.format = self.parser.format
248 self.format = self.parser.format
250 self.str_detail_level = str_detail_level
249 self.str_detail_level = str_detail_level
251 self.set_active_scheme(scheme)
250 self.set_active_scheme(scheme)
252
251
253 def _getdef(self,obj,oname=''):
252 def _getdef(self,obj,oname=''):
254 """Return the definition header for any callable object.
253 """Return the definition header for any callable object.
255
254
256 If any exception is generated, None is returned instead and the
255 If any exception is generated, None is returned instead and the
257 exception is suppressed."""
256 exception is suppressed."""
258
257
259 try:
258 try:
260 # We need a plain string here, NOT unicode!
259 # We need a plain string here, NOT unicode!
261 hdef = oname + inspect.formatargspec(*getargspec(obj))
260 hdef = oname + inspect.formatargspec(*getargspec(obj))
262 return hdef.encode('ascii')
261 return hdef.encode('ascii')
263 except:
262 except:
264 return None
263 return None
265
264
266 def __head(self,h):
265 def __head(self,h):
267 """Return a header string with proper colors."""
266 """Return a header string with proper colors."""
268 return '%s%s%s' % (self.color_table.active_colors.header,h,
267 return '%s%s%s' % (self.color_table.active_colors.header,h,
269 self.color_table.active_colors.normal)
268 self.color_table.active_colors.normal)
270
269
271 def set_active_scheme(self,scheme):
270 def set_active_scheme(self,scheme):
272 self.color_table.set_active_scheme(scheme)
271 self.color_table.set_active_scheme(scheme)
273 self.parser.color_table.set_active_scheme(scheme)
272 self.parser.color_table.set_active_scheme(scheme)
274
273
275 def noinfo(self,msg,oname):
274 def noinfo(self,msg,oname):
276 """Generic message when no information is found."""
275 """Generic message when no information is found."""
277 print 'No %s found' % msg,
276 print 'No %s found' % msg,
278 if oname:
277 if oname:
279 print 'for %s' % oname
278 print 'for %s' % oname
280 else:
279 else:
281 print
280 print
282
281
283 def pdef(self,obj,oname=''):
282 def pdef(self,obj,oname=''):
284 """Print the definition header for any callable object.
283 """Print the definition header for any callable object.
285
284
286 If the object is a class, print the constructor information."""
285 If the object is a class, print the constructor information."""
287
286
288 if not callable(obj):
287 if not callable(obj):
289 print 'Object is not callable.'
288 print 'Object is not callable.'
290 return
289 return
291
290
292 header = ''
291 header = ''
293
292
294 if inspect.isclass(obj):
293 if inspect.isclass(obj):
295 header = self.__head('Class constructor information:\n')
294 header = self.__head('Class constructor information:\n')
296 obj = obj.__init__
295 obj = obj.__init__
297 elif type(obj) is types.InstanceType:
296 elif type(obj) is types.InstanceType:
298 obj = obj.__call__
297 obj = obj.__call__
299
298
300 output = self._getdef(obj,oname)
299 output = self._getdef(obj,oname)
301 if output is None:
300 if output is None:
302 self.noinfo('definition header',oname)
301 self.noinfo('definition header',oname)
303 else:
302 else:
304 print >>IPython.utils.io.Term.cout, header,self.format(output),
303 print >>IPython.utils.io.Term.cout, header,self.format(output),
305
304
306 def pdoc(self,obj,oname='',formatter = None):
305 def pdoc(self,obj,oname='',formatter = None):
307 """Print the docstring for any object.
306 """Print the docstring for any object.
308
307
309 Optional:
308 Optional:
310 -formatter: a function to run the docstring through for specially
309 -formatter: a function to run the docstring through for specially
311 formatted docstrings."""
310 formatted docstrings."""
312
311
313 head = self.__head # so that itpl can find it even if private
312 head = self.__head # so that itpl can find it even if private
314 ds = getdoc(obj)
313 ds = getdoc(obj)
315 if formatter:
314 if formatter:
316 ds = formatter(ds)
315 ds = formatter(ds)
317 if inspect.isclass(obj):
316 if inspect.isclass(obj):
318 init_ds = getdoc(obj.__init__)
317 init_ds = getdoc(obj.__init__)
319 output = itpl('$head("Class Docstring:")\n'
318 output = itpl('$head("Class Docstring:")\n'
320 '$indent(ds)\n'
319 '$indent(ds)\n'
321 '$head("Constructor Docstring"):\n'
320 '$head("Constructor Docstring"):\n'
322 '$indent(init_ds)')
321 '$indent(init_ds)')
323 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
322 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
324 and hasattr(obj,'__call__'):
323 and hasattr(obj,'__call__'):
325 call_ds = getdoc(obj.__call__)
324 call_ds = getdoc(obj.__call__)
326 if call_ds:
325 if call_ds:
327 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
326 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
328 '$head("Calling Docstring:")\n$indent(call_ds)')
327 '$head("Calling Docstring:")\n$indent(call_ds)')
329 else:
328 else:
330 output = ds
329 output = ds
331 else:
330 else:
332 output = ds
331 output = ds
333 if output is None:
332 if output is None:
334 self.noinfo('documentation',oname)
333 self.noinfo('documentation',oname)
335 return
334 return
336 page.page(output)
335 page.page(output)
337
336
338 def psource(self,obj,oname=''):
337 def psource(self,obj,oname=''):
339 """Print the source code for an object."""
338 """Print the source code for an object."""
340
339
341 # Flush the source cache because inspect can return out-of-date source
340 # Flush the source cache because inspect can return out-of-date source
342 linecache.checkcache()
341 linecache.checkcache()
343 try:
342 try:
344 src = getsource(obj)
343 src = getsource(obj)
345 except:
344 except:
346 self.noinfo('source',oname)
345 self.noinfo('source',oname)
347 else:
346 else:
348 page.page(self.format(src))
347 page.page(self.format(src))
349
348
350 def pfile(self,obj,oname=''):
349 def pfile(self,obj,oname=''):
351 """Show the whole file where an object was defined."""
350 """Show the whole file where an object was defined."""
352
351
353 try:
352 try:
354 try:
353 try:
355 lineno = inspect.getsourcelines(obj)[1]
354 lineno = inspect.getsourcelines(obj)[1]
356 except TypeError:
355 except TypeError:
357 # For instances, try the class object like getsource() does
356 # For instances, try the class object like getsource() does
358 if hasattr(obj,'__class__'):
357 if hasattr(obj,'__class__'):
359 lineno = inspect.getsourcelines(obj.__class__)[1]
358 lineno = inspect.getsourcelines(obj.__class__)[1]
360 # Adjust the inspected object so getabsfile() below works
359 # Adjust the inspected object so getabsfile() below works
361 obj = obj.__class__
360 obj = obj.__class__
362 except:
361 except:
363 self.noinfo('file',oname)
362 self.noinfo('file',oname)
364 return
363 return
365
364
366 # We only reach this point if object was successfully queried
365 # We only reach this point if object was successfully queried
367
366
368 # run contents of file through pager starting at line
367 # run contents of file through pager starting at line
369 # where the object is defined
368 # where the object is defined
370 ofile = inspect.getabsfile(obj)
369 ofile = inspect.getabsfile(obj)
371
370
372 if (ofile.endswith('.so') or ofile.endswith('.dll')):
371 if (ofile.endswith('.so') or ofile.endswith('.dll')):
373 print 'File %r is binary, not printing.' % ofile
372 print 'File %r is binary, not printing.' % ofile
374 elif not os.path.isfile(ofile):
373 elif not os.path.isfile(ofile):
375 print 'File %r does not exist, not printing.' % ofile
374 print 'File %r does not exist, not printing.' % ofile
376 else:
375 else:
377 # Print only text files, not extension binaries. Note that
376 # Print only text files, not extension binaries. Note that
378 # getsourcelines returns lineno with 1-offset and page() uses
377 # getsourcelines returns lineno with 1-offset and page() uses
379 # 0-offset, so we must adjust.
378 # 0-offset, so we must adjust.
380 page.page(self.format(open(ofile).read()),lineno-1)
379 page.page(self.format(open(ofile).read()),lineno-1)
381
380
382 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
381 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
383 """Show detailed information about an object.
382 """Show detailed information about an object.
384
383
385 Optional arguments:
384 Optional arguments:
386
385
387 - oname: name of the variable pointing to the object.
386 - oname: name of the variable pointing to the object.
388
387
389 - formatter: special formatter for docstrings (see pdoc)
388 - formatter: special formatter for docstrings (see pdoc)
390
389
391 - info: a structure with some information fields which may have been
390 - info: a structure with some information fields which may have been
392 precomputed already.
391 precomputed already.
393
392
394 - detail_level: if set to 1, more information is given.
393 - detail_level: if set to 1, more information is given.
395 """
394 """
396
395
397 obj_type = type(obj)
396 obj_type = type(obj)
398
397
399 header = self.__head
398 header = self.__head
400 if info is None:
399 if info is None:
401 ismagic = 0
400 ismagic = 0
402 isalias = 0
401 isalias = 0
403 ospace = ''
402 ospace = ''
404 else:
403 else:
405 ismagic = info.ismagic
404 ismagic = info.ismagic
406 isalias = info.isalias
405 isalias = info.isalias
407 ospace = info.namespace
406 ospace = info.namespace
408 # Get docstring, special-casing aliases:
407 # Get docstring, special-casing aliases:
409 if isalias:
408 if isalias:
410 if not callable(obj):
409 if not callable(obj):
411 try:
410 try:
412 ds = "Alias to the system command:\n %s" % obj[1]
411 ds = "Alias to the system command:\n %s" % obj[1]
413 except:
412 except:
414 ds = "Alias: " + str(obj)
413 ds = "Alias: " + str(obj)
415 else:
414 else:
416 ds = "Alias to " + str(obj)
415 ds = "Alias to " + str(obj)
417 if obj.__doc__:
416 if obj.__doc__:
418 ds += "\nDocstring:\n" + obj.__doc__
417 ds += "\nDocstring:\n" + obj.__doc__
419 else:
418 else:
420 ds = getdoc(obj)
419 ds = getdoc(obj)
421 if ds is None:
420 if ds is None:
422 ds = '<no docstring>'
421 ds = '<no docstring>'
423 if formatter is not None:
422 if formatter is not None:
424 ds = formatter(ds)
423 ds = formatter(ds)
425
424
426 # store output in a list which gets joined with \n at the end.
425 # store output in a list which gets joined with \n at the end.
427 out = myStringIO()
426 out = myStringIO()
428
427
429 string_max = 200 # max size of strings to show (snipped if longer)
428 string_max = 200 # max size of strings to show (snipped if longer)
430 shalf = int((string_max -5)/2)
429 shalf = int((string_max -5)/2)
431
430
432 if ismagic:
431 if ismagic:
433 obj_type_name = 'Magic function'
432 obj_type_name = 'Magic function'
434 elif isalias:
433 elif isalias:
435 obj_type_name = 'System alias'
434 obj_type_name = 'System alias'
436 else:
435 else:
437 obj_type_name = obj_type.__name__
436 obj_type_name = obj_type.__name__
438 out.writeln(header('Type:\t\t')+obj_type_name)
437 out.writeln(header('Type:\t\t')+obj_type_name)
439
438
440 try:
439 try:
441 bclass = obj.__class__
440 bclass = obj.__class__
442 out.writeln(header('Base Class:\t')+str(bclass))
441 out.writeln(header('Base Class:\t')+str(bclass))
443 except: pass
442 except: pass
444
443
445 # String form, but snip if too long in ? form (full in ??)
444 # String form, but snip if too long in ? form (full in ??)
446 if detail_level >= self.str_detail_level:
445 if detail_level >= self.str_detail_level:
447 try:
446 try:
448 ostr = str(obj)
447 ostr = str(obj)
449 str_head = 'String Form:'
448 str_head = 'String Form:'
450 if not detail_level and len(ostr)>string_max:
449 if not detail_level and len(ostr)>string_max:
451 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
450 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
452 ostr = ("\n" + " " * len(str_head.expandtabs())).\
451 ostr = ("\n" + " " * len(str_head.expandtabs())).\
453 join(map(string.strip,ostr.split("\n")))
452 join(q.strip() for q in ostr.split("\n"))
454 if ostr.find('\n') > -1:
453 if ostr.find('\n') > -1:
455 # Print multi-line strings starting at the next line.
454 # Print multi-line strings starting at the next line.
456 str_sep = '\n'
455 str_sep = '\n'
457 else:
456 else:
458 str_sep = '\t'
457 str_sep = '\t'
459 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
458 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
460 except:
459 except:
461 pass
460 pass
462
461
463 if ospace:
462 if ospace:
464 out.writeln(header('Namespace:\t')+ospace)
463 out.writeln(header('Namespace:\t')+ospace)
465
464
466 # Length (for strings and lists)
465 # Length (for strings and lists)
467 try:
466 try:
468 length = str(len(obj))
467 length = str(len(obj))
469 out.writeln(header('Length:\t\t')+length)
468 out.writeln(header('Length:\t\t')+length)
470 except: pass
469 except: pass
471
470
472 # Filename where object was defined
471 # Filename where object was defined
473 binary_file = False
472 binary_file = False
474 try:
473 try:
475 try:
474 try:
476 fname = inspect.getabsfile(obj)
475 fname = inspect.getabsfile(obj)
477 except TypeError:
476 except TypeError:
478 # For an instance, the file that matters is where its class was
477 # For an instance, the file that matters is where its class was
479 # declared.
478 # declared.
480 if hasattr(obj,'__class__'):
479 if hasattr(obj,'__class__'):
481 fname = inspect.getabsfile(obj.__class__)
480 fname = inspect.getabsfile(obj.__class__)
482 if fname.endswith('<string>'):
481 if fname.endswith('<string>'):
483 fname = 'Dynamically generated function. No source code available.'
482 fname = 'Dynamically generated function. No source code available.'
484 if (fname.endswith('.so') or fname.endswith('.dll')):
483 if (fname.endswith('.so') or fname.endswith('.dll')):
485 binary_file = True
484 binary_file = True
486 out.writeln(header('File:\t\t')+fname)
485 out.writeln(header('File:\t\t')+fname)
487 except:
486 except:
488 # if anything goes wrong, we don't want to show source, so it's as
487 # if anything goes wrong, we don't want to show source, so it's as
489 # if the file was binary
488 # if the file was binary
490 binary_file = True
489 binary_file = True
491
490
492 # reconstruct the function definition and print it:
491 # reconstruct the function definition and print it:
493 defln = self._getdef(obj,oname)
492 defln = self._getdef(obj,oname)
494 if defln:
493 if defln:
495 out.write(header('Definition:\t')+self.format(defln))
494 out.write(header('Definition:\t')+self.format(defln))
496
495
497 # Docstrings only in detail 0 mode, since source contains them (we
496 # Docstrings only in detail 0 mode, since source contains them (we
498 # avoid repetitions). If source fails, we add them back, see below.
497 # avoid repetitions). If source fails, we add them back, see below.
499 if ds and detail_level == 0:
498 if ds and detail_level == 0:
500 out.writeln(header('Docstring:\n') + indent(ds))
499 out.writeln(header('Docstring:\n') + indent(ds))
501
500
502 # Original source code for any callable
501 # Original source code for any callable
503 if detail_level:
502 if detail_level:
504 # Flush the source cache because inspect can return out-of-date
503 # Flush the source cache because inspect can return out-of-date
505 # source
504 # source
506 linecache.checkcache()
505 linecache.checkcache()
507 source_success = False
506 source_success = False
508 try:
507 try:
509 try:
508 try:
510 src = getsource(obj,binary_file)
509 src = getsource(obj,binary_file)
511 except TypeError:
510 except TypeError:
512 if hasattr(obj,'__class__'):
511 if hasattr(obj,'__class__'):
513 src = getsource(obj.__class__,binary_file)
512 src = getsource(obj.__class__,binary_file)
514 if src is not None:
513 if src is not None:
515 source = self.format(src)
514 source = self.format(src)
516 out.write(header('Source:\n')+source.rstrip())
515 out.write(header('Source:\n')+source.rstrip())
517 source_success = True
516 source_success = True
518 except Exception, msg:
517 except Exception, msg:
519 pass
518 pass
520
519
521 if ds and not source_success:
520 if ds and not source_success:
522 out.writeln(header('Docstring [source file open failed]:\n')
521 out.writeln(header('Docstring [source file open failed]:\n')
523 + indent(ds))
522 + indent(ds))
524
523
525 # Constructor docstring for classes
524 # Constructor docstring for classes
526 if inspect.isclass(obj):
525 if inspect.isclass(obj):
527 # reconstruct the function definition and print it:
526 # reconstruct the function definition and print it:
528 try:
527 try:
529 obj_init = obj.__init__
528 obj_init = obj.__init__
530 except AttributeError:
529 except AttributeError:
531 init_def = init_ds = None
530 init_def = init_ds = None
532 else:
531 else:
533 init_def = self._getdef(obj_init,oname)
532 init_def = self._getdef(obj_init,oname)
534 init_ds = getdoc(obj_init)
533 init_ds = getdoc(obj_init)
535 # Skip Python's auto-generated docstrings
534 # Skip Python's auto-generated docstrings
536 if init_ds and \
535 if init_ds and \
537 init_ds.startswith('x.__init__(...) initializes'):
536 init_ds.startswith('x.__init__(...) initializes'):
538 init_ds = None
537 init_ds = None
539
538
540 if init_def or init_ds:
539 if init_def or init_ds:
541 out.writeln(header('\nConstructor information:'))
540 out.writeln(header('\nConstructor information:'))
542 if init_def:
541 if init_def:
543 out.write(header('Definition:\t')+ self.format(init_def))
542 out.write(header('Definition:\t')+ self.format(init_def))
544 if init_ds:
543 if init_ds:
545 out.writeln(header('Docstring:\n') + indent(init_ds))
544 out.writeln(header('Docstring:\n') + indent(init_ds))
546 # and class docstring for instances:
545 # and class docstring for instances:
547 elif obj_type is types.InstanceType or \
546 elif obj_type is types.InstanceType or \
548 isinstance(obj,object):
547 isinstance(obj,object):
549
548
550 # First, check whether the instance docstring is identical to the
549 # First, check whether the instance docstring is identical to the
551 # class one, and print it separately if they don't coincide. In
550 # class one, and print it separately if they don't coincide. In
552 # most cases they will, but it's nice to print all the info for
551 # most cases they will, but it's nice to print all the info for
553 # objects which use instance-customized docstrings.
552 # objects which use instance-customized docstrings.
554 if ds:
553 if ds:
555 try:
554 try:
556 cls = getattr(obj,'__class__')
555 cls = getattr(obj,'__class__')
557 except:
556 except:
558 class_ds = None
557 class_ds = None
559 else:
558 else:
560 class_ds = getdoc(cls)
559 class_ds = getdoc(cls)
561 # Skip Python's auto-generated docstrings
560 # Skip Python's auto-generated docstrings
562 if class_ds and \
561 if class_ds and \
563 (class_ds.startswith('function(code, globals[,') or \
562 (class_ds.startswith('function(code, globals[,') or \
564 class_ds.startswith('instancemethod(function, instance,') or \
563 class_ds.startswith('instancemethod(function, instance,') or \
565 class_ds.startswith('module(name[,') ):
564 class_ds.startswith('module(name[,') ):
566 class_ds = None
565 class_ds = None
567 if class_ds and ds != class_ds:
566 if class_ds and ds != class_ds:
568 out.writeln(header('Class Docstring:\n') +
567 out.writeln(header('Class Docstring:\n') +
569 indent(class_ds))
568 indent(class_ds))
570
569
571 # Next, try to show constructor docstrings
570 # Next, try to show constructor docstrings
572 try:
571 try:
573 init_ds = getdoc(obj.__init__)
572 init_ds = getdoc(obj.__init__)
574 # Skip Python's auto-generated docstrings
573 # Skip Python's auto-generated docstrings
575 if init_ds and \
574 if init_ds and \
576 init_ds.startswith('x.__init__(...) initializes'):
575 init_ds.startswith('x.__init__(...) initializes'):
577 init_ds = None
576 init_ds = None
578 except AttributeError:
577 except AttributeError:
579 init_ds = None
578 init_ds = None
580 if init_ds:
579 if init_ds:
581 out.writeln(header('Constructor Docstring:\n') +
580 out.writeln(header('Constructor Docstring:\n') +
582 indent(init_ds))
581 indent(init_ds))
583
582
584 # Call form docstring for callable instances
583 # Call form docstring for callable instances
585 if hasattr(obj,'__call__'):
584 if hasattr(obj,'__call__'):
586 #out.writeln(header('Callable:\t')+'Yes')
585 #out.writeln(header('Callable:\t')+'Yes')
587 call_def = self._getdef(obj.__call__,oname)
586 call_def = self._getdef(obj.__call__,oname)
588 #if call_def is None:
587 #if call_def is None:
589 # out.writeln(header('Call def:\t')+
588 # out.writeln(header('Call def:\t')+
590 # 'Calling definition not available.')
589 # 'Calling definition not available.')
591 if call_def is not None:
590 if call_def is not None:
592 out.writeln(header('Call def:\t')+self.format(call_def))
591 out.writeln(header('Call def:\t')+self.format(call_def))
593 call_ds = getdoc(obj.__call__)
592 call_ds = getdoc(obj.__call__)
594 # Skip Python's auto-generated docstrings
593 # Skip Python's auto-generated docstrings
595 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
594 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
596 call_ds = None
595 call_ds = None
597 if call_ds:
596 if call_ds:
598 out.writeln(header('Call docstring:\n') + indent(call_ds))
597 out.writeln(header('Call docstring:\n') + indent(call_ds))
599
598
600 # Finally send to printer/pager
599 # Finally send to printer/pager
601 output = out.getvalue()
600 output = out.getvalue()
602 if output:
601 if output:
603 page.page(output)
602 page.page(output)
604 # end pinfo
603 # end pinfo
605
604
606 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
605 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
607 """Compute a dict with detailed information about an object.
606 """Compute a dict with detailed information about an object.
608
607
609 Optional arguments:
608 Optional arguments:
610
609
611 - oname: name of the variable pointing to the object.
610 - oname: name of the variable pointing to the object.
612
611
613 - formatter: special formatter for docstrings (see pdoc)
612 - formatter: special formatter for docstrings (see pdoc)
614
613
615 - info: a structure with some information fields which may have been
614 - info: a structure with some information fields which may have been
616 precomputed already.
615 precomputed already.
617
616
618 - detail_level: if set to 1, more information is given.
617 - detail_level: if set to 1, more information is given.
619 """
618 """
620
619
621 obj_type = type(obj)
620 obj_type = type(obj)
622
621
623 header = self.__head
622 header = self.__head
624 if info is None:
623 if info is None:
625 ismagic = 0
624 ismagic = 0
626 isalias = 0
625 isalias = 0
627 ospace = ''
626 ospace = ''
628 else:
627 else:
629 ismagic = info.ismagic
628 ismagic = info.ismagic
630 isalias = info.isalias
629 isalias = info.isalias
631 ospace = info.namespace
630 ospace = info.namespace
632
631
633 # Get docstring, special-casing aliases:
632 # Get docstring, special-casing aliases:
634 if isalias:
633 if isalias:
635 if not callable(obj):
634 if not callable(obj):
636 try:
635 try:
637 ds = "Alias to the system command:\n %s" % obj[1]
636 ds = "Alias to the system command:\n %s" % obj[1]
638 except:
637 except:
639 ds = "Alias: " + str(obj)
638 ds = "Alias: " + str(obj)
640 else:
639 else:
641 ds = "Alias to " + str(obj)
640 ds = "Alias to " + str(obj)
642 if obj.__doc__:
641 if obj.__doc__:
643 ds += "\nDocstring:\n" + obj.__doc__
642 ds += "\nDocstring:\n" + obj.__doc__
644 else:
643 else:
645 ds = getdoc(obj)
644 ds = getdoc(obj)
646 if ds is None:
645 if ds is None:
647 ds = '<no docstring>'
646 ds = '<no docstring>'
648 if formatter is not None:
647 if formatter is not None:
649 ds = formatter(ds)
648 ds = formatter(ds)
650
649
651 # store output in a dict, we initialize it here and fill it as we go
650 # store output in a dict, we initialize it here and fill it as we go
652 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
651 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
653
652
654 string_max = 200 # max size of strings to show (snipped if longer)
653 string_max = 200 # max size of strings to show (snipped if longer)
655 shalf = int((string_max -5)/2)
654 shalf = int((string_max -5)/2)
656
655
657 if ismagic:
656 if ismagic:
658 obj_type_name = 'Magic function'
657 obj_type_name = 'Magic function'
659 elif isalias:
658 elif isalias:
660 obj_type_name = 'System alias'
659 obj_type_name = 'System alias'
661 else:
660 else:
662 obj_type_name = obj_type.__name__
661 obj_type_name = obj_type.__name__
663 out['type_name'] = obj_type_name
662 out['type_name'] = obj_type_name
664
663
665 try:
664 try:
666 bclass = obj.__class__
665 bclass = obj.__class__
667 out['base_class'] = str(bclass)
666 out['base_class'] = str(bclass)
668 except: pass
667 except: pass
669
668
670 # String form, but snip if too long in ? form (full in ??)
669 # String form, but snip if too long in ? form (full in ??)
671 if detail_level >= self.str_detail_level:
670 if detail_level >= self.str_detail_level:
672 try:
671 try:
673 ostr = str(obj)
672 ostr = str(obj)
674 str_head = 'string_form'
673 str_head = 'string_form'
675 if not detail_level and len(ostr)>string_max:
674 if not detail_level and len(ostr)>string_max:
676 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
675 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
677 ostr = ("\n" + " " * len(str_head.expandtabs())).\
676 ostr = ("\n" + " " * len(str_head.expandtabs())).\
678 join(map(string.strip,ostr.split("\n")))
677 join(q.strip() for q in ostr.split("\n"))
679 if ostr.find('\n') > -1:
678 if ostr.find('\n') > -1:
680 # Print multi-line strings starting at the next line.
679 # Print multi-line strings starting at the next line.
681 str_sep = '\n'
680 str_sep = '\n'
682 else:
681 else:
683 str_sep = '\t'
682 str_sep = '\t'
684 out[str_head] = ostr
683 out[str_head] = ostr
685 except:
684 except:
686 pass
685 pass
687
686
688 if ospace:
687 if ospace:
689 out['namespace'] = ospace
688 out['namespace'] = ospace
690
689
691 # Length (for strings and lists)
690 # Length (for strings and lists)
692 try:
691 try:
693 out['length'] = str(len(obj))
692 out['length'] = str(len(obj))
694 except: pass
693 except: pass
695
694
696 # Filename where object was defined
695 # Filename where object was defined
697 binary_file = False
696 binary_file = False
698 try:
697 try:
699 try:
698 try:
700 fname = inspect.getabsfile(obj)
699 fname = inspect.getabsfile(obj)
701 except TypeError:
700 except TypeError:
702 # For an instance, the file that matters is where its class was
701 # For an instance, the file that matters is where its class was
703 # declared.
702 # declared.
704 if hasattr(obj,'__class__'):
703 if hasattr(obj,'__class__'):
705 fname = inspect.getabsfile(obj.__class__)
704 fname = inspect.getabsfile(obj.__class__)
706 if fname.endswith('<string>'):
705 if fname.endswith('<string>'):
707 fname = 'Dynamically generated function. No source code available.'
706 fname = 'Dynamically generated function. No source code available.'
708 if (fname.endswith('.so') or fname.endswith('.dll')):
707 if (fname.endswith('.so') or fname.endswith('.dll')):
709 binary_file = True
708 binary_file = True
710 out['file'] = fname
709 out['file'] = fname
711 except:
710 except:
712 # if anything goes wrong, we don't want to show source, so it's as
711 # if anything goes wrong, we don't want to show source, so it's as
713 # if the file was binary
712 # if the file was binary
714 binary_file = True
713 binary_file = True
715
714
716 # reconstruct the function definition and print it:
715 # reconstruct the function definition and print it:
717 defln = self._getdef(obj, oname)
716 defln = self._getdef(obj, oname)
718 if defln:
717 if defln:
719 out['definition'] = self.format(defln)
718 out['definition'] = self.format(defln)
720
719
721 # Docstrings only in detail 0 mode, since source contains them (we
720 # Docstrings only in detail 0 mode, since source contains them (we
722 # avoid repetitions). If source fails, we add them back, see below.
721 # avoid repetitions). If source fails, we add them back, see below.
723 if ds and detail_level == 0:
722 if ds and detail_level == 0:
724 out['docstring'] = ds
723 out['docstring'] = ds
725
724
726 # Original source code for any callable
725 # Original source code for any callable
727 if detail_level:
726 if detail_level:
728 # Flush the source cache because inspect can return out-of-date
727 # Flush the source cache because inspect can return out-of-date
729 # source
728 # source
730 linecache.checkcache()
729 linecache.checkcache()
731 source_success = False
730 source_success = False
732 try:
731 try:
733 try:
732 try:
734 src = getsource(obj,binary_file)
733 src = getsource(obj,binary_file)
735 except TypeError:
734 except TypeError:
736 if hasattr(obj,'__class__'):
735 if hasattr(obj,'__class__'):
737 src = getsource(obj.__class__,binary_file)
736 src = getsource(obj.__class__,binary_file)
738 if src is not None:
737 if src is not None:
739 source = self.format(src)
738 source = self.format(src)
740 out['source'] = source.rstrip()
739 out['source'] = source.rstrip()
741 source_success = True
740 source_success = True
742 except Exception, msg:
741 except Exception, msg:
743 pass
742 pass
744
743
745 # Constructor docstring for classes
744 # Constructor docstring for classes
746 if inspect.isclass(obj):
745 if inspect.isclass(obj):
747 # reconstruct the function definition and print it:
746 # reconstruct the function definition and print it:
748 try:
747 try:
749 obj_init = obj.__init__
748 obj_init = obj.__init__
750 except AttributeError:
749 except AttributeError:
751 init_def = init_ds = None
750 init_def = init_ds = None
752 else:
751 else:
753 init_def = self._getdef(obj_init,oname)
752 init_def = self._getdef(obj_init,oname)
754 init_ds = getdoc(obj_init)
753 init_ds = getdoc(obj_init)
755 # Skip Python's auto-generated docstrings
754 # Skip Python's auto-generated docstrings
756 if init_ds and \
755 if init_ds and \
757 init_ds.startswith('x.__init__(...) initializes'):
756 init_ds.startswith('x.__init__(...) initializes'):
758 init_ds = None
757 init_ds = None
759
758
760 if init_def or init_ds:
759 if init_def or init_ds:
761 if init_def:
760 if init_def:
762 out['init_definition'] = self.format(init_def)
761 out['init_definition'] = self.format(init_def)
763 if init_ds:
762 if init_ds:
764 out['init_docstring'] = init_ds
763 out['init_docstring'] = init_ds
765
764
766 # and class docstring for instances:
765 # and class docstring for instances:
767 elif obj_type is types.InstanceType or \
766 elif obj_type is types.InstanceType or \
768 isinstance(obj, object):
767 isinstance(obj, object):
769 # First, check whether the instance docstring is identical to the
768 # First, check whether the instance docstring is identical to the
770 # class one, and print it separately if they don't coincide. In
769 # class one, and print it separately if they don't coincide. In
771 # most cases they will, but it's nice to print all the info for
770 # most cases they will, but it's nice to print all the info for
772 # objects which use instance-customized docstrings.
771 # objects which use instance-customized docstrings.
773 if ds:
772 if ds:
774 try:
773 try:
775 cls = getattr(obj,'__class__')
774 cls = getattr(obj,'__class__')
776 except:
775 except:
777 class_ds = None
776 class_ds = None
778 else:
777 else:
779 class_ds = getdoc(cls)
778 class_ds = getdoc(cls)
780 # Skip Python's auto-generated docstrings
779 # Skip Python's auto-generated docstrings
781 if class_ds and \
780 if class_ds and \
782 (class_ds.startswith('function(code, globals[,') or \
781 (class_ds.startswith('function(code, globals[,') or \
783 class_ds.startswith('instancemethod(function, instance,') or \
782 class_ds.startswith('instancemethod(function, instance,') or \
784 class_ds.startswith('module(name[,') ):
783 class_ds.startswith('module(name[,') ):
785 class_ds = None
784 class_ds = None
786 if class_ds and ds != class_ds:
785 if class_ds and ds != class_ds:
787 out['class_docstring'] = class_ds
786 out['class_docstring'] = class_ds
788
787
789 # Next, try to show constructor docstrings
788 # Next, try to show constructor docstrings
790 try:
789 try:
791 init_ds = getdoc(obj.__init__)
790 init_ds = getdoc(obj.__init__)
792 # Skip Python's auto-generated docstrings
791 # Skip Python's auto-generated docstrings
793 if init_ds and \
792 if init_ds and \
794 init_ds.startswith('x.__init__(...) initializes'):
793 init_ds.startswith('x.__init__(...) initializes'):
795 init_ds = None
794 init_ds = None
796 except AttributeError:
795 except AttributeError:
797 init_ds = None
796 init_ds = None
798 if init_ds:
797 if init_ds:
799 out['init_docstring'] = init_ds
798 out['init_docstring'] = init_ds
800
799
801 # Call form docstring for callable instances
800 # Call form docstring for callable instances
802 if hasattr(obj, '__call__'):
801 if hasattr(obj, '__call__'):
803 call_def = self._getdef(obj.__call__, oname)
802 call_def = self._getdef(obj.__call__, oname)
804 if call_def is not None:
803 if call_def is not None:
805 out['call_def'] = self.format(call_def)
804 out['call_def'] = self.format(call_def)
806 call_ds = getdoc(obj.__call__)
805 call_ds = getdoc(obj.__call__)
807 # Skip Python's auto-generated docstrings
806 # Skip Python's auto-generated docstrings
808 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
807 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
809 call_ds = None
808 call_ds = None
810 if call_ds:
809 if call_ds:
811 out['call_docstring'] = call_ds
810 out['call_docstring'] = call_ds
812
811
813 # Compute the object's argspec as a callable. The key is to decide
812 # Compute the object's argspec as a callable. The key is to decide
814 # whether to pull it from the object itself, from its __init__ or
813 # whether to pull it from the object itself, from its __init__ or
815 # from its __call__ method.
814 # from its __call__ method.
816
815
817 if inspect.isclass(obj):
816 if inspect.isclass(obj):
818 callable_obj = obj.__init__
817 callable_obj = obj.__init__
819 elif callable(obj):
818 elif callable(obj):
820 callable_obj = obj
819 callable_obj = obj
821 else:
820 else:
822 callable_obj = None
821 callable_obj = None
823
822
824 if callable_obj:
823 if callable_obj:
825 try:
824 try:
826 args, varargs, varkw, defaults = getargspec(callable_obj)
825 args, varargs, varkw, defaults = getargspec(callable_obj)
827 except (TypeError, AttributeError):
826 except (TypeError, AttributeError):
828 # For extensions/builtins we can't retrieve the argspec
827 # For extensions/builtins we can't retrieve the argspec
829 pass
828 pass
830 else:
829 else:
831 out['argspec'] = dict(args=args, varargs=varargs,
830 out['argspec'] = dict(args=args, varargs=varargs,
832 varkw=varkw, defaults=defaults)
831 varkw=varkw, defaults=defaults)
833
832
834 return object_info(**out)
833 return object_info(**out)
835
834
836
835
837 def psearch(self,pattern,ns_table,ns_search=[],
836 def psearch(self,pattern,ns_table,ns_search=[],
838 ignore_case=False,show_all=False):
837 ignore_case=False,show_all=False):
839 """Search namespaces with wildcards for objects.
838 """Search namespaces with wildcards for objects.
840
839
841 Arguments:
840 Arguments:
842
841
843 - pattern: string containing shell-like wildcards to use in namespace
842 - pattern: string containing shell-like wildcards to use in namespace
844 searches and optionally a type specification to narrow the search to
843 searches and optionally a type specification to narrow the search to
845 objects of that type.
844 objects of that type.
846
845
847 - ns_table: dict of name->namespaces for search.
846 - ns_table: dict of name->namespaces for search.
848
847
849 Optional arguments:
848 Optional arguments:
850
849
851 - ns_search: list of namespace names to include in search.
850 - ns_search: list of namespace names to include in search.
852
851
853 - ignore_case(False): make the search case-insensitive.
852 - ignore_case(False): make the search case-insensitive.
854
853
855 - show_all(False): show all names, including those starting with
854 - show_all(False): show all names, including those starting with
856 underscores.
855 underscores.
857 """
856 """
858 #print 'ps pattern:<%r>' % pattern # dbg
857 #print 'ps pattern:<%r>' % pattern # dbg
859
858
860 # defaults
859 # defaults
861 type_pattern = 'all'
860 type_pattern = 'all'
862 filter = ''
861 filter = ''
863
862
864 cmds = pattern.split()
863 cmds = pattern.split()
865 len_cmds = len(cmds)
864 len_cmds = len(cmds)
866 if len_cmds == 1:
865 if len_cmds == 1:
867 # Only filter pattern given
866 # Only filter pattern given
868 filter = cmds[0]
867 filter = cmds[0]
869 elif len_cmds == 2:
868 elif len_cmds == 2:
870 # Both filter and type specified
869 # Both filter and type specified
871 filter,type_pattern = cmds
870 filter,type_pattern = cmds
872 else:
871 else:
873 raise ValueError('invalid argument string for psearch: <%s>' %
872 raise ValueError('invalid argument string for psearch: <%s>' %
874 pattern)
873 pattern)
875
874
876 # filter search namespaces
875 # filter search namespaces
877 for name in ns_search:
876 for name in ns_search:
878 if name not in ns_table:
877 if name not in ns_table:
879 raise ValueError('invalid namespace <%s>. Valid names: %s' %
878 raise ValueError('invalid namespace <%s>. Valid names: %s' %
880 (name,ns_table.keys()))
879 (name,ns_table.keys()))
881
880
882 #print 'type_pattern:',type_pattern # dbg
881 #print 'type_pattern:',type_pattern # dbg
883 search_result = []
882 search_result = []
884 for ns_name in ns_search:
883 for ns_name in ns_search:
885 ns = ns_table[ns_name]
884 ns = ns_table[ns_name]
886 tmp_res = list(list_namespace(ns,type_pattern,filter,
885 tmp_res = list(list_namespace(ns,type_pattern,filter,
887 ignore_case=ignore_case,
886 ignore_case=ignore_case,
888 show_all=show_all))
887 show_all=show_all))
889 search_result.extend(tmp_res)
888 search_result.extend(tmp_res)
890 search_result.sort()
889 search_result.sort()
891
890
892 page.page('\n'.join(search_result))
891 page.page('\n'.join(search_result))
@@ -1,1230 +1,1229 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 ultratb.py -- Spice up your tracebacks!
3 ultratb.py -- Spice up your tracebacks!
4
4
5 * ColorTB
5 * ColorTB
6 I've always found it a bit hard to visually parse tracebacks in Python. The
6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 ColorTB class is a solution to that problem. It colors the different parts of a
7 ColorTB class is a solution to that problem. It colors the different parts of a
8 traceback in a manner similar to what you would expect from a syntax-highlighting
8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 text editor.
9 text editor.
10
10
11 Installation instructions for ColorTB:
11 Installation instructions for ColorTB:
12 import sys,ultratb
12 import sys,ultratb
13 sys.excepthook = ultratb.ColorTB()
13 sys.excepthook = ultratb.ColorTB()
14
14
15 * VerboseTB
15 * VerboseTB
16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 of useful info when a traceback occurs. Ping originally had it spit out HTML
17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 and intended it for CGI programmers, but why should they have all the fun? I
18 and intended it for CGI programmers, but why should they have all the fun? I
19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 but kind of neat, and maybe useful for long-running programs that you believe
20 but kind of neat, and maybe useful for long-running programs that you believe
21 are bug-free. If a crash *does* occur in that type of program you want details.
21 are bug-free. If a crash *does* occur in that type of program you want details.
22 Give it a shot--you'll love it or you'll hate it.
22 Give it a shot--you'll love it or you'll hate it.
23
23
24 Note:
24 Note:
25
25
26 The Verbose mode prints the variables currently visible where the exception
26 The Verbose mode prints the variables currently visible where the exception
27 happened (shortening their strings if too long). This can potentially be
27 happened (shortening their strings if too long). This can potentially be
28 very slow, if you happen to have a huge data structure whose string
28 very slow, if you happen to have a huge data structure whose string
29 representation is complex to compute. Your computer may appear to freeze for
29 representation is complex to compute. Your computer may appear to freeze for
30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 with Ctrl-C (maybe hitting it more than once).
31 with Ctrl-C (maybe hitting it more than once).
32
32
33 If you encounter this kind of situation often, you may want to use the
33 If you encounter this kind of situation often, you may want to use the
34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 variables (but otherwise includes the information and context given by
35 variables (but otherwise includes the information and context given by
36 Verbose).
36 Verbose).
37
37
38
38
39 Installation instructions for ColorTB:
39 Installation instructions for ColorTB:
40 import sys,ultratb
40 import sys,ultratb
41 sys.excepthook = ultratb.VerboseTB()
41 sys.excepthook = ultratb.VerboseTB()
42
42
43 Note: Much of the code in this module was lifted verbatim from the standard
43 Note: Much of the code in this module was lifted verbatim from the standard
44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45
45
46 * Color schemes
46 * Color schemes
47 The colors are defined in the class TBTools through the use of the
47 The colors are defined in the class TBTools through the use of the
48 ColorSchemeTable class. Currently the following exist:
48 ColorSchemeTable class. Currently the following exist:
49
49
50 - NoColor: allows all of this module to be used in any terminal (the color
50 - NoColor: allows all of this module to be used in any terminal (the color
51 escapes are just dummy blank strings).
51 escapes are just dummy blank strings).
52
52
53 - Linux: is meant to look good in a terminal like the Linux console (black
53 - Linux: is meant to look good in a terminal like the Linux console (black
54 or very dark background).
54 or very dark background).
55
55
56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 in light background terminals.
57 in light background terminals.
58
58
59 You can implement other color schemes easily, the syntax is fairly
59 You can implement other color schemes easily, the syntax is fairly
60 self-explanatory. Please send back new schemes you develop to the author for
60 self-explanatory. Please send back new schemes you develop to the author for
61 possible inclusion in future releases.
61 possible inclusion in future releases.
62 """
62 """
63
63
64 #*****************************************************************************
64 #*****************************************************************************
65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 #
67 #
68 # Distributed under the terms of the BSD License. The full license is in
68 # Distributed under the terms of the BSD License. The full license is in
69 # the file COPYING, distributed as part of this software.
69 # the file COPYING, distributed as part of this software.
70 #*****************************************************************************
70 #*****************************************************************************
71
71
72 from __future__ import with_statement
72 from __future__ import with_statement
73
73
74 import inspect
74 import inspect
75 import keyword
75 import keyword
76 import linecache
76 import linecache
77 import os
77 import os
78 import pydoc
78 import pydoc
79 import re
79 import re
80 import string
81 import sys
80 import sys
82 import time
81 import time
83 import tokenize
82 import tokenize
84 import traceback
83 import traceback
85 import types
84 import types
86
85
87 # For purposes of monkeypatching inspect to fix a bug in it.
86 # For purposes of monkeypatching inspect to fix a bug in it.
88 from inspect import getsourcefile, getfile, getmodule,\
87 from inspect import getsourcefile, getfile, getmodule,\
89 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
90
89
91 # IPython's own modules
90 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
91 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython.core import debugger, ipapi
92 from IPython.core import debugger, ipapi
94 from IPython.core.display_trap import DisplayTrap
93 from IPython.core.display_trap import DisplayTrap
95 from IPython.core.excolors import exception_colors
94 from IPython.core.excolors import exception_colors
96 from IPython.utils import PyColorize
95 from IPython.utils import PyColorize
97 from IPython.utils import io
96 from IPython.utils import io
98 from IPython.utils.data import uniq_stable
97 from IPython.utils.data import uniq_stable
99 from IPython.utils.warn import info, error
98 from IPython.utils.warn import info, error
100
99
101 # Globals
100 # Globals
102 # amount of space to put line numbers before verbose tracebacks
101 # amount of space to put line numbers before verbose tracebacks
103 INDENT_SIZE = 8
102 INDENT_SIZE = 8
104
103
105 # Default color scheme. This is used, for example, by the traceback
104 # Default color scheme. This is used, for example, by the traceback
106 # formatter. When running in an actual IPython instance, the user's rc.colors
105 # formatter. When running in an actual IPython instance, the user's rc.colors
107 # value is used, but havinga module global makes this functionality available
106 # value is used, but havinga module global makes this functionality available
108 # to users of ultratb who are NOT running inside ipython.
107 # to users of ultratb who are NOT running inside ipython.
109 DEFAULT_SCHEME = 'NoColor'
108 DEFAULT_SCHEME = 'NoColor'
110
109
111 #---------------------------------------------------------------------------
110 #---------------------------------------------------------------------------
112 # Code begins
111 # Code begins
113
112
114 # Utility functions
113 # Utility functions
115 def inspect_error():
114 def inspect_error():
116 """Print a message about internal inspect errors.
115 """Print a message about internal inspect errors.
117
116
118 These are unfortunately quite common."""
117 These are unfortunately quite common."""
119
118
120 error('Internal Python error in the inspect module.\n'
119 error('Internal Python error in the inspect module.\n'
121 'Below is the traceback from this internal error.\n')
120 'Below is the traceback from this internal error.\n')
122
121
123
122
124 def findsource(object):
123 def findsource(object):
125 """Return the entire source file and starting line number for an object.
124 """Return the entire source file and starting line number for an object.
126
125
127 The argument may be a module, class, method, function, traceback, frame,
126 The argument may be a module, class, method, function, traceback, frame,
128 or code object. The source code is returned as a list of all the lines
127 or code object. The source code is returned as a list of all the lines
129 in the file and the line number indexes a line in that list. An IOError
128 in the file and the line number indexes a line in that list. An IOError
130 is raised if the source code cannot be retrieved.
129 is raised if the source code cannot be retrieved.
131
130
132 FIXED version with which we monkeypatch the stdlib to work around a bug."""
131 FIXED version with which we monkeypatch the stdlib to work around a bug."""
133
132
134 file = getsourcefile(object) or getfile(object)
133 file = getsourcefile(object) or getfile(object)
135 # If the object is a frame, then trying to get the globals dict from its
134 # If the object is a frame, then trying to get the globals dict from its
136 # module won't work. Instead, the frame object itself has the globals
135 # module won't work. Instead, the frame object itself has the globals
137 # dictionary.
136 # dictionary.
138 globals_dict = None
137 globals_dict = None
139 if inspect.isframe(object):
138 if inspect.isframe(object):
140 # XXX: can this ever be false?
139 # XXX: can this ever be false?
141 globals_dict = object.f_globals
140 globals_dict = object.f_globals
142 else:
141 else:
143 module = getmodule(object, file)
142 module = getmodule(object, file)
144 if module:
143 if module:
145 globals_dict = module.__dict__
144 globals_dict = module.__dict__
146 lines = linecache.getlines(file, globals_dict)
145 lines = linecache.getlines(file, globals_dict)
147 if not lines:
146 if not lines:
148 raise IOError('could not get source code')
147 raise IOError('could not get source code')
149
148
150 if ismodule(object):
149 if ismodule(object):
151 return lines, 0
150 return lines, 0
152
151
153 if isclass(object):
152 if isclass(object):
154 name = object.__name__
153 name = object.__name__
155 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
154 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
156 # make some effort to find the best matching class definition:
155 # make some effort to find the best matching class definition:
157 # use the one with the least indentation, which is the one
156 # use the one with the least indentation, which is the one
158 # that's most probably not inside a function definition.
157 # that's most probably not inside a function definition.
159 candidates = []
158 candidates = []
160 for i in range(len(lines)):
159 for i in range(len(lines)):
161 match = pat.match(lines[i])
160 match = pat.match(lines[i])
162 if match:
161 if match:
163 # if it's at toplevel, it's already the best one
162 # if it's at toplevel, it's already the best one
164 if lines[i][0] == 'c':
163 if lines[i][0] == 'c':
165 return lines, i
164 return lines, i
166 # else add whitespace to candidate list
165 # else add whitespace to candidate list
167 candidates.append((match.group(1), i))
166 candidates.append((match.group(1), i))
168 if candidates:
167 if candidates:
169 # this will sort by whitespace, and by line number,
168 # this will sort by whitespace, and by line number,
170 # less whitespace first
169 # less whitespace first
171 candidates.sort()
170 candidates.sort()
172 return lines, candidates[0][1]
171 return lines, candidates[0][1]
173 else:
172 else:
174 raise IOError('could not find class definition')
173 raise IOError('could not find class definition')
175
174
176 if ismethod(object):
175 if ismethod(object):
177 object = object.im_func
176 object = object.im_func
178 if isfunction(object):
177 if isfunction(object):
179 object = object.func_code
178 object = object.func_code
180 if istraceback(object):
179 if istraceback(object):
181 object = object.tb_frame
180 object = object.tb_frame
182 if isframe(object):
181 if isframe(object):
183 object = object.f_code
182 object = object.f_code
184 if iscode(object):
183 if iscode(object):
185 if not hasattr(object, 'co_firstlineno'):
184 if not hasattr(object, 'co_firstlineno'):
186 raise IOError('could not find function definition')
185 raise IOError('could not find function definition')
187 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
186 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
188 pmatch = pat.match
187 pmatch = pat.match
189 # fperez - fix: sometimes, co_firstlineno can give a number larger than
188 # fperez - fix: sometimes, co_firstlineno can give a number larger than
190 # the length of lines, which causes an error. Safeguard against that.
189 # the length of lines, which causes an error. Safeguard against that.
191 lnum = min(object.co_firstlineno,len(lines))-1
190 lnum = min(object.co_firstlineno,len(lines))-1
192 while lnum > 0:
191 while lnum > 0:
193 if pmatch(lines[lnum]): break
192 if pmatch(lines[lnum]): break
194 lnum -= 1
193 lnum -= 1
195
194
196 return lines, lnum
195 return lines, lnum
197 raise IOError('could not find code object')
196 raise IOError('could not find code object')
198
197
199 # Monkeypatch inspect to apply our bugfix. This code only works with py25
198 # Monkeypatch inspect to apply our bugfix. This code only works with py25
200 if sys.version_info[:2] >= (2,5):
199 if sys.version_info[:2] >= (2,5):
201 inspect.findsource = findsource
200 inspect.findsource = findsource
202
201
203 def fix_frame_records_filenames(records):
202 def fix_frame_records_filenames(records):
204 """Try to fix the filenames in each record from inspect.getinnerframes().
203 """Try to fix the filenames in each record from inspect.getinnerframes().
205
204
206 Particularly, modules loaded from within zip files have useless filenames
205 Particularly, modules loaded from within zip files have useless filenames
207 attached to their code object, and inspect.getinnerframes() just uses it.
206 attached to their code object, and inspect.getinnerframes() just uses it.
208 """
207 """
209 fixed_records = []
208 fixed_records = []
210 for frame, filename, line_no, func_name, lines, index in records:
209 for frame, filename, line_no, func_name, lines, index in records:
211 # Look inside the frame's globals dictionary for __file__, which should
210 # Look inside the frame's globals dictionary for __file__, which should
212 # be better.
211 # be better.
213 better_fn = frame.f_globals.get('__file__', None)
212 better_fn = frame.f_globals.get('__file__', None)
214 if isinstance(better_fn, str):
213 if isinstance(better_fn, str):
215 # Check the type just in case someone did something weird with
214 # Check the type just in case someone did something weird with
216 # __file__. It might also be None if the error occurred during
215 # __file__. It might also be None if the error occurred during
217 # import.
216 # import.
218 filename = better_fn
217 filename = better_fn
219 fixed_records.append((frame, filename, line_no, func_name, lines, index))
218 fixed_records.append((frame, filename, line_no, func_name, lines, index))
220 return fixed_records
219 return fixed_records
221
220
222
221
223 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
222 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
224 import linecache
223 import linecache
225 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
224 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
226
225
227 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
226 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
228
227
229 # If the error is at the console, don't build any context, since it would
228 # If the error is at the console, don't build any context, since it would
230 # otherwise produce 5 blank lines printed out (there is no file at the
229 # otherwise produce 5 blank lines printed out (there is no file at the
231 # console)
230 # console)
232 rec_check = records[tb_offset:]
231 rec_check = records[tb_offset:]
233 try:
232 try:
234 rname = rec_check[0][1]
233 rname = rec_check[0][1]
235 if rname == '<ipython console>' or rname.endswith('<string>'):
234 if rname == '<ipython console>' or rname.endswith('<string>'):
236 return rec_check
235 return rec_check
237 except IndexError:
236 except IndexError:
238 pass
237 pass
239
238
240 aux = traceback.extract_tb(etb)
239 aux = traceback.extract_tb(etb)
241 assert len(records) == len(aux)
240 assert len(records) == len(aux)
242 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
241 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
243 maybeStart = lnum-1 - context//2
242 maybeStart = lnum-1 - context//2
244 start = max(maybeStart, 0)
243 start = max(maybeStart, 0)
245 end = start + context
244 end = start + context
246 lines = linecache.getlines(file)[start:end]
245 lines = linecache.getlines(file)[start:end]
247 # pad with empty lines if necessary
246 # pad with empty lines if necessary
248 if maybeStart < 0:
247 if maybeStart < 0:
249 lines = (['\n'] * -maybeStart) + lines
248 lines = (['\n'] * -maybeStart) + lines
250 if len(lines) < context:
249 if len(lines) < context:
251 lines += ['\n'] * (context - len(lines))
250 lines += ['\n'] * (context - len(lines))
252 buf = list(records[i])
251 buf = list(records[i])
253 buf[LNUM_POS] = lnum
252 buf[LNUM_POS] = lnum
254 buf[INDEX_POS] = lnum - 1 - start
253 buf[INDEX_POS] = lnum - 1 - start
255 buf[LINES_POS] = lines
254 buf[LINES_POS] = lines
256 records[i] = tuple(buf)
255 records[i] = tuple(buf)
257 return records[tb_offset:]
256 return records[tb_offset:]
258
257
259 # Helper function -- largely belongs to VerboseTB, but we need the same
258 # Helper function -- largely belongs to VerboseTB, but we need the same
260 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
259 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
261 # can be recognized properly by ipython.el's py-traceback-line-re
260 # can be recognized properly by ipython.el's py-traceback-line-re
262 # (SyntaxErrors have to be treated specially because they have no traceback)
261 # (SyntaxErrors have to be treated specially because they have no traceback)
263
262
264 _parser = PyColorize.Parser()
263 _parser = PyColorize.Parser()
265
264
266 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
265 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
267 numbers_width = INDENT_SIZE - 1
266 numbers_width = INDENT_SIZE - 1
268 res = []
267 res = []
269 i = lnum - index
268 i = lnum - index
270
269
271 # This lets us get fully syntax-highlighted tracebacks.
270 # This lets us get fully syntax-highlighted tracebacks.
272 if scheme is None:
271 if scheme is None:
273 ipinst = ipapi.get()
272 ipinst = ipapi.get()
274 if ipinst is not None:
273 if ipinst is not None:
275 scheme = ipinst.colors
274 scheme = ipinst.colors
276 else:
275 else:
277 scheme = DEFAULT_SCHEME
276 scheme = DEFAULT_SCHEME
278
277
279 _line_format = _parser.format2
278 _line_format = _parser.format2
280
279
281 for line in lines:
280 for line in lines:
282 new_line, err = _line_format(line,'str',scheme)
281 new_line, err = _line_format(line,'str',scheme)
283 if not err: line = new_line
282 if not err: line = new_line
284
283
285 if i == lnum:
284 if i == lnum:
286 # This is the line with the error
285 # This is the line with the error
287 pad = numbers_width - len(str(i))
286 pad = numbers_width - len(str(i))
288 if pad >= 3:
287 if pad >= 3:
289 marker = '-'*(pad-3) + '-> '
288 marker = '-'*(pad-3) + '-> '
290 elif pad == 2:
289 elif pad == 2:
291 marker = '> '
290 marker = '> '
292 elif pad == 1:
291 elif pad == 1:
293 marker = '>'
292 marker = '>'
294 else:
293 else:
295 marker = ''
294 marker = ''
296 num = marker + str(i)
295 num = marker + str(i)
297 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
296 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
298 Colors.line, line, Colors.Normal)
297 Colors.line, line, Colors.Normal)
299 else:
298 else:
300 num = '%*s' % (numbers_width,i)
299 num = '%*s' % (numbers_width,i)
301 line = '%s%s%s %s' %(Colors.lineno, num,
300 line = '%s%s%s %s' %(Colors.lineno, num,
302 Colors.Normal, line)
301 Colors.Normal, line)
303
302
304 res.append(line)
303 res.append(line)
305 if lvals and i == lnum:
304 if lvals and i == lnum:
306 res.append(lvals + '\n')
305 res.append(lvals + '\n')
307 i = i + 1
306 i = i + 1
308 return res
307 return res
309
308
310
309
311 #---------------------------------------------------------------------------
310 #---------------------------------------------------------------------------
312 # Module classes
311 # Module classes
313 class TBTools(object):
312 class TBTools(object):
314 """Basic tools used by all traceback printer classes."""
313 """Basic tools used by all traceback printer classes."""
315
314
316 # Number of frames to skip when reporting tracebacks
315 # Number of frames to skip when reporting tracebacks
317 tb_offset = 0
316 tb_offset = 0
318
317
319 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
318 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
320 # Whether to call the interactive pdb debugger after printing
319 # Whether to call the interactive pdb debugger after printing
321 # tracebacks or not
320 # tracebacks or not
322 self.call_pdb = call_pdb
321 self.call_pdb = call_pdb
323
322
324 # Output stream to write to. Note that we store the original value in
323 # Output stream to write to. Note that we store the original value in
325 # a private attribute and then make the public ostream a property, so
324 # a private attribute and then make the public ostream a property, so
326 # that we can delay accessing io.Term.cout until runtime. The way
325 # that we can delay accessing io.Term.cout until runtime. The way
327 # things are written now, the Term.cout object is dynamically managed
326 # things are written now, the Term.cout object is dynamically managed
328 # so a reference to it should NEVER be stored statically. This
327 # so a reference to it should NEVER be stored statically. This
329 # property approach confines this detail to a single location, and all
328 # property approach confines this detail to a single location, and all
330 # subclasses can simply access self.ostream for writing.
329 # subclasses can simply access self.ostream for writing.
331 self._ostream = ostream
330 self._ostream = ostream
332
331
333 # Create color table
332 # Create color table
334 self.color_scheme_table = exception_colors()
333 self.color_scheme_table = exception_colors()
335
334
336 self.set_colors(color_scheme)
335 self.set_colors(color_scheme)
337 self.old_scheme = color_scheme # save initial value for toggles
336 self.old_scheme = color_scheme # save initial value for toggles
338
337
339 if call_pdb:
338 if call_pdb:
340 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
339 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
341 else:
340 else:
342 self.pdb = None
341 self.pdb = None
343
342
344 def _get_ostream(self):
343 def _get_ostream(self):
345 """Output stream that exceptions are written to.
344 """Output stream that exceptions are written to.
346
345
347 Valid values are:
346 Valid values are:
348
347
349 - None: the default, which means that IPython will dynamically resolve
348 - None: the default, which means that IPython will dynamically resolve
350 to io.Term.cout. This ensures compatibility with most tools, including
349 to io.Term.cout. This ensures compatibility with most tools, including
351 Windows (where plain stdout doesn't recognize ANSI escapes).
350 Windows (where plain stdout doesn't recognize ANSI escapes).
352
351
353 - Any object with 'write' and 'flush' attributes.
352 - Any object with 'write' and 'flush' attributes.
354 """
353 """
355 return io.Term.cout if self._ostream is None else self._ostream
354 return io.Term.cout if self._ostream is None else self._ostream
356
355
357 def _set_ostream(self, val):
356 def _set_ostream(self, val):
358 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
357 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
359 self._ostream = val
358 self._ostream = val
360
359
361 ostream = property(_get_ostream, _set_ostream)
360 ostream = property(_get_ostream, _set_ostream)
362
361
363 def set_colors(self,*args,**kw):
362 def set_colors(self,*args,**kw):
364 """Shorthand access to the color table scheme selector method."""
363 """Shorthand access to the color table scheme selector method."""
365
364
366 # Set own color table
365 # Set own color table
367 self.color_scheme_table.set_active_scheme(*args,**kw)
366 self.color_scheme_table.set_active_scheme(*args,**kw)
368 # for convenience, set Colors to the active scheme
367 # for convenience, set Colors to the active scheme
369 self.Colors = self.color_scheme_table.active_colors
368 self.Colors = self.color_scheme_table.active_colors
370 # Also set colors of debugger
369 # Also set colors of debugger
371 if hasattr(self,'pdb') and self.pdb is not None:
370 if hasattr(self,'pdb') and self.pdb is not None:
372 self.pdb.set_colors(*args,**kw)
371 self.pdb.set_colors(*args,**kw)
373
372
374 def color_toggle(self):
373 def color_toggle(self):
375 """Toggle between the currently active color scheme and NoColor."""
374 """Toggle between the currently active color scheme and NoColor."""
376
375
377 if self.color_scheme_table.active_scheme_name == 'NoColor':
376 if self.color_scheme_table.active_scheme_name == 'NoColor':
378 self.color_scheme_table.set_active_scheme(self.old_scheme)
377 self.color_scheme_table.set_active_scheme(self.old_scheme)
379 self.Colors = self.color_scheme_table.active_colors
378 self.Colors = self.color_scheme_table.active_colors
380 else:
379 else:
381 self.old_scheme = self.color_scheme_table.active_scheme_name
380 self.old_scheme = self.color_scheme_table.active_scheme_name
382 self.color_scheme_table.set_active_scheme('NoColor')
381 self.color_scheme_table.set_active_scheme('NoColor')
383 self.Colors = self.color_scheme_table.active_colors
382 self.Colors = self.color_scheme_table.active_colors
384
383
385 def stb2text(self, stb):
384 def stb2text(self, stb):
386 """Convert a structured traceback (a list) to a string."""
385 """Convert a structured traceback (a list) to a string."""
387 return '\n'.join(stb)
386 return '\n'.join(stb)
388
387
389 def text(self, etype, value, tb, tb_offset=None, context=5):
388 def text(self, etype, value, tb, tb_offset=None, context=5):
390 """Return formatted traceback.
389 """Return formatted traceback.
391
390
392 Subclasses may override this if they add extra arguments.
391 Subclasses may override this if they add extra arguments.
393 """
392 """
394 tb_list = self.structured_traceback(etype, value, tb,
393 tb_list = self.structured_traceback(etype, value, tb,
395 tb_offset, context)
394 tb_offset, context)
396 return self.stb2text(tb_list)
395 return self.stb2text(tb_list)
397
396
398 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
397 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
399 context=5, mode=None):
398 context=5, mode=None):
400 """Return a list of traceback frames.
399 """Return a list of traceback frames.
401
400
402 Must be implemented by each class.
401 Must be implemented by each class.
403 """
402 """
404 raise NotImplementedError()
403 raise NotImplementedError()
405
404
406
405
407 #---------------------------------------------------------------------------
406 #---------------------------------------------------------------------------
408 class ListTB(TBTools):
407 class ListTB(TBTools):
409 """Print traceback information from a traceback list, with optional color.
408 """Print traceback information from a traceback list, with optional color.
410
409
411 Calling: requires 3 arguments:
410 Calling: requires 3 arguments:
412 (etype, evalue, elist)
411 (etype, evalue, elist)
413 as would be obtained by:
412 as would be obtained by:
414 etype, evalue, tb = sys.exc_info()
413 etype, evalue, tb = sys.exc_info()
415 if tb:
414 if tb:
416 elist = traceback.extract_tb(tb)
415 elist = traceback.extract_tb(tb)
417 else:
416 else:
418 elist = None
417 elist = None
419
418
420 It can thus be used by programs which need to process the traceback before
419 It can thus be used by programs which need to process the traceback before
421 printing (such as console replacements based on the code module from the
420 printing (such as console replacements based on the code module from the
422 standard library).
421 standard library).
423
422
424 Because they are meant to be called without a full traceback (only a
423 Because they are meant to be called without a full traceback (only a
425 list), instances of this class can't call the interactive pdb debugger."""
424 list), instances of this class can't call the interactive pdb debugger."""
426
425
427 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
426 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
428 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
427 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
429 ostream=ostream)
428 ostream=ostream)
430
429
431 def __call__(self, etype, value, elist):
430 def __call__(self, etype, value, elist):
432 self.ostream.flush()
431 self.ostream.flush()
433 self.ostream.write(self.text(etype, value, elist))
432 self.ostream.write(self.text(etype, value, elist))
434 self.ostream.write('\n')
433 self.ostream.write('\n')
435
434
436 def structured_traceback(self, etype, value, elist, tb_offset=None,
435 def structured_traceback(self, etype, value, elist, tb_offset=None,
437 context=5):
436 context=5):
438 """Return a color formatted string with the traceback info.
437 """Return a color formatted string with the traceback info.
439
438
440 Parameters
439 Parameters
441 ----------
440 ----------
442 etype : exception type
441 etype : exception type
443 Type of the exception raised.
442 Type of the exception raised.
444
443
445 value : object
444 value : object
446 Data stored in the exception
445 Data stored in the exception
447
446
448 elist : list
447 elist : list
449 List of frames, see class docstring for details.
448 List of frames, see class docstring for details.
450
449
451 tb_offset : int, optional
450 tb_offset : int, optional
452 Number of frames in the traceback to skip. If not given, the
451 Number of frames in the traceback to skip. If not given, the
453 instance value is used (set in constructor).
452 instance value is used (set in constructor).
454
453
455 context : int, optional
454 context : int, optional
456 Number of lines of context information to print.
455 Number of lines of context information to print.
457
456
458 Returns
457 Returns
459 -------
458 -------
460 String with formatted exception.
459 String with formatted exception.
461 """
460 """
462 tb_offset = self.tb_offset if tb_offset is None else tb_offset
461 tb_offset = self.tb_offset if tb_offset is None else tb_offset
463 Colors = self.Colors
462 Colors = self.Colors
464 out_list = []
463 out_list = []
465 if elist:
464 if elist:
466
465
467 if tb_offset and len(elist) > tb_offset:
466 if tb_offset and len(elist) > tb_offset:
468 elist = elist[tb_offset:]
467 elist = elist[tb_offset:]
469
468
470 out_list.append('Traceback %s(most recent call last)%s:' %
469 out_list.append('Traceback %s(most recent call last)%s:' %
471 (Colors.normalEm, Colors.Normal) + '\n')
470 (Colors.normalEm, Colors.Normal) + '\n')
472 out_list.extend(self._format_list(elist))
471 out_list.extend(self._format_list(elist))
473 # The exception info should be a single entry in the list.
472 # The exception info should be a single entry in the list.
474 lines = ''.join(self._format_exception_only(etype, value))
473 lines = ''.join(self._format_exception_only(etype, value))
475 out_list.append(lines)
474 out_list.append(lines)
476
475
477 # Note: this code originally read:
476 # Note: this code originally read:
478
477
479 ## for line in lines[:-1]:
478 ## for line in lines[:-1]:
480 ## out_list.append(" "+line)
479 ## out_list.append(" "+line)
481 ## out_list.append(lines[-1])
480 ## out_list.append(lines[-1])
482
481
483 # This means it was indenting everything but the last line by a little
482 # This means it was indenting everything but the last line by a little
484 # bit. I've disabled this for now, but if we see ugliness somewhre we
483 # bit. I've disabled this for now, but if we see ugliness somewhre we
485 # can restore it.
484 # can restore it.
486
485
487 return out_list
486 return out_list
488
487
489 def _format_list(self, extracted_list):
488 def _format_list(self, extracted_list):
490 """Format a list of traceback entry tuples for printing.
489 """Format a list of traceback entry tuples for printing.
491
490
492 Given a list of tuples as returned by extract_tb() or
491 Given a list of tuples as returned by extract_tb() or
493 extract_stack(), return a list of strings ready for printing.
492 extract_stack(), return a list of strings ready for printing.
494 Each string in the resulting list corresponds to the item with the
493 Each string in the resulting list corresponds to the item with the
495 same index in the argument list. Each string ends in a newline;
494 same index in the argument list. Each string ends in a newline;
496 the strings may contain internal newlines as well, for those items
495 the strings may contain internal newlines as well, for those items
497 whose source text line is not None.
496 whose source text line is not None.
498
497
499 Lifted almost verbatim from traceback.py
498 Lifted almost verbatim from traceback.py
500 """
499 """
501
500
502 Colors = self.Colors
501 Colors = self.Colors
503 list = []
502 list = []
504 for filename, lineno, name, line in extracted_list[:-1]:
503 for filename, lineno, name, line in extracted_list[:-1]:
505 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
504 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
506 (Colors.filename, filename, Colors.Normal,
505 (Colors.filename, filename, Colors.Normal,
507 Colors.lineno, lineno, Colors.Normal,
506 Colors.lineno, lineno, Colors.Normal,
508 Colors.name, name, Colors.Normal)
507 Colors.name, name, Colors.Normal)
509 if line:
508 if line:
510 item = item + ' %s\n' % line.strip()
509 item = item + ' %s\n' % line.strip()
511 list.append(item)
510 list.append(item)
512 # Emphasize the last entry
511 # Emphasize the last entry
513 filename, lineno, name, line = extracted_list[-1]
512 filename, lineno, name, line = extracted_list[-1]
514 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
513 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
515 (Colors.normalEm,
514 (Colors.normalEm,
516 Colors.filenameEm, filename, Colors.normalEm,
515 Colors.filenameEm, filename, Colors.normalEm,
517 Colors.linenoEm, lineno, Colors.normalEm,
516 Colors.linenoEm, lineno, Colors.normalEm,
518 Colors.nameEm, name, Colors.normalEm,
517 Colors.nameEm, name, Colors.normalEm,
519 Colors.Normal)
518 Colors.Normal)
520 if line:
519 if line:
521 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
520 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
522 Colors.Normal)
521 Colors.Normal)
523 list.append(item)
522 list.append(item)
524 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
523 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
525 return list
524 return list
526
525
527 def _format_exception_only(self, etype, value):
526 def _format_exception_only(self, etype, value):
528 """Format the exception part of a traceback.
527 """Format the exception part of a traceback.
529
528
530 The arguments are the exception type and value such as given by
529 The arguments are the exception type and value such as given by
531 sys.exc_info()[:2]. The return value is a list of strings, each ending
530 sys.exc_info()[:2]. The return value is a list of strings, each ending
532 in a newline. Normally, the list contains a single string; however,
531 in a newline. Normally, the list contains a single string; however,
533 for SyntaxError exceptions, it contains several lines that (when
532 for SyntaxError exceptions, it contains several lines that (when
534 printed) display detailed information about where the syntax error
533 printed) display detailed information about where the syntax error
535 occurred. The message indicating which exception occurred is the
534 occurred. The message indicating which exception occurred is the
536 always last string in the list.
535 always last string in the list.
537
536
538 Also lifted nearly verbatim from traceback.py
537 Also lifted nearly verbatim from traceback.py
539 """
538 """
540
539
541 have_filedata = False
540 have_filedata = False
542 Colors = self.Colors
541 Colors = self.Colors
543 list = []
542 list = []
544 try:
543 try:
545 stype = Colors.excName + etype.__name__ + Colors.Normal
544 stype = Colors.excName + etype.__name__ + Colors.Normal
546 except AttributeError:
545 except AttributeError:
547 stype = etype # String exceptions don't get special coloring
546 stype = etype # String exceptions don't get special coloring
548 if value is None:
547 if value is None:
549 list.append( str(stype) + '\n')
548 list.append( str(stype) + '\n')
550 else:
549 else:
551 if etype is SyntaxError:
550 if etype is SyntaxError:
552 try:
551 try:
553 msg, (filename, lineno, offset, line) = value
552 msg, (filename, lineno, offset, line) = value
554 except:
553 except:
555 have_filedata = False
554 have_filedata = False
556 else:
555 else:
557 have_filedata = True
556 have_filedata = True
558 #print 'filename is',filename # dbg
557 #print 'filename is',filename # dbg
559 if not filename: filename = "<string>"
558 if not filename: filename = "<string>"
560 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
559 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
561 (Colors.normalEm,
560 (Colors.normalEm,
562 Colors.filenameEm, filename, Colors.normalEm,
561 Colors.filenameEm, filename, Colors.normalEm,
563 Colors.linenoEm, lineno, Colors.Normal ))
562 Colors.linenoEm, lineno, Colors.Normal ))
564 if line is not None:
563 if line is not None:
565 i = 0
564 i = 0
566 while i < len(line) and line[i].isspace():
565 while i < len(line) and line[i].isspace():
567 i = i+1
566 i = i+1
568 list.append('%s %s%s\n' % (Colors.line,
567 list.append('%s %s%s\n' % (Colors.line,
569 line.strip(),
568 line.strip(),
570 Colors.Normal))
569 Colors.Normal))
571 if offset is not None:
570 if offset is not None:
572 s = ' '
571 s = ' '
573 for c in line[i:offset-1]:
572 for c in line[i:offset-1]:
574 if c.isspace():
573 if c.isspace():
575 s = s + c
574 s = s + c
576 else:
575 else:
577 s = s + ' '
576 s = s + ' '
578 list.append('%s%s^%s\n' % (Colors.caret, s,
577 list.append('%s%s^%s\n' % (Colors.caret, s,
579 Colors.Normal) )
578 Colors.Normal) )
580 value = msg
579 value = msg
581 s = self._some_str(value)
580 s = self._some_str(value)
582 if s:
581 if s:
583 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
582 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
584 Colors.Normal, s))
583 Colors.Normal, s))
585 else:
584 else:
586 list.append('%s\n' % str(stype))
585 list.append('%s\n' % str(stype))
587
586
588 # sync with user hooks
587 # sync with user hooks
589 if have_filedata:
588 if have_filedata:
590 ipinst = ipapi.get()
589 ipinst = ipapi.get()
591 if ipinst is not None:
590 if ipinst is not None:
592 ipinst.hooks.synchronize_with_editor(filename, lineno, 0)
591 ipinst.hooks.synchronize_with_editor(filename, lineno, 0)
593
592
594 return list
593 return list
595
594
596 def get_exception_only(self, etype, value):
595 def get_exception_only(self, etype, value):
597 """Only print the exception type and message, without a traceback.
596 """Only print the exception type and message, without a traceback.
598
597
599 Parameters
598 Parameters
600 ----------
599 ----------
601 etype : exception type
600 etype : exception type
602 value : exception value
601 value : exception value
603 """
602 """
604 return ListTB.structured_traceback(self, etype, value, [])
603 return ListTB.structured_traceback(self, etype, value, [])
605
604
606
605
607 def show_exception_only(self, etype, evalue):
606 def show_exception_only(self, etype, evalue):
608 """Only print the exception type and message, without a traceback.
607 """Only print the exception type and message, without a traceback.
609
608
610 Parameters
609 Parameters
611 ----------
610 ----------
612 etype : exception type
611 etype : exception type
613 value : exception value
612 value : exception value
614 """
613 """
615 # This method needs to use __call__ from *this* class, not the one from
614 # This method needs to use __call__ from *this* class, not the one from
616 # a subclass whose signature or behavior may be different
615 # a subclass whose signature or behavior may be different
617 ostream = self.ostream
616 ostream = self.ostream
618 ostream.flush()
617 ostream.flush()
619 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
618 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
620 ostream.flush()
619 ostream.flush()
621
620
622 def _some_str(self, value):
621 def _some_str(self, value):
623 # Lifted from traceback.py
622 # Lifted from traceback.py
624 try:
623 try:
625 return str(value)
624 return str(value)
626 except:
625 except:
627 return '<unprintable %s object>' % type(value).__name__
626 return '<unprintable %s object>' % type(value).__name__
628
627
629 #----------------------------------------------------------------------------
628 #----------------------------------------------------------------------------
630 class VerboseTB(TBTools):
629 class VerboseTB(TBTools):
631 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
630 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
632 of HTML. Requires inspect and pydoc. Crazy, man.
631 of HTML. Requires inspect and pydoc. Crazy, man.
633
632
634 Modified version which optionally strips the topmost entries from the
633 Modified version which optionally strips the topmost entries from the
635 traceback, to be used with alternate interpreters (because their own code
634 traceback, to be used with alternate interpreters (because their own code
636 would appear in the traceback)."""
635 would appear in the traceback)."""
637
636
638 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
637 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
639 tb_offset=0, long_header=False, include_vars=True):
638 tb_offset=0, long_header=False, include_vars=True):
640 """Specify traceback offset, headers and color scheme.
639 """Specify traceback offset, headers and color scheme.
641
640
642 Define how many frames to drop from the tracebacks. Calling it with
641 Define how many frames to drop from the tracebacks. Calling it with
643 tb_offset=1 allows use of this handler in interpreters which will have
642 tb_offset=1 allows use of this handler in interpreters which will have
644 their own code at the top of the traceback (VerboseTB will first
643 their own code at the top of the traceback (VerboseTB will first
645 remove that frame before printing the traceback info)."""
644 remove that frame before printing the traceback info)."""
646 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
645 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
647 ostream=ostream)
646 ostream=ostream)
648 self.tb_offset = tb_offset
647 self.tb_offset = tb_offset
649 self.long_header = long_header
648 self.long_header = long_header
650 self.include_vars = include_vars
649 self.include_vars = include_vars
651
650
652 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
651 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
653 context=5):
652 context=5):
654 """Return a nice text document describing the traceback."""
653 """Return a nice text document describing the traceback."""
655
654
656 tb_offset = self.tb_offset if tb_offset is None else tb_offset
655 tb_offset = self.tb_offset if tb_offset is None else tb_offset
657
656
658 # some locals
657 # some locals
659 try:
658 try:
660 etype = etype.__name__
659 etype = etype.__name__
661 except AttributeError:
660 except AttributeError:
662 pass
661 pass
663 Colors = self.Colors # just a shorthand + quicker name lookup
662 Colors = self.Colors # just a shorthand + quicker name lookup
664 ColorsNormal = Colors.Normal # used a lot
663 ColorsNormal = Colors.Normal # used a lot
665 col_scheme = self.color_scheme_table.active_scheme_name
664 col_scheme = self.color_scheme_table.active_scheme_name
666 indent = ' '*INDENT_SIZE
665 indent = ' '*INDENT_SIZE
667 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
666 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
668 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
667 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
669 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
668 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
670
669
671 # some internal-use functions
670 # some internal-use functions
672 def text_repr(value):
671 def text_repr(value):
673 """Hopefully pretty robust repr equivalent."""
672 """Hopefully pretty robust repr equivalent."""
674 # this is pretty horrible but should always return *something*
673 # this is pretty horrible but should always return *something*
675 try:
674 try:
676 return pydoc.text.repr(value)
675 return pydoc.text.repr(value)
677 except KeyboardInterrupt:
676 except KeyboardInterrupt:
678 raise
677 raise
679 except:
678 except:
680 try:
679 try:
681 return repr(value)
680 return repr(value)
682 except KeyboardInterrupt:
681 except KeyboardInterrupt:
683 raise
682 raise
684 except:
683 except:
685 try:
684 try:
686 # all still in an except block so we catch
685 # all still in an except block so we catch
687 # getattr raising
686 # getattr raising
688 name = getattr(value, '__name__', None)
687 name = getattr(value, '__name__', None)
689 if name:
688 if name:
690 # ick, recursion
689 # ick, recursion
691 return text_repr(name)
690 return text_repr(name)
692 klass = getattr(value, '__class__', None)
691 klass = getattr(value, '__class__', None)
693 if klass:
692 if klass:
694 return '%s instance' % text_repr(klass)
693 return '%s instance' % text_repr(klass)
695 except KeyboardInterrupt:
694 except KeyboardInterrupt:
696 raise
695 raise
697 except:
696 except:
698 return 'UNRECOVERABLE REPR FAILURE'
697 return 'UNRECOVERABLE REPR FAILURE'
699 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
698 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
700 def nullrepr(value, repr=text_repr): return ''
699 def nullrepr(value, repr=text_repr): return ''
701
700
702 # meat of the code begins
701 # meat of the code begins
703 try:
702 try:
704 etype = etype.__name__
703 etype = etype.__name__
705 except AttributeError:
704 except AttributeError:
706 pass
705 pass
707
706
708 if self.long_header:
707 if self.long_header:
709 # Header with the exception type, python version, and date
708 # Header with the exception type, python version, and date
710 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
709 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
711 date = time.ctime(time.time())
710 date = time.ctime(time.time())
712
711
713 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
712 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
714 exc, ' '*(75-len(str(etype))-len(pyver)),
713 exc, ' '*(75-len(str(etype))-len(pyver)),
715 pyver, date.rjust(75) )
714 pyver, date.rjust(75) )
716 head += "\nA problem occured executing Python code. Here is the sequence of function"\
715 head += "\nA problem occured executing Python code. Here is the sequence of function"\
717 "\ncalls leading up to the error, with the most recent (innermost) call last."
716 "\ncalls leading up to the error, with the most recent (innermost) call last."
718 else:
717 else:
719 # Simplified header
718 # Simplified header
720 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
719 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
721 'Traceback (most recent call last)'.\
720 'Traceback (most recent call last)'.\
722 rjust(75 - len(str(etype)) ) )
721 rjust(75 - len(str(etype)) ) )
723 frames = []
722 frames = []
724 # Flush cache before calling inspect. This helps alleviate some of the
723 # Flush cache before calling inspect. This helps alleviate some of the
725 # problems with python 2.3's inspect.py.
724 # problems with python 2.3's inspect.py.
726 linecache.checkcache()
725 linecache.checkcache()
727 # Drop topmost frames if requested
726 # Drop topmost frames if requested
728 try:
727 try:
729 # Try the default getinnerframes and Alex's: Alex's fixes some
728 # Try the default getinnerframes and Alex's: Alex's fixes some
730 # problems, but it generates empty tracebacks for console errors
729 # problems, but it generates empty tracebacks for console errors
731 # (5 blanks lines) where none should be returned.
730 # (5 blanks lines) where none should be returned.
732 #records = inspect.getinnerframes(etb, context)[tb_offset:]
731 #records = inspect.getinnerframes(etb, context)[tb_offset:]
733 #print 'python records:', records # dbg
732 #print 'python records:', records # dbg
734 records = _fixed_getinnerframes(etb, context, tb_offset)
733 records = _fixed_getinnerframes(etb, context, tb_offset)
735 #print 'alex records:', records # dbg
734 #print 'alex records:', records # dbg
736 except:
735 except:
737
736
738 # FIXME: I've been getting many crash reports from python 2.3
737 # FIXME: I've been getting many crash reports from python 2.3
739 # users, traceable to inspect.py. If I can find a small test-case
738 # users, traceable to inspect.py. If I can find a small test-case
740 # to reproduce this, I should either write a better workaround or
739 # to reproduce this, I should either write a better workaround or
741 # file a bug report against inspect (if that's the real problem).
740 # file a bug report against inspect (if that's the real problem).
742 # So far, I haven't been able to find an isolated example to
741 # So far, I haven't been able to find an isolated example to
743 # reproduce the problem.
742 # reproduce the problem.
744 inspect_error()
743 inspect_error()
745 traceback.print_exc(file=self.ostream)
744 traceback.print_exc(file=self.ostream)
746 info('\nUnfortunately, your original traceback can not be constructed.\n')
745 info('\nUnfortunately, your original traceback can not be constructed.\n')
747 return ''
746 return ''
748
747
749 # build some color string templates outside these nested loops
748 # build some color string templates outside these nested loops
750 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
749 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
751 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
750 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
752 ColorsNormal)
751 ColorsNormal)
753 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
752 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
754 (Colors.vName, Colors.valEm, ColorsNormal)
753 (Colors.vName, Colors.valEm, ColorsNormal)
755 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
754 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
756 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
755 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
757 Colors.vName, ColorsNormal)
756 Colors.vName, ColorsNormal)
758 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
757 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
759 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
758 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
760 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
759 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
761 ColorsNormal)
760 ColorsNormal)
762
761
763 # now, loop over all records printing context and info
762 # now, loop over all records printing context and info
764 abspath = os.path.abspath
763 abspath = os.path.abspath
765 for frame, file, lnum, func, lines, index in records:
764 for frame, file, lnum, func, lines, index in records:
766 #print '*** record:',file,lnum,func,lines,index # dbg
765 #print '*** record:',file,lnum,func,lines,index # dbg
767 try:
766 try:
768 file = file and abspath(file) or '?'
767 file = file and abspath(file) or '?'
769 except OSError:
768 except OSError:
770 # if file is '<console>' or something not in the filesystem,
769 # if file is '<console>' or something not in the filesystem,
771 # the abspath call will throw an OSError. Just ignore it and
770 # the abspath call will throw an OSError. Just ignore it and
772 # keep the original file string.
771 # keep the original file string.
773 pass
772 pass
774 link = tpl_link % file
773 link = tpl_link % file
775 try:
774 try:
776 args, varargs, varkw, locals = inspect.getargvalues(frame)
775 args, varargs, varkw, locals = inspect.getargvalues(frame)
777 except:
776 except:
778 # This can happen due to a bug in python2.3. We should be
777 # This can happen due to a bug in python2.3. We should be
779 # able to remove this try/except when 2.4 becomes a
778 # able to remove this try/except when 2.4 becomes a
780 # requirement. Bug details at http://python.org/sf/1005466
779 # requirement. Bug details at http://python.org/sf/1005466
781 inspect_error()
780 inspect_error()
782 traceback.print_exc(file=self.ostream)
781 traceback.print_exc(file=self.ostream)
783 info("\nIPython's exception reporting continues...\n")
782 info("\nIPython's exception reporting continues...\n")
784
783
785 if func == '?':
784 if func == '?':
786 call = ''
785 call = ''
787 else:
786 else:
788 # Decide whether to include variable details or not
787 # Decide whether to include variable details or not
789 var_repr = self.include_vars and eqrepr or nullrepr
788 var_repr = self.include_vars and eqrepr or nullrepr
790 try:
789 try:
791 call = tpl_call % (func,inspect.formatargvalues(args,
790 call = tpl_call % (func,inspect.formatargvalues(args,
792 varargs, varkw,
791 varargs, varkw,
793 locals,formatvalue=var_repr))
792 locals,formatvalue=var_repr))
794 except KeyError:
793 except KeyError:
795 # This happens in situations like errors inside generator
794 # This happens in situations like errors inside generator
796 # expressions, where local variables are listed in the
795 # expressions, where local variables are listed in the
797 # line, but can't be extracted from the frame. I'm not
796 # line, but can't be extracted from the frame. I'm not
798 # 100% sure this isn't actually a bug in inspect itself,
797 # 100% sure this isn't actually a bug in inspect itself,
799 # but since there's no info for us to compute with, the
798 # but since there's no info for us to compute with, the
800 # best we can do is report the failure and move on. Here
799 # best we can do is report the failure and move on. Here
801 # we must *not* call any traceback construction again,
800 # we must *not* call any traceback construction again,
802 # because that would mess up use of %debug later on. So we
801 # because that would mess up use of %debug later on. So we
803 # simply report the failure and move on. The only
802 # simply report the failure and move on. The only
804 # limitation will be that this frame won't have locals
803 # limitation will be that this frame won't have locals
805 # listed in the call signature. Quite subtle problem...
804 # listed in the call signature. Quite subtle problem...
806 # I can't think of a good way to validate this in a unit
805 # I can't think of a good way to validate this in a unit
807 # test, but running a script consisting of:
806 # test, but running a script consisting of:
808 # dict( (k,v.strip()) for (k,v) in range(10) )
807 # dict( (k,v.strip()) for (k,v) in range(10) )
809 # will illustrate the error, if this exception catch is
808 # will illustrate the error, if this exception catch is
810 # disabled.
809 # disabled.
811 call = tpl_call_fail % func
810 call = tpl_call_fail % func
812
811
813 # Initialize a list of names on the current line, which the
812 # Initialize a list of names on the current line, which the
814 # tokenizer below will populate.
813 # tokenizer below will populate.
815 names = []
814 names = []
816
815
817 def tokeneater(token_type, token, start, end, line):
816 def tokeneater(token_type, token, start, end, line):
818 """Stateful tokeneater which builds dotted names.
817 """Stateful tokeneater which builds dotted names.
819
818
820 The list of names it appends to (from the enclosing scope) can
819 The list of names it appends to (from the enclosing scope) can
821 contain repeated composite names. This is unavoidable, since
820 contain repeated composite names. This is unavoidable, since
822 there is no way to disambguate partial dotted structures until
821 there is no way to disambguate partial dotted structures until
823 the full list is known. The caller is responsible for pruning
822 the full list is known. The caller is responsible for pruning
824 the final list of duplicates before using it."""
823 the final list of duplicates before using it."""
825
824
826 # build composite names
825 # build composite names
827 if token == '.':
826 if token == '.':
828 try:
827 try:
829 names[-1] += '.'
828 names[-1] += '.'
830 # store state so the next token is added for x.y.z names
829 # store state so the next token is added for x.y.z names
831 tokeneater.name_cont = True
830 tokeneater.name_cont = True
832 return
831 return
833 except IndexError:
832 except IndexError:
834 pass
833 pass
835 if token_type == tokenize.NAME and token not in keyword.kwlist:
834 if token_type == tokenize.NAME and token not in keyword.kwlist:
836 if tokeneater.name_cont:
835 if tokeneater.name_cont:
837 # Dotted names
836 # Dotted names
838 names[-1] += token
837 names[-1] += token
839 tokeneater.name_cont = False
838 tokeneater.name_cont = False
840 else:
839 else:
841 # Regular new names. We append everything, the caller
840 # Regular new names. We append everything, the caller
842 # will be responsible for pruning the list later. It's
841 # will be responsible for pruning the list later. It's
843 # very tricky to try to prune as we go, b/c composite
842 # very tricky to try to prune as we go, b/c composite
844 # names can fool us. The pruning at the end is easy
843 # names can fool us. The pruning at the end is easy
845 # to do (or the caller can print a list with repeated
844 # to do (or the caller can print a list with repeated
846 # names if so desired.
845 # names if so desired.
847 names.append(token)
846 names.append(token)
848 elif token_type == tokenize.NEWLINE:
847 elif token_type == tokenize.NEWLINE:
849 raise IndexError
848 raise IndexError
850 # we need to store a bit of state in the tokenizer to build
849 # we need to store a bit of state in the tokenizer to build
851 # dotted names
850 # dotted names
852 tokeneater.name_cont = False
851 tokeneater.name_cont = False
853
852
854 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
853 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
855 line = getline(file, lnum[0])
854 line = getline(file, lnum[0])
856 lnum[0] += 1
855 lnum[0] += 1
857 return line
856 return line
858
857
859 # Build the list of names on this line of code where the exception
858 # Build the list of names on this line of code where the exception
860 # occurred.
859 # occurred.
861 try:
860 try:
862 # This builds the names list in-place by capturing it from the
861 # This builds the names list in-place by capturing it from the
863 # enclosing scope.
862 # enclosing scope.
864 tokenize.tokenize(linereader, tokeneater)
863 tokenize.tokenize(linereader, tokeneater)
865 except IndexError:
864 except IndexError:
866 # signals exit of tokenizer
865 # signals exit of tokenizer
867 pass
866 pass
868 except tokenize.TokenError,msg:
867 except tokenize.TokenError,msg:
869 _m = ("An unexpected error occurred while tokenizing input\n"
868 _m = ("An unexpected error occurred while tokenizing input\n"
870 "The following traceback may be corrupted or invalid\n"
869 "The following traceback may be corrupted or invalid\n"
871 "The error message is: %s\n" % msg)
870 "The error message is: %s\n" % msg)
872 error(_m)
871 error(_m)
873
872
874 # prune names list of duplicates, but keep the right order
873 # prune names list of duplicates, but keep the right order
875 unique_names = uniq_stable(names)
874 unique_names = uniq_stable(names)
876
875
877 # Start loop over vars
876 # Start loop over vars
878 lvals = []
877 lvals = []
879 if self.include_vars:
878 if self.include_vars:
880 for name_full in unique_names:
879 for name_full in unique_names:
881 name_base = name_full.split('.',1)[0]
880 name_base = name_full.split('.',1)[0]
882 if name_base in frame.f_code.co_varnames:
881 if name_base in frame.f_code.co_varnames:
883 if locals.has_key(name_base):
882 if locals.has_key(name_base):
884 try:
883 try:
885 value = repr(eval(name_full,locals))
884 value = repr(eval(name_full,locals))
886 except:
885 except:
887 value = undefined
886 value = undefined
888 else:
887 else:
889 value = undefined
888 value = undefined
890 name = tpl_local_var % name_full
889 name = tpl_local_var % name_full
891 else:
890 else:
892 if frame.f_globals.has_key(name_base):
891 if frame.f_globals.has_key(name_base):
893 try:
892 try:
894 value = repr(eval(name_full,frame.f_globals))
893 value = repr(eval(name_full,frame.f_globals))
895 except:
894 except:
896 value = undefined
895 value = undefined
897 else:
896 else:
898 value = undefined
897 value = undefined
899 name = tpl_global_var % name_full
898 name = tpl_global_var % name_full
900 lvals.append(tpl_name_val % (name,value))
899 lvals.append(tpl_name_val % (name,value))
901 if lvals:
900 if lvals:
902 lvals = '%s%s' % (indent,em_normal.join(lvals))
901 lvals = '%s%s' % (indent,em_normal.join(lvals))
903 else:
902 else:
904 lvals = ''
903 lvals = ''
905
904
906 level = '%s %s\n' % (link,call)
905 level = '%s %s\n' % (link,call)
907
906
908 if index is None:
907 if index is None:
909 frames.append(level)
908 frames.append(level)
910 else:
909 else:
911 frames.append('%s%s' % (level,''.join(
910 frames.append('%s%s' % (level,''.join(
912 _format_traceback_lines(lnum,index,lines,Colors,lvals,
911 _format_traceback_lines(lnum,index,lines,Colors,lvals,
913 col_scheme))))
912 col_scheme))))
914
913
915 # Get (safely) a string form of the exception info
914 # Get (safely) a string form of the exception info
916 try:
915 try:
917 etype_str,evalue_str = map(str,(etype,evalue))
916 etype_str,evalue_str = map(str,(etype,evalue))
918 except:
917 except:
919 # User exception is improperly defined.
918 # User exception is improperly defined.
920 etype,evalue = str,sys.exc_info()[:2]
919 etype,evalue = str,sys.exc_info()[:2]
921 etype_str,evalue_str = map(str,(etype,evalue))
920 etype_str,evalue_str = map(str,(etype,evalue))
922 # ... and format it
921 # ... and format it
923 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
922 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
924 ColorsNormal, evalue_str)]
923 ColorsNormal, evalue_str)]
925 if type(evalue) is types.InstanceType:
924 if type(evalue) is types.InstanceType:
926 try:
925 try:
927 names = [w for w in dir(evalue) if isinstance(w, basestring)]
926 names = [w for w in dir(evalue) if isinstance(w, basestring)]
928 except:
927 except:
929 # Every now and then, an object with funny inernals blows up
928 # Every now and then, an object with funny inernals blows up
930 # when dir() is called on it. We do the best we can to report
929 # when dir() is called on it. We do the best we can to report
931 # the problem and continue
930 # the problem and continue
932 _m = '%sException reporting error (object with broken dir())%s:'
931 _m = '%sException reporting error (object with broken dir())%s:'
933 exception.append(_m % (Colors.excName,ColorsNormal))
932 exception.append(_m % (Colors.excName,ColorsNormal))
934 etype_str,evalue_str = map(str,sys.exc_info()[:2])
933 etype_str,evalue_str = map(str,sys.exc_info()[:2])
935 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
934 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
936 ColorsNormal, evalue_str))
935 ColorsNormal, evalue_str))
937 names = []
936 names = []
938 for name in names:
937 for name in names:
939 value = text_repr(getattr(evalue, name))
938 value = text_repr(getattr(evalue, name))
940 exception.append('\n%s%s = %s' % (indent, name, value))
939 exception.append('\n%s%s = %s' % (indent, name, value))
941
940
942 # vds: >>
941 # vds: >>
943 if records:
942 if records:
944 filepath, lnum = records[-1][1:3]
943 filepath, lnum = records[-1][1:3]
945 #print "file:", str(file), "linenb", str(lnum) # dbg
944 #print "file:", str(file), "linenb", str(lnum) # dbg
946 filepath = os.path.abspath(filepath)
945 filepath = os.path.abspath(filepath)
947 ipinst = ipapi.get()
946 ipinst = ipapi.get()
948 if ipinst is not None:
947 if ipinst is not None:
949 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
948 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
950 # vds: <<
949 # vds: <<
951
950
952 # return all our info assembled as a single string
951 # return all our info assembled as a single string
953 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
952 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
954 return [head] + frames + [''.join(exception[0])]
953 return [head] + frames + [''.join(exception[0])]
955
954
956 def debugger(self,force=False):
955 def debugger(self,force=False):
957 """Call up the pdb debugger if desired, always clean up the tb
956 """Call up the pdb debugger if desired, always clean up the tb
958 reference.
957 reference.
959
958
960 Keywords:
959 Keywords:
961
960
962 - force(False): by default, this routine checks the instance call_pdb
961 - force(False): by default, this routine checks the instance call_pdb
963 flag and does not actually invoke the debugger if the flag is false.
962 flag and does not actually invoke the debugger if the flag is false.
964 The 'force' option forces the debugger to activate even if the flag
963 The 'force' option forces the debugger to activate even if the flag
965 is false.
964 is false.
966
965
967 If the call_pdb flag is set, the pdb interactive debugger is
966 If the call_pdb flag is set, the pdb interactive debugger is
968 invoked. In all cases, the self.tb reference to the current traceback
967 invoked. In all cases, the self.tb reference to the current traceback
969 is deleted to prevent lingering references which hamper memory
968 is deleted to prevent lingering references which hamper memory
970 management.
969 management.
971
970
972 Note that each call to pdb() does an 'import readline', so if your app
971 Note that each call to pdb() does an 'import readline', so if your app
973 requires a special setup for the readline completers, you'll have to
972 requires a special setup for the readline completers, you'll have to
974 fix that by hand after invoking the exception handler."""
973 fix that by hand after invoking the exception handler."""
975
974
976 if force or self.call_pdb:
975 if force or self.call_pdb:
977 if self.pdb is None:
976 if self.pdb is None:
978 self.pdb = debugger.Pdb(
977 self.pdb = debugger.Pdb(
979 self.color_scheme_table.active_scheme_name)
978 self.color_scheme_table.active_scheme_name)
980 # the system displayhook may have changed, restore the original
979 # the system displayhook may have changed, restore the original
981 # for pdb
980 # for pdb
982 display_trap = DisplayTrap(hook=sys.__displayhook__)
981 display_trap = DisplayTrap(hook=sys.__displayhook__)
983 with display_trap:
982 with display_trap:
984 self.pdb.reset()
983 self.pdb.reset()
985 # Find the right frame so we don't pop up inside ipython itself
984 # Find the right frame so we don't pop up inside ipython itself
986 if hasattr(self,'tb') and self.tb is not None:
985 if hasattr(self,'tb') and self.tb is not None:
987 etb = self.tb
986 etb = self.tb
988 else:
987 else:
989 etb = self.tb = sys.last_traceback
988 etb = self.tb = sys.last_traceback
990 while self.tb is not None and self.tb.tb_next is not None:
989 while self.tb is not None and self.tb.tb_next is not None:
991 self.tb = self.tb.tb_next
990 self.tb = self.tb.tb_next
992 if etb and etb.tb_next:
991 if etb and etb.tb_next:
993 etb = etb.tb_next
992 etb = etb.tb_next
994 self.pdb.botframe = etb.tb_frame
993 self.pdb.botframe = etb.tb_frame
995 self.pdb.interaction(self.tb.tb_frame, self.tb)
994 self.pdb.interaction(self.tb.tb_frame, self.tb)
996
995
997 if hasattr(self,'tb'):
996 if hasattr(self,'tb'):
998 del self.tb
997 del self.tb
999
998
1000 def handler(self, info=None):
999 def handler(self, info=None):
1001 (etype, evalue, etb) = info or sys.exc_info()
1000 (etype, evalue, etb) = info or sys.exc_info()
1002 self.tb = etb
1001 self.tb = etb
1003 ostream = self.ostream
1002 ostream = self.ostream
1004 ostream.flush()
1003 ostream.flush()
1005 ostream.write(self.text(etype, evalue, etb))
1004 ostream.write(self.text(etype, evalue, etb))
1006 ostream.write('\n')
1005 ostream.write('\n')
1007 ostream.flush()
1006 ostream.flush()
1008
1007
1009 # Changed so an instance can just be called as VerboseTB_inst() and print
1008 # Changed so an instance can just be called as VerboseTB_inst() and print
1010 # out the right info on its own.
1009 # out the right info on its own.
1011 def __call__(self, etype=None, evalue=None, etb=None):
1010 def __call__(self, etype=None, evalue=None, etb=None):
1012 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1011 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1013 if etb is None:
1012 if etb is None:
1014 self.handler()
1013 self.handler()
1015 else:
1014 else:
1016 self.handler((etype, evalue, etb))
1015 self.handler((etype, evalue, etb))
1017 try:
1016 try:
1018 self.debugger()
1017 self.debugger()
1019 except KeyboardInterrupt:
1018 except KeyboardInterrupt:
1020 print "\nKeyboardInterrupt"
1019 print "\nKeyboardInterrupt"
1021
1020
1022 #----------------------------------------------------------------------------
1021 #----------------------------------------------------------------------------
1023 class FormattedTB(VerboseTB, ListTB):
1022 class FormattedTB(VerboseTB, ListTB):
1024 """Subclass ListTB but allow calling with a traceback.
1023 """Subclass ListTB but allow calling with a traceback.
1025
1024
1026 It can thus be used as a sys.excepthook for Python > 2.1.
1025 It can thus be used as a sys.excepthook for Python > 2.1.
1027
1026
1028 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1027 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1029
1028
1030 Allows a tb_offset to be specified. This is useful for situations where
1029 Allows a tb_offset to be specified. This is useful for situations where
1031 one needs to remove a number of topmost frames from the traceback (such as
1030 one needs to remove a number of topmost frames from the traceback (such as
1032 occurs with python programs that themselves execute other python code,
1031 occurs with python programs that themselves execute other python code,
1033 like Python shells). """
1032 like Python shells). """
1034
1033
1035 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1034 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1036 ostream=None,
1035 ostream=None,
1037 tb_offset=0, long_header=False, include_vars=False):
1036 tb_offset=0, long_header=False, include_vars=False):
1038
1037
1039 # NEVER change the order of this list. Put new modes at the end:
1038 # NEVER change the order of this list. Put new modes at the end:
1040 self.valid_modes = ['Plain','Context','Verbose']
1039 self.valid_modes = ['Plain','Context','Verbose']
1041 self.verbose_modes = self.valid_modes[1:3]
1040 self.verbose_modes = self.valid_modes[1:3]
1042
1041
1043 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1042 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1044 ostream=ostream, tb_offset=tb_offset,
1043 ostream=ostream, tb_offset=tb_offset,
1045 long_header=long_header, include_vars=include_vars)
1044 long_header=long_header, include_vars=include_vars)
1046
1045
1047 # Different types of tracebacks are joined with different separators to
1046 # Different types of tracebacks are joined with different separators to
1048 # form a single string. They are taken from this dict
1047 # form a single string. They are taken from this dict
1049 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1048 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1050 # set_mode also sets the tb_join_char attribute
1049 # set_mode also sets the tb_join_char attribute
1051 self.set_mode(mode)
1050 self.set_mode(mode)
1052
1051
1053 def _extract_tb(self,tb):
1052 def _extract_tb(self,tb):
1054 if tb:
1053 if tb:
1055 return traceback.extract_tb(tb)
1054 return traceback.extract_tb(tb)
1056 else:
1055 else:
1057 return None
1056 return None
1058
1057
1059 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1058 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1060 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1059 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1061 mode = self.mode
1060 mode = self.mode
1062 if mode in self.verbose_modes:
1061 if mode in self.verbose_modes:
1063 # Verbose modes need a full traceback
1062 # Verbose modes need a full traceback
1064 return VerboseTB.structured_traceback(
1063 return VerboseTB.structured_traceback(
1065 self, etype, value, tb, tb_offset, context
1064 self, etype, value, tb, tb_offset, context
1066 )
1065 )
1067 else:
1066 else:
1068 # We must check the source cache because otherwise we can print
1067 # We must check the source cache because otherwise we can print
1069 # out-of-date source code.
1068 # out-of-date source code.
1070 linecache.checkcache()
1069 linecache.checkcache()
1071 # Now we can extract and format the exception
1070 # Now we can extract and format the exception
1072 elist = self._extract_tb(tb)
1071 elist = self._extract_tb(tb)
1073 return ListTB.structured_traceback(
1072 return ListTB.structured_traceback(
1074 self, etype, value, elist, tb_offset, context
1073 self, etype, value, elist, tb_offset, context
1075 )
1074 )
1076
1075
1077 def stb2text(self, stb):
1076 def stb2text(self, stb):
1078 """Convert a structured traceback (a list) to a string."""
1077 """Convert a structured traceback (a list) to a string."""
1079 return self.tb_join_char.join(stb)
1078 return self.tb_join_char.join(stb)
1080
1079
1081
1080
1082 def set_mode(self,mode=None):
1081 def set_mode(self,mode=None):
1083 """Switch to the desired mode.
1082 """Switch to the desired mode.
1084
1083
1085 If mode is not specified, cycles through the available modes."""
1084 If mode is not specified, cycles through the available modes."""
1086
1085
1087 if not mode:
1086 if not mode:
1088 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1087 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1089 len(self.valid_modes)
1088 len(self.valid_modes)
1090 self.mode = self.valid_modes[new_idx]
1089 self.mode = self.valid_modes[new_idx]
1091 elif mode not in self.valid_modes:
1090 elif mode not in self.valid_modes:
1092 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
1091 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
1093 'Valid modes: '+str(self.valid_modes)
1092 'Valid modes: '+str(self.valid_modes)
1094 else:
1093 else:
1095 self.mode = mode
1094 self.mode = mode
1096 # include variable details only in 'Verbose' mode
1095 # include variable details only in 'Verbose' mode
1097 self.include_vars = (self.mode == self.valid_modes[2])
1096 self.include_vars = (self.mode == self.valid_modes[2])
1098 # Set the join character for generating text tracebacks
1097 # Set the join character for generating text tracebacks
1099 self.tb_join_char = self._join_chars[self.mode]
1098 self.tb_join_char = self._join_chars[self.mode]
1100
1099
1101 # some convenient shorcuts
1100 # some convenient shorcuts
1102 def plain(self):
1101 def plain(self):
1103 self.set_mode(self.valid_modes[0])
1102 self.set_mode(self.valid_modes[0])
1104
1103
1105 def context(self):
1104 def context(self):
1106 self.set_mode(self.valid_modes[1])
1105 self.set_mode(self.valid_modes[1])
1107
1106
1108 def verbose(self):
1107 def verbose(self):
1109 self.set_mode(self.valid_modes[2])
1108 self.set_mode(self.valid_modes[2])
1110
1109
1111 #----------------------------------------------------------------------------
1110 #----------------------------------------------------------------------------
1112 class AutoFormattedTB(FormattedTB):
1111 class AutoFormattedTB(FormattedTB):
1113 """A traceback printer which can be called on the fly.
1112 """A traceback printer which can be called on the fly.
1114
1113
1115 It will find out about exceptions by itself.
1114 It will find out about exceptions by itself.
1116
1115
1117 A brief example:
1116 A brief example:
1118
1117
1119 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1118 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1120 try:
1119 try:
1121 ...
1120 ...
1122 except:
1121 except:
1123 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1122 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1124 """
1123 """
1125
1124
1126 def __call__(self,etype=None,evalue=None,etb=None,
1125 def __call__(self,etype=None,evalue=None,etb=None,
1127 out=None,tb_offset=None):
1126 out=None,tb_offset=None):
1128 """Print out a formatted exception traceback.
1127 """Print out a formatted exception traceback.
1129
1128
1130 Optional arguments:
1129 Optional arguments:
1131 - out: an open file-like object to direct output to.
1130 - out: an open file-like object to direct output to.
1132
1131
1133 - tb_offset: the number of frames to skip over in the stack, on a
1132 - tb_offset: the number of frames to skip over in the stack, on a
1134 per-call basis (this overrides temporarily the instance's tb_offset
1133 per-call basis (this overrides temporarily the instance's tb_offset
1135 given at initialization time. """
1134 given at initialization time. """
1136
1135
1137
1136
1138 if out is None:
1137 if out is None:
1139 out = self.ostream
1138 out = self.ostream
1140 out.flush()
1139 out.flush()
1141 out.write(self.text(etype, evalue, etb, tb_offset))
1140 out.write(self.text(etype, evalue, etb, tb_offset))
1142 out.write('\n')
1141 out.write('\n')
1143 out.flush()
1142 out.flush()
1144 # FIXME: we should remove the auto pdb behavior from here and leave
1143 # FIXME: we should remove the auto pdb behavior from here and leave
1145 # that to the clients.
1144 # that to the clients.
1146 try:
1145 try:
1147 self.debugger()
1146 self.debugger()
1148 except KeyboardInterrupt:
1147 except KeyboardInterrupt:
1149 print "\nKeyboardInterrupt"
1148 print "\nKeyboardInterrupt"
1150
1149
1151 def structured_traceback(self, etype=None, value=None, tb=None,
1150 def structured_traceback(self, etype=None, value=None, tb=None,
1152 tb_offset=None, context=5):
1151 tb_offset=None, context=5):
1153 if etype is None:
1152 if etype is None:
1154 etype,value,tb = sys.exc_info()
1153 etype,value,tb = sys.exc_info()
1155 self.tb = tb
1154 self.tb = tb
1156 return FormattedTB.structured_traceback(
1155 return FormattedTB.structured_traceback(
1157 self, etype, value, tb, tb_offset, context)
1156 self, etype, value, tb, tb_offset, context)
1158
1157
1159 #---------------------------------------------------------------------------
1158 #---------------------------------------------------------------------------
1160
1159
1161 # A simple class to preserve Nathan's original functionality.
1160 # A simple class to preserve Nathan's original functionality.
1162 class ColorTB(FormattedTB):
1161 class ColorTB(FormattedTB):
1163 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1162 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1164 def __init__(self,color_scheme='Linux',call_pdb=0):
1163 def __init__(self,color_scheme='Linux',call_pdb=0):
1165 FormattedTB.__init__(self,color_scheme=color_scheme,
1164 FormattedTB.__init__(self,color_scheme=color_scheme,
1166 call_pdb=call_pdb)
1165 call_pdb=call_pdb)
1167
1166
1168
1167
1169 class SyntaxTB(ListTB):
1168 class SyntaxTB(ListTB):
1170 """Extension which holds some state: the last exception value"""
1169 """Extension which holds some state: the last exception value"""
1171
1170
1172 def __init__(self,color_scheme = 'NoColor'):
1171 def __init__(self,color_scheme = 'NoColor'):
1173 ListTB.__init__(self,color_scheme)
1172 ListTB.__init__(self,color_scheme)
1174 self.last_syntax_error = None
1173 self.last_syntax_error = None
1175
1174
1176 def __call__(self, etype, value, elist):
1175 def __call__(self, etype, value, elist):
1177 self.last_syntax_error = value
1176 self.last_syntax_error = value
1178 ListTB.__call__(self,etype,value,elist)
1177 ListTB.__call__(self,etype,value,elist)
1179
1178
1180 def clear_err_state(self):
1179 def clear_err_state(self):
1181 """Return the current error state and clear it"""
1180 """Return the current error state and clear it"""
1182 e = self.last_syntax_error
1181 e = self.last_syntax_error
1183 self.last_syntax_error = None
1182 self.last_syntax_error = None
1184 return e
1183 return e
1185
1184
1186 def stb2text(self, stb):
1185 def stb2text(self, stb):
1187 """Convert a structured traceback (a list) to a string."""
1186 """Convert a structured traceback (a list) to a string."""
1188 return ''.join(stb)
1187 return ''.join(stb)
1189
1188
1190
1189
1191 #----------------------------------------------------------------------------
1190 #----------------------------------------------------------------------------
1192 # module testing (minimal)
1191 # module testing (minimal)
1193 if __name__ == "__main__":
1192 if __name__ == "__main__":
1194 def spam(c, (d, e)):
1193 def spam(c, (d, e)):
1195 x = c + d
1194 x = c + d
1196 y = c * d
1195 y = c * d
1197 foo(x, y)
1196 foo(x, y)
1198
1197
1199 def foo(a, b, bar=1):
1198 def foo(a, b, bar=1):
1200 eggs(a, b + bar)
1199 eggs(a, b + bar)
1201
1200
1202 def eggs(f, g, z=globals()):
1201 def eggs(f, g, z=globals()):
1203 h = f + g
1202 h = f + g
1204 i = f - g
1203 i = f - g
1205 return h / i
1204 return h / i
1206
1205
1207 print ''
1206 print ''
1208 print '*** Before ***'
1207 print '*** Before ***'
1209 try:
1208 try:
1210 print spam(1, (2, 3))
1209 print spam(1, (2, 3))
1211 except:
1210 except:
1212 traceback.print_exc()
1211 traceback.print_exc()
1213 print ''
1212 print ''
1214
1213
1215 handler = ColorTB()
1214 handler = ColorTB()
1216 print '*** ColorTB ***'
1215 print '*** ColorTB ***'
1217 try:
1216 try:
1218 print spam(1, (2, 3))
1217 print spam(1, (2, 3))
1219 except:
1218 except:
1220 apply(handler, sys.exc_info() )
1219 apply(handler, sys.exc_info() )
1221 print ''
1220 print ''
1222
1221
1223 handler = VerboseTB()
1222 handler = VerboseTB()
1224 print '*** VerboseTB ***'
1223 print '*** VerboseTB ***'
1225 try:
1224 try:
1226 print spam(1, (2, 3))
1225 print spam(1, (2, 3))
1227 except:
1226 except:
1228 apply(handler, sys.exc_info() )
1227 apply(handler, sys.exc_info() )
1229 print ''
1228 print ''
1230
1229
General Comments 0
You need to be logged in to leave comments. Login now