##// END OF EJS Templates
Protect against absent global IPython instance....
Fernando Perez -
Show More
@@ -1,1056 +1,1061 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 # Required modules
72 # Required modules
73 import inspect
73 import inspect
74 import keyword
74 import keyword
75 import linecache
75 import linecache
76 import os
76 import os
77 import pydoc
77 import pydoc
78 import re
78 import re
79 import string
79 import string
80 import sys
80 import sys
81 import time
81 import time
82 import tokenize
82 import tokenize
83 import traceback
83 import traceback
84 import types
84 import types
85
85
86 # For purposes of monkeypatching inspect to fix a bug in it.
86 # For purposes of monkeypatching inspect to fix a bug in it.
87 from inspect import getsourcefile, getfile, getmodule,\
87 from inspect import getsourcefile, getfile, getmodule,\
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89
89
90
90
91 # IPython's own modules
91 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
92 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython import Debugger, PyColorize, ipapi
93 from IPython import Debugger, PyColorize, ipapi
94 from IPython.ipstruct import Struct
94 from IPython.ipstruct import Struct
95 from IPython.excolors import exception_colors
95 from IPython.excolors import exception_colors
96 from IPython.genutils import Term,uniq_stable,error,info
96 from IPython.genutils import Term,uniq_stable,error,info
97
97
98 # Globals
98 # Globals
99 # amount of space to put line numbers before verbose tracebacks
99 # amount of space to put line numbers before verbose tracebacks
100 INDENT_SIZE = 8
100 INDENT_SIZE = 8
101
101
102 # Default color scheme. This is used, for example, by the traceback
102 # Default color scheme. This is used, for example, by the traceback
103 # formatter. When running in an actual IPython instance, the user's rc.colors
103 # formatter. When running in an actual IPython instance, the user's rc.colors
104 # value is used, but havinga module global makes this functionality available
104 # value is used, but havinga module global makes this functionality available
105 # to users of ultraTB who are NOT running inside ipython.
105 # to users of ultraTB who are NOT running inside ipython.
106 DEFAULT_SCHEME = 'NoColor'
106 DEFAULT_SCHEME = 'NoColor'
107
107
108 #---------------------------------------------------------------------------
108 #---------------------------------------------------------------------------
109 # Code begins
109 # Code begins
110
110
111 # Utility functions
111 # Utility functions
112 def inspect_error():
112 def inspect_error():
113 """Print a message about internal inspect errors.
113 """Print a message about internal inspect errors.
114
114
115 These are unfortunately quite common."""
115 These are unfortunately quite common."""
116
116
117 error('Internal Python error in the inspect module.\n'
117 error('Internal Python error in the inspect module.\n'
118 'Below is the traceback from this internal error.\n')
118 'Below is the traceback from this internal error.\n')
119
119
120
120
121 def findsource(object):
121 def findsource(object):
122 """Return the entire source file and starting line number for an object.
122 """Return the entire source file and starting line number for an object.
123
123
124 The argument may be a module, class, method, function, traceback, frame,
124 The argument may be a module, class, method, function, traceback, frame,
125 or code object. The source code is returned as a list of all the lines
125 or code object. The source code is returned as a list of all the lines
126 in the file and the line number indexes a line in that list. An IOError
126 in the file and the line number indexes a line in that list. An IOError
127 is raised if the source code cannot be retrieved.
127 is raised if the source code cannot be retrieved.
128
128
129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
130
130
131 file = getsourcefile(object) or getfile(object)
131 file = getsourcefile(object) or getfile(object)
132 # If the object is a frame, then trying to get the globals dict from its
132 # If the object is a frame, then trying to get the globals dict from its
133 # module won't work. Instead, the frame object itself has the globals
133 # module won't work. Instead, the frame object itself has the globals
134 # dictionary.
134 # dictionary.
135 globals_dict = None
135 globals_dict = None
136 if inspect.isframe(object):
136 if inspect.isframe(object):
137 # XXX: can this ever be false?
137 # XXX: can this ever be false?
138 globals_dict = object.f_globals
138 globals_dict = object.f_globals
139 else:
139 else:
140 module = getmodule(object, file)
140 module = getmodule(object, file)
141 if module:
141 if module:
142 globals_dict = module.__dict__
142 globals_dict = module.__dict__
143 lines = linecache.getlines(file, globals_dict)
143 lines = linecache.getlines(file, globals_dict)
144 if not lines:
144 if not lines:
145 raise IOError('could not get source code')
145 raise IOError('could not get source code')
146
146
147 if ismodule(object):
147 if ismodule(object):
148 return lines, 0
148 return lines, 0
149
149
150 if isclass(object):
150 if isclass(object):
151 name = object.__name__
151 name = object.__name__
152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
153 # make some effort to find the best matching class definition:
153 # make some effort to find the best matching class definition:
154 # use the one with the least indentation, which is the one
154 # use the one with the least indentation, which is the one
155 # that's most probably not inside a function definition.
155 # that's most probably not inside a function definition.
156 candidates = []
156 candidates = []
157 for i in range(len(lines)):
157 for i in range(len(lines)):
158 match = pat.match(lines[i])
158 match = pat.match(lines[i])
159 if match:
159 if match:
160 # if it's at toplevel, it's already the best one
160 # if it's at toplevel, it's already the best one
161 if lines[i][0] == 'c':
161 if lines[i][0] == 'c':
162 return lines, i
162 return lines, i
163 # else add whitespace to candidate list
163 # else add whitespace to candidate list
164 candidates.append((match.group(1), i))
164 candidates.append((match.group(1), i))
165 if candidates:
165 if candidates:
166 # this will sort by whitespace, and by line number,
166 # this will sort by whitespace, and by line number,
167 # less whitespace first
167 # less whitespace first
168 candidates.sort()
168 candidates.sort()
169 return lines, candidates[0][1]
169 return lines, candidates[0][1]
170 else:
170 else:
171 raise IOError('could not find class definition')
171 raise IOError('could not find class definition')
172
172
173 if ismethod(object):
173 if ismethod(object):
174 object = object.im_func
174 object = object.im_func
175 if isfunction(object):
175 if isfunction(object):
176 object = object.func_code
176 object = object.func_code
177 if istraceback(object):
177 if istraceback(object):
178 object = object.tb_frame
178 object = object.tb_frame
179 if isframe(object):
179 if isframe(object):
180 object = object.f_code
180 object = object.f_code
181 if iscode(object):
181 if iscode(object):
182 if not hasattr(object, 'co_firstlineno'):
182 if not hasattr(object, 'co_firstlineno'):
183 raise IOError('could not find function definition')
183 raise IOError('could not find function definition')
184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
185 pmatch = pat.match
185 pmatch = pat.match
186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
187 # the length of lines, which causes an error. Safeguard against that.
187 # the length of lines, which causes an error. Safeguard against that.
188 lnum = min(object.co_firstlineno,len(lines))-1
188 lnum = min(object.co_firstlineno,len(lines))-1
189 while lnum > 0:
189 while lnum > 0:
190 if pmatch(lines[lnum]): break
190 if pmatch(lines[lnum]): break
191 lnum -= 1
191 lnum -= 1
192
192
193 return lines, lnum
193 return lines, lnum
194 raise IOError('could not find code object')
194 raise IOError('could not find code object')
195
195
196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
197 if sys.version_info[:2] >= (2,5):
197 if sys.version_info[:2] >= (2,5):
198 inspect.findsource = findsource
198 inspect.findsource = findsource
199
199
200 def fix_frame_records_filenames(records):
200 def fix_frame_records_filenames(records):
201 """Try to fix the filenames in each record from inspect.getinnerframes().
201 """Try to fix the filenames in each record from inspect.getinnerframes().
202
202
203 Particularly, modules loaded from within zip files have useless filenames
203 Particularly, modules loaded from within zip files have useless filenames
204 attached to their code object, and inspect.getinnerframes() just uses it.
204 attached to their code object, and inspect.getinnerframes() just uses it.
205 """
205 """
206 fixed_records = []
206 fixed_records = []
207 for frame, filename, line_no, func_name, lines, index in records:
207 for frame, filename, line_no, func_name, lines, index in records:
208 # Look inside the frame's globals dictionary for __file__, which should
208 # Look inside the frame's globals dictionary for __file__, which should
209 # be better.
209 # be better.
210 better_fn = frame.f_globals.get('__file__', None)
210 better_fn = frame.f_globals.get('__file__', None)
211 if isinstance(better_fn, str):
211 if isinstance(better_fn, str):
212 # Check the type just in case someone did something weird with
212 # Check the type just in case someone did something weird with
213 # __file__. It might also be None if the error occurred during
213 # __file__. It might also be None if the error occurred during
214 # import.
214 # import.
215 filename = better_fn
215 filename = better_fn
216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
217 return fixed_records
217 return fixed_records
218
218
219
219
220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
221 import linecache
221 import linecache
222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
223
223
224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
225
225
226 # If the error is at the console, don't build any context, since it would
226 # If the error is at the console, don't build any context, since it would
227 # otherwise produce 5 blank lines printed out (there is no file at the
227 # otherwise produce 5 blank lines printed out (there is no file at the
228 # console)
228 # console)
229 rec_check = records[tb_offset:]
229 rec_check = records[tb_offset:]
230 try:
230 try:
231 rname = rec_check[0][1]
231 rname = rec_check[0][1]
232 if rname == '<ipython console>' or rname.endswith('<string>'):
232 if rname == '<ipython console>' or rname.endswith('<string>'):
233 return rec_check
233 return rec_check
234 except IndexError:
234 except IndexError:
235 pass
235 pass
236
236
237 aux = traceback.extract_tb(etb)
237 aux = traceback.extract_tb(etb)
238 assert len(records) == len(aux)
238 assert len(records) == len(aux)
239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
240 maybeStart = lnum-1 - context//2
240 maybeStart = lnum-1 - context//2
241 start = max(maybeStart, 0)
241 start = max(maybeStart, 0)
242 end = start + context
242 end = start + context
243 lines = linecache.getlines(file)[start:end]
243 lines = linecache.getlines(file)[start:end]
244 # pad with empty lines if necessary
244 # pad with empty lines if necessary
245 if maybeStart < 0:
245 if maybeStart < 0:
246 lines = (['\n'] * -maybeStart) + lines
246 lines = (['\n'] * -maybeStart) + lines
247 if len(lines) < context:
247 if len(lines) < context:
248 lines += ['\n'] * (context - len(lines))
248 lines += ['\n'] * (context - len(lines))
249 buf = list(records[i])
249 buf = list(records[i])
250 buf[LNUM_POS] = lnum
250 buf[LNUM_POS] = lnum
251 buf[INDEX_POS] = lnum - 1 - start
251 buf[INDEX_POS] = lnum - 1 - start
252 buf[LINES_POS] = lines
252 buf[LINES_POS] = lines
253 records[i] = tuple(buf)
253 records[i] = tuple(buf)
254 return records[tb_offset:]
254 return records[tb_offset:]
255
255
256 # Helper function -- largely belongs to VerboseTB, but we need the same
256 # Helper function -- largely belongs to VerboseTB, but we need the same
257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
258 # can be recognized properly by ipython.el's py-traceback-line-re
258 # can be recognized properly by ipython.el's py-traceback-line-re
259 # (SyntaxErrors have to be treated specially because they have no traceback)
259 # (SyntaxErrors have to be treated specially because they have no traceback)
260
260
261 _parser = PyColorize.Parser()
261 _parser = PyColorize.Parser()
262
262
263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
264 numbers_width = INDENT_SIZE - 1
264 numbers_width = INDENT_SIZE - 1
265 res = []
265 res = []
266 i = lnum - index
266 i = lnum - index
267
267
268 # This lets us get fully syntax-highlighted tracebacks.
268 # This lets us get fully syntax-highlighted tracebacks.
269 if scheme is None:
269 if scheme is None:
270 try:
270 ipinst = ipapi.get()
271 scheme = ipapi.get().IP.rc.colors
271 if ipinst is not None:
272 except:
272 scheme = ipinst.IP.rc.colors
273 else:
273 scheme = DEFAULT_SCHEME
274 scheme = DEFAULT_SCHEME
274 _line_format = _parser.format2
275 _line_format = _parser.format2
275
276
276 for line in lines:
277 for line in lines:
277 new_line, err = _line_format(line,'str',scheme)
278 new_line, err = _line_format(line,'str',scheme)
278 if not err: line = new_line
279 if not err: line = new_line
279
280
280 if i == lnum:
281 if i == lnum:
281 # This is the line with the error
282 # This is the line with the error
282 pad = numbers_width - len(str(i))
283 pad = numbers_width - len(str(i))
283 if pad >= 3:
284 if pad >= 3:
284 marker = '-'*(pad-3) + '-> '
285 marker = '-'*(pad-3) + '-> '
285 elif pad == 2:
286 elif pad == 2:
286 marker = '> '
287 marker = '> '
287 elif pad == 1:
288 elif pad == 1:
288 marker = '>'
289 marker = '>'
289 else:
290 else:
290 marker = ''
291 marker = ''
291 num = marker + str(i)
292 num = marker + str(i)
292 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
293 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
293 Colors.line, line, Colors.Normal)
294 Colors.line, line, Colors.Normal)
294 else:
295 else:
295 num = '%*s' % (numbers_width,i)
296 num = '%*s' % (numbers_width,i)
296 line = '%s%s%s %s' %(Colors.lineno, num,
297 line = '%s%s%s %s' %(Colors.lineno, num,
297 Colors.Normal, line)
298 Colors.Normal, line)
298
299
299 res.append(line)
300 res.append(line)
300 if lvals and i == lnum:
301 if lvals and i == lnum:
301 res.append(lvals + '\n')
302 res.append(lvals + '\n')
302 i = i + 1
303 i = i + 1
303 return res
304 return res
304
305
305
306
306 #---------------------------------------------------------------------------
307 #---------------------------------------------------------------------------
307 # Module classes
308 # Module classes
308 class TBTools:
309 class TBTools:
309 """Basic tools used by all traceback printer classes."""
310 """Basic tools used by all traceback printer classes."""
310
311
311 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
312 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
312 # Whether to call the interactive pdb debugger after printing
313 # Whether to call the interactive pdb debugger after printing
313 # tracebacks or not
314 # tracebacks or not
314 self.call_pdb = call_pdb
315 self.call_pdb = call_pdb
315
316
316 # Create color table
317 # Create color table
317 self.color_scheme_table = exception_colors()
318 self.color_scheme_table = exception_colors()
318
319
319 self.set_colors(color_scheme)
320 self.set_colors(color_scheme)
320 self.old_scheme = color_scheme # save initial value for toggles
321 self.old_scheme = color_scheme # save initial value for toggles
321
322
322 if call_pdb:
323 if call_pdb:
323 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
324 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
324 else:
325 else:
325 self.pdb = None
326 self.pdb = None
326
327
327 def set_colors(self,*args,**kw):
328 def set_colors(self,*args,**kw):
328 """Shorthand access to the color table scheme selector method."""
329 """Shorthand access to the color table scheme selector method."""
329
330
330 # Set own color table
331 # Set own color table
331 self.color_scheme_table.set_active_scheme(*args,**kw)
332 self.color_scheme_table.set_active_scheme(*args,**kw)
332 # for convenience, set Colors to the active scheme
333 # for convenience, set Colors to the active scheme
333 self.Colors = self.color_scheme_table.active_colors
334 self.Colors = self.color_scheme_table.active_colors
334 # Also set colors of debugger
335 # Also set colors of debugger
335 if hasattr(self,'pdb') and self.pdb is not None:
336 if hasattr(self,'pdb') and self.pdb is not None:
336 self.pdb.set_colors(*args,**kw)
337 self.pdb.set_colors(*args,**kw)
337
338
338 def color_toggle(self):
339 def color_toggle(self):
339 """Toggle between the currently active color scheme and NoColor."""
340 """Toggle between the currently active color scheme and NoColor."""
340
341
341 if self.color_scheme_table.active_scheme_name == 'NoColor':
342 if self.color_scheme_table.active_scheme_name == 'NoColor':
342 self.color_scheme_table.set_active_scheme(self.old_scheme)
343 self.color_scheme_table.set_active_scheme(self.old_scheme)
343 self.Colors = self.color_scheme_table.active_colors
344 self.Colors = self.color_scheme_table.active_colors
344 else:
345 else:
345 self.old_scheme = self.color_scheme_table.active_scheme_name
346 self.old_scheme = self.color_scheme_table.active_scheme_name
346 self.color_scheme_table.set_active_scheme('NoColor')
347 self.color_scheme_table.set_active_scheme('NoColor')
347 self.Colors = self.color_scheme_table.active_colors
348 self.Colors = self.color_scheme_table.active_colors
348
349
349 #---------------------------------------------------------------------------
350 #---------------------------------------------------------------------------
350 class ListTB(TBTools):
351 class ListTB(TBTools):
351 """Print traceback information from a traceback list, with optional color.
352 """Print traceback information from a traceback list, with optional color.
352
353
353 Calling: requires 3 arguments:
354 Calling: requires 3 arguments:
354 (etype, evalue, elist)
355 (etype, evalue, elist)
355 as would be obtained by:
356 as would be obtained by:
356 etype, evalue, tb = sys.exc_info()
357 etype, evalue, tb = sys.exc_info()
357 if tb:
358 if tb:
358 elist = traceback.extract_tb(tb)
359 elist = traceback.extract_tb(tb)
359 else:
360 else:
360 elist = None
361 elist = None
361
362
362 It can thus be used by programs which need to process the traceback before
363 It can thus be used by programs which need to process the traceback before
363 printing (such as console replacements based on the code module from the
364 printing (such as console replacements based on the code module from the
364 standard library).
365 standard library).
365
366
366 Because they are meant to be called without a full traceback (only a
367 Because they are meant to be called without a full traceback (only a
367 list), instances of this class can't call the interactive pdb debugger."""
368 list), instances of this class can't call the interactive pdb debugger."""
368
369
369 def __init__(self,color_scheme = 'NoColor'):
370 def __init__(self,color_scheme = 'NoColor'):
370 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
371 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
371
372
372 def __call__(self, etype, value, elist):
373 def __call__(self, etype, value, elist):
373 Term.cout.flush()
374 Term.cout.flush()
374 print >> Term.cerr, self.text(etype,value,elist)
375 print >> Term.cerr, self.text(etype,value,elist)
375 Term.cerr.flush()
376 Term.cerr.flush()
376
377
377 def text(self,etype, value, elist,context=5):
378 def text(self,etype, value, elist,context=5):
378 """Return a color formatted string with the traceback info."""
379 """Return a color formatted string with the traceback info."""
379
380
380 Colors = self.Colors
381 Colors = self.Colors
381 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
382 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
382 if elist:
383 if elist:
383 out_string.append('Traceback %s(most recent call last)%s:' % \
384 out_string.append('Traceback %s(most recent call last)%s:' % \
384 (Colors.normalEm, Colors.Normal) + '\n')
385 (Colors.normalEm, Colors.Normal) + '\n')
385 out_string.extend(self._format_list(elist))
386 out_string.extend(self._format_list(elist))
386 lines = self._format_exception_only(etype, value)
387 lines = self._format_exception_only(etype, value)
387 for line in lines[:-1]:
388 for line in lines[:-1]:
388 out_string.append(" "+line)
389 out_string.append(" "+line)
389 out_string.append(lines[-1])
390 out_string.append(lines[-1])
390 return ''.join(out_string)
391 return ''.join(out_string)
391
392
392 def _format_list(self, extracted_list):
393 def _format_list(self, extracted_list):
393 """Format a list of traceback entry tuples for printing.
394 """Format a list of traceback entry tuples for printing.
394
395
395 Given a list of tuples as returned by extract_tb() or
396 Given a list of tuples as returned by extract_tb() or
396 extract_stack(), return a list of strings ready for printing.
397 extract_stack(), return a list of strings ready for printing.
397 Each string in the resulting list corresponds to the item with the
398 Each string in the resulting list corresponds to the item with the
398 same index in the argument list. Each string ends in a newline;
399 same index in the argument list. Each string ends in a newline;
399 the strings may contain internal newlines as well, for those items
400 the strings may contain internal newlines as well, for those items
400 whose source text line is not None.
401 whose source text line is not None.
401
402
402 Lifted almost verbatim from traceback.py
403 Lifted almost verbatim from traceback.py
403 """
404 """
404
405
405 Colors = self.Colors
406 Colors = self.Colors
406 list = []
407 list = []
407 for filename, lineno, name, line in extracted_list[:-1]:
408 for filename, lineno, name, line in extracted_list[:-1]:
408 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
409 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
409 (Colors.filename, filename, Colors.Normal,
410 (Colors.filename, filename, Colors.Normal,
410 Colors.lineno, lineno, Colors.Normal,
411 Colors.lineno, lineno, Colors.Normal,
411 Colors.name, name, Colors.Normal)
412 Colors.name, name, Colors.Normal)
412 if line:
413 if line:
413 item = item + ' %s\n' % line.strip()
414 item = item + ' %s\n' % line.strip()
414 list.append(item)
415 list.append(item)
415 # Emphasize the last entry
416 # Emphasize the last entry
416 filename, lineno, name, line = extracted_list[-1]
417 filename, lineno, name, line = extracted_list[-1]
417 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
418 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
418 (Colors.normalEm,
419 (Colors.normalEm,
419 Colors.filenameEm, filename, Colors.normalEm,
420 Colors.filenameEm, filename, Colors.normalEm,
420 Colors.linenoEm, lineno, Colors.normalEm,
421 Colors.linenoEm, lineno, Colors.normalEm,
421 Colors.nameEm, name, Colors.normalEm,
422 Colors.nameEm, name, Colors.normalEm,
422 Colors.Normal)
423 Colors.Normal)
423 if line:
424 if line:
424 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
425 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
425 Colors.Normal)
426 Colors.Normal)
426 list.append(item)
427 list.append(item)
427 return list
428 return list
428
429
429 def _format_exception_only(self, etype, value):
430 def _format_exception_only(self, etype, value):
430 """Format the exception part of a traceback.
431 """Format the exception part of a traceback.
431
432
432 The arguments are the exception type and value such as given by
433 The arguments are the exception type and value such as given by
433 sys.exc_info()[:2]. The return value is a list of strings, each ending
434 sys.exc_info()[:2]. The return value is a list of strings, each ending
434 in a newline. Normally, the list contains a single string; however,
435 in a newline. Normally, the list contains a single string; however,
435 for SyntaxError exceptions, it contains several lines that (when
436 for SyntaxError exceptions, it contains several lines that (when
436 printed) display detailed information about where the syntax error
437 printed) display detailed information about where the syntax error
437 occurred. The message indicating which exception occurred is the
438 occurred. The message indicating which exception occurred is the
438 always last string in the list.
439 always last string in the list.
439
440
440 Also lifted nearly verbatim from traceback.py
441 Also lifted nearly verbatim from traceback.py
441 """
442 """
442
443
443 have_filedata = False
444 have_filedata = False
444 Colors = self.Colors
445 Colors = self.Colors
445 list = []
446 list = []
446 try:
447 try:
447 stype = Colors.excName + etype.__name__ + Colors.Normal
448 stype = Colors.excName + etype.__name__ + Colors.Normal
448 except AttributeError:
449 except AttributeError:
449 stype = etype # String exceptions don't get special coloring
450 stype = etype # String exceptions don't get special coloring
450 if value is None:
451 if value is None:
451 list.append( str(stype) + '\n')
452 list.append( str(stype) + '\n')
452 else:
453 else:
453 if etype is SyntaxError:
454 if etype is SyntaxError:
454 try:
455 try:
455 msg, (filename, lineno, offset, line) = value
456 msg, (filename, lineno, offset, line) = value
456 except:
457 except:
457 have_filedata = False
458 have_filedata = False
458 else:
459 else:
459 have_filedata = True
460 have_filedata = True
460 #print 'filename is',filename # dbg
461 #print 'filename is',filename # dbg
461 if not filename: filename = "<string>"
462 if not filename: filename = "<string>"
462 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
463 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
463 (Colors.normalEm,
464 (Colors.normalEm,
464 Colors.filenameEm, filename, Colors.normalEm,
465 Colors.filenameEm, filename, Colors.normalEm,
465 Colors.linenoEm, lineno, Colors.Normal ))
466 Colors.linenoEm, lineno, Colors.Normal ))
466 if line is not None:
467 if line is not None:
467 i = 0
468 i = 0
468 while i < len(line) and line[i].isspace():
469 while i < len(line) and line[i].isspace():
469 i = i+1
470 i = i+1
470 list.append('%s %s%s\n' % (Colors.line,
471 list.append('%s %s%s\n' % (Colors.line,
471 line.strip(),
472 line.strip(),
472 Colors.Normal))
473 Colors.Normal))
473 if offset is not None:
474 if offset is not None:
474 s = ' '
475 s = ' '
475 for c in line[i:offset-1]:
476 for c in line[i:offset-1]:
476 if c.isspace():
477 if c.isspace():
477 s = s + c
478 s = s + c
478 else:
479 else:
479 s = s + ' '
480 s = s + ' '
480 list.append('%s%s^%s\n' % (Colors.caret, s,
481 list.append('%s%s^%s\n' % (Colors.caret, s,
481 Colors.Normal) )
482 Colors.Normal) )
482 value = msg
483 value = msg
483 s = self._some_str(value)
484 s = self._some_str(value)
484 if s:
485 if s:
485 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
486 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
486 Colors.Normal, s))
487 Colors.Normal, s))
487 else:
488 else:
488 list.append('%s\n' % str(stype))
489 list.append('%s\n' % str(stype))
489
490
490 # vds:>>
491 # vds:>>
491 if have_filedata:
492 if have_filedata:
492 ipapi.get().IP.hooks.synchronize_with_editor(filename, lineno, 0)
493 ipinst = ipapi.get()
494 if ipinst is not None:
495 ipinst.IP.hooks.synchronize_with_editor(filename, lineno, 0)
493 # vds:<<
496 # vds:<<
494
497
495 return list
498 return list
496
499
497 def _some_str(self, value):
500 def _some_str(self, value):
498 # Lifted from traceback.py
501 # Lifted from traceback.py
499 try:
502 try:
500 return str(value)
503 return str(value)
501 except:
504 except:
502 return '<unprintable %s object>' % type(value).__name__
505 return '<unprintable %s object>' % type(value).__name__
503
506
504 #----------------------------------------------------------------------------
507 #----------------------------------------------------------------------------
505 class VerboseTB(TBTools):
508 class VerboseTB(TBTools):
506 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
509 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
507 of HTML. Requires inspect and pydoc. Crazy, man.
510 of HTML. Requires inspect and pydoc. Crazy, man.
508
511
509 Modified version which optionally strips the topmost entries from the
512 Modified version which optionally strips the topmost entries from the
510 traceback, to be used with alternate interpreters (because their own code
513 traceback, to be used with alternate interpreters (because their own code
511 would appear in the traceback)."""
514 would appear in the traceback)."""
512
515
513 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
516 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
514 call_pdb = 0, include_vars=1):
517 call_pdb = 0, include_vars=1):
515 """Specify traceback offset, headers and color scheme.
518 """Specify traceback offset, headers and color scheme.
516
519
517 Define how many frames to drop from the tracebacks. Calling it with
520 Define how many frames to drop from the tracebacks. Calling it with
518 tb_offset=1 allows use of this handler in interpreters which will have
521 tb_offset=1 allows use of this handler in interpreters which will have
519 their own code at the top of the traceback (VerboseTB will first
522 their own code at the top of the traceback (VerboseTB will first
520 remove that frame before printing the traceback info)."""
523 remove that frame before printing the traceback info)."""
521 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
524 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
522 self.tb_offset = tb_offset
525 self.tb_offset = tb_offset
523 self.long_header = long_header
526 self.long_header = long_header
524 self.include_vars = include_vars
527 self.include_vars = include_vars
525
528
526 def text(self, etype, evalue, etb, context=5):
529 def text(self, etype, evalue, etb, context=5):
527 """Return a nice text document describing the traceback."""
530 """Return a nice text document describing the traceback."""
528
531
529 # some locals
532 # some locals
530 try:
533 try:
531 etype = etype.__name__
534 etype = etype.__name__
532 except AttributeError:
535 except AttributeError:
533 pass
536 pass
534 Colors = self.Colors # just a shorthand + quicker name lookup
537 Colors = self.Colors # just a shorthand + quicker name lookup
535 ColorsNormal = Colors.Normal # used a lot
538 ColorsNormal = Colors.Normal # used a lot
536 col_scheme = self.color_scheme_table.active_scheme_name
539 col_scheme = self.color_scheme_table.active_scheme_name
537 indent = ' '*INDENT_SIZE
540 indent = ' '*INDENT_SIZE
538 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
541 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
539 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
542 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
540 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
543 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
541
544
542 # some internal-use functions
545 # some internal-use functions
543 def text_repr(value):
546 def text_repr(value):
544 """Hopefully pretty robust repr equivalent."""
547 """Hopefully pretty robust repr equivalent."""
545 # this is pretty horrible but should always return *something*
548 # this is pretty horrible but should always return *something*
546 try:
549 try:
547 return pydoc.text.repr(value)
550 return pydoc.text.repr(value)
548 except KeyboardInterrupt:
551 except KeyboardInterrupt:
549 raise
552 raise
550 except:
553 except:
551 try:
554 try:
552 return repr(value)
555 return repr(value)
553 except KeyboardInterrupt:
556 except KeyboardInterrupt:
554 raise
557 raise
555 except:
558 except:
556 try:
559 try:
557 # all still in an except block so we catch
560 # all still in an except block so we catch
558 # getattr raising
561 # getattr raising
559 name = getattr(value, '__name__', None)
562 name = getattr(value, '__name__', None)
560 if name:
563 if name:
561 # ick, recursion
564 # ick, recursion
562 return text_repr(name)
565 return text_repr(name)
563 klass = getattr(value, '__class__', None)
566 klass = getattr(value, '__class__', None)
564 if klass:
567 if klass:
565 return '%s instance' % text_repr(klass)
568 return '%s instance' % text_repr(klass)
566 except KeyboardInterrupt:
569 except KeyboardInterrupt:
567 raise
570 raise
568 except:
571 except:
569 return 'UNRECOVERABLE REPR FAILURE'
572 return 'UNRECOVERABLE REPR FAILURE'
570 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
573 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
571 def nullrepr(value, repr=text_repr): return ''
574 def nullrepr(value, repr=text_repr): return ''
572
575
573 # meat of the code begins
576 # meat of the code begins
574 try:
577 try:
575 etype = etype.__name__
578 etype = etype.__name__
576 except AttributeError:
579 except AttributeError:
577 pass
580 pass
578
581
579 if self.long_header:
582 if self.long_header:
580 # Header with the exception type, python version, and date
583 # Header with the exception type, python version, and date
581 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
584 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
582 date = time.ctime(time.time())
585 date = time.ctime(time.time())
583
586
584 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
587 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
585 exc, ' '*(75-len(str(etype))-len(pyver)),
588 exc, ' '*(75-len(str(etype))-len(pyver)),
586 pyver, string.rjust(date, 75) )
589 pyver, string.rjust(date, 75) )
587 head += "\nA problem occured executing Python code. Here is the sequence of function"\
590 head += "\nA problem occured executing Python code. Here is the sequence of function"\
588 "\ncalls leading up to the error, with the most recent (innermost) call last."
591 "\ncalls leading up to the error, with the most recent (innermost) call last."
589 else:
592 else:
590 # Simplified header
593 # Simplified header
591 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
594 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
592 string.rjust('Traceback (most recent call last)',
595 string.rjust('Traceback (most recent call last)',
593 75 - len(str(etype)) ) )
596 75 - len(str(etype)) ) )
594 frames = []
597 frames = []
595 # Flush cache before calling inspect. This helps alleviate some of the
598 # Flush cache before calling inspect. This helps alleviate some of the
596 # problems with python 2.3's inspect.py.
599 # problems with python 2.3's inspect.py.
597 linecache.checkcache()
600 linecache.checkcache()
598 # Drop topmost frames if requested
601 # Drop topmost frames if requested
599 try:
602 try:
600 # Try the default getinnerframes and Alex's: Alex's fixes some
603 # Try the default getinnerframes and Alex's: Alex's fixes some
601 # problems, but it generates empty tracebacks for console errors
604 # problems, but it generates empty tracebacks for console errors
602 # (5 blanks lines) where none should be returned.
605 # (5 blanks lines) where none should be returned.
603 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
606 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
604 #print 'python records:', records # dbg
607 #print 'python records:', records # dbg
605 records = _fixed_getinnerframes(etb, context,self.tb_offset)
608 records = _fixed_getinnerframes(etb, context,self.tb_offset)
606 #print 'alex records:', records # dbg
609 #print 'alex records:', records # dbg
607 except:
610 except:
608
611
609 # FIXME: I've been getting many crash reports from python 2.3
612 # FIXME: I've been getting many crash reports from python 2.3
610 # users, traceable to inspect.py. If I can find a small test-case
613 # users, traceable to inspect.py. If I can find a small test-case
611 # to reproduce this, I should either write a better workaround or
614 # to reproduce this, I should either write a better workaround or
612 # file a bug report against inspect (if that's the real problem).
615 # file a bug report against inspect (if that's the real problem).
613 # So far, I haven't been able to find an isolated example to
616 # So far, I haven't been able to find an isolated example to
614 # reproduce the problem.
617 # reproduce the problem.
615 inspect_error()
618 inspect_error()
616 traceback.print_exc(file=Term.cerr)
619 traceback.print_exc(file=Term.cerr)
617 info('\nUnfortunately, your original traceback can not be constructed.\n')
620 info('\nUnfortunately, your original traceback can not be constructed.\n')
618 return ''
621 return ''
619
622
620 # build some color string templates outside these nested loops
623 # build some color string templates outside these nested loops
621 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
624 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
622 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
625 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
623 ColorsNormal)
626 ColorsNormal)
624 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
627 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
625 (Colors.vName, Colors.valEm, ColorsNormal)
628 (Colors.vName, Colors.valEm, ColorsNormal)
626 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
629 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
627 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
630 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
628 Colors.vName, ColorsNormal)
631 Colors.vName, ColorsNormal)
629 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
632 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
630 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
633 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
631 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
634 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
632 ColorsNormal)
635 ColorsNormal)
633
636
634 # now, loop over all records printing context and info
637 # now, loop over all records printing context and info
635 abspath = os.path.abspath
638 abspath = os.path.abspath
636 for frame, file, lnum, func, lines, index in records:
639 for frame, file, lnum, func, lines, index in records:
637 #print '*** record:',file,lnum,func,lines,index # dbg
640 #print '*** record:',file,lnum,func,lines,index # dbg
638 try:
641 try:
639 file = file and abspath(file) or '?'
642 file = file and abspath(file) or '?'
640 except OSError:
643 except OSError:
641 # if file is '<console>' or something not in the filesystem,
644 # if file is '<console>' or something not in the filesystem,
642 # the abspath call will throw an OSError. Just ignore it and
645 # the abspath call will throw an OSError. Just ignore it and
643 # keep the original file string.
646 # keep the original file string.
644 pass
647 pass
645 link = tpl_link % file
648 link = tpl_link % file
646 try:
649 try:
647 args, varargs, varkw, locals = inspect.getargvalues(frame)
650 args, varargs, varkw, locals = inspect.getargvalues(frame)
648 except:
651 except:
649 # This can happen due to a bug in python2.3. We should be
652 # This can happen due to a bug in python2.3. We should be
650 # able to remove this try/except when 2.4 becomes a
653 # able to remove this try/except when 2.4 becomes a
651 # requirement. Bug details at http://python.org/sf/1005466
654 # requirement. Bug details at http://python.org/sf/1005466
652 inspect_error()
655 inspect_error()
653 traceback.print_exc(file=Term.cerr)
656 traceback.print_exc(file=Term.cerr)
654 info("\nIPython's exception reporting continues...\n")
657 info("\nIPython's exception reporting continues...\n")
655
658
656 if func == '?':
659 if func == '?':
657 call = ''
660 call = ''
658 else:
661 else:
659 # Decide whether to include variable details or not
662 # Decide whether to include variable details or not
660 var_repr = self.include_vars and eqrepr or nullrepr
663 var_repr = self.include_vars and eqrepr or nullrepr
661 try:
664 try:
662 call = tpl_call % (func,inspect.formatargvalues(args,
665 call = tpl_call % (func,inspect.formatargvalues(args,
663 varargs, varkw,
666 varargs, varkw,
664 locals,formatvalue=var_repr))
667 locals,formatvalue=var_repr))
665 except KeyError:
668 except KeyError:
666 # Very odd crash from inspect.formatargvalues(). The
669 # Very odd crash from inspect.formatargvalues(). The
667 # scenario under which it appeared was a call to
670 # scenario under which it appeared was a call to
668 # view(array,scale) in NumTut.view.view(), where scale had
671 # view(array,scale) in NumTut.view.view(), where scale had
669 # been defined as a scalar (it should be a tuple). Somehow
672 # been defined as a scalar (it should be a tuple). Somehow
670 # inspect messes up resolving the argument list of view()
673 # inspect messes up resolving the argument list of view()
671 # and barfs out. At some point I should dig into this one
674 # and barfs out. At some point I should dig into this one
672 # and file a bug report about it.
675 # and file a bug report about it.
673 inspect_error()
676 inspect_error()
674 traceback.print_exc(file=Term.cerr)
677 traceback.print_exc(file=Term.cerr)
675 info("\nIPython's exception reporting continues...\n")
678 info("\nIPython's exception reporting continues...\n")
676 call = tpl_call_fail % func
679 call = tpl_call_fail % func
677
680
678 # Initialize a list of names on the current line, which the
681 # Initialize a list of names on the current line, which the
679 # tokenizer below will populate.
682 # tokenizer below will populate.
680 names = []
683 names = []
681
684
682 def tokeneater(token_type, token, start, end, line):
685 def tokeneater(token_type, token, start, end, line):
683 """Stateful tokeneater which builds dotted names.
686 """Stateful tokeneater which builds dotted names.
684
687
685 The list of names it appends to (from the enclosing scope) can
688 The list of names it appends to (from the enclosing scope) can
686 contain repeated composite names. This is unavoidable, since
689 contain repeated composite names. This is unavoidable, since
687 there is no way to disambguate partial dotted structures until
690 there is no way to disambguate partial dotted structures until
688 the full list is known. The caller is responsible for pruning
691 the full list is known. The caller is responsible for pruning
689 the final list of duplicates before using it."""
692 the final list of duplicates before using it."""
690
693
691 # build composite names
694 # build composite names
692 if token == '.':
695 if token == '.':
693 try:
696 try:
694 names[-1] += '.'
697 names[-1] += '.'
695 # store state so the next token is added for x.y.z names
698 # store state so the next token is added for x.y.z names
696 tokeneater.name_cont = True
699 tokeneater.name_cont = True
697 return
700 return
698 except IndexError:
701 except IndexError:
699 pass
702 pass
700 if token_type == tokenize.NAME and token not in keyword.kwlist:
703 if token_type == tokenize.NAME and token not in keyword.kwlist:
701 if tokeneater.name_cont:
704 if tokeneater.name_cont:
702 # Dotted names
705 # Dotted names
703 names[-1] += token
706 names[-1] += token
704 tokeneater.name_cont = False
707 tokeneater.name_cont = False
705 else:
708 else:
706 # Regular new names. We append everything, the caller
709 # Regular new names. We append everything, the caller
707 # will be responsible for pruning the list later. It's
710 # will be responsible for pruning the list later. It's
708 # very tricky to try to prune as we go, b/c composite
711 # very tricky to try to prune as we go, b/c composite
709 # names can fool us. The pruning at the end is easy
712 # names can fool us. The pruning at the end is easy
710 # to do (or the caller can print a list with repeated
713 # to do (or the caller can print a list with repeated
711 # names if so desired.
714 # names if so desired.
712 names.append(token)
715 names.append(token)
713 elif token_type == tokenize.NEWLINE:
716 elif token_type == tokenize.NEWLINE:
714 raise IndexError
717 raise IndexError
715 # we need to store a bit of state in the tokenizer to build
718 # we need to store a bit of state in the tokenizer to build
716 # dotted names
719 # dotted names
717 tokeneater.name_cont = False
720 tokeneater.name_cont = False
718
721
719 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
722 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
720 line = getline(file, lnum[0])
723 line = getline(file, lnum[0])
721 lnum[0] += 1
724 lnum[0] += 1
722 return line
725 return line
723
726
724 # Build the list of names on this line of code where the exception
727 # Build the list of names on this line of code where the exception
725 # occurred.
728 # occurred.
726 try:
729 try:
727 # This builds the names list in-place by capturing it from the
730 # This builds the names list in-place by capturing it from the
728 # enclosing scope.
731 # enclosing scope.
729 tokenize.tokenize(linereader, tokeneater)
732 tokenize.tokenize(linereader, tokeneater)
730 except IndexError:
733 except IndexError:
731 # signals exit of tokenizer
734 # signals exit of tokenizer
732 pass
735 pass
733 except tokenize.TokenError,msg:
736 except tokenize.TokenError,msg:
734 _m = ("An unexpected error occurred while tokenizing input\n"
737 _m = ("An unexpected error occurred while tokenizing input\n"
735 "The following traceback may be corrupted or invalid\n"
738 "The following traceback may be corrupted or invalid\n"
736 "The error message is: %s\n" % msg)
739 "The error message is: %s\n" % msg)
737 error(_m)
740 error(_m)
738
741
739 # prune names list of duplicates, but keep the right order
742 # prune names list of duplicates, but keep the right order
740 unique_names = uniq_stable(names)
743 unique_names = uniq_stable(names)
741
744
742 # Start loop over vars
745 # Start loop over vars
743 lvals = []
746 lvals = []
744 if self.include_vars:
747 if self.include_vars:
745 for name_full in unique_names:
748 for name_full in unique_names:
746 name_base = name_full.split('.',1)[0]
749 name_base = name_full.split('.',1)[0]
747 if name_base in frame.f_code.co_varnames:
750 if name_base in frame.f_code.co_varnames:
748 if locals.has_key(name_base):
751 if locals.has_key(name_base):
749 try:
752 try:
750 value = repr(eval(name_full,locals))
753 value = repr(eval(name_full,locals))
751 except:
754 except:
752 value = undefined
755 value = undefined
753 else:
756 else:
754 value = undefined
757 value = undefined
755 name = tpl_local_var % name_full
758 name = tpl_local_var % name_full
756 else:
759 else:
757 if frame.f_globals.has_key(name_base):
760 if frame.f_globals.has_key(name_base):
758 try:
761 try:
759 value = repr(eval(name_full,frame.f_globals))
762 value = repr(eval(name_full,frame.f_globals))
760 except:
763 except:
761 value = undefined
764 value = undefined
762 else:
765 else:
763 value = undefined
766 value = undefined
764 name = tpl_global_var % name_full
767 name = tpl_global_var % name_full
765 lvals.append(tpl_name_val % (name,value))
768 lvals.append(tpl_name_val % (name,value))
766 if lvals:
769 if lvals:
767 lvals = '%s%s' % (indent,em_normal.join(lvals))
770 lvals = '%s%s' % (indent,em_normal.join(lvals))
768 else:
771 else:
769 lvals = ''
772 lvals = ''
770
773
771 level = '%s %s\n' % (link,call)
774 level = '%s %s\n' % (link,call)
772
775
773 if index is None:
776 if index is None:
774 frames.append(level)
777 frames.append(level)
775 else:
778 else:
776 frames.append('%s%s' % (level,''.join(
779 frames.append('%s%s' % (level,''.join(
777 _formatTracebackLines(lnum,index,lines,Colors,lvals,
780 _formatTracebackLines(lnum,index,lines,Colors,lvals,
778 col_scheme))))
781 col_scheme))))
779
782
780 # Get (safely) a string form of the exception info
783 # Get (safely) a string form of the exception info
781 try:
784 try:
782 etype_str,evalue_str = map(str,(etype,evalue))
785 etype_str,evalue_str = map(str,(etype,evalue))
783 except:
786 except:
784 # User exception is improperly defined.
787 # User exception is improperly defined.
785 etype,evalue = str,sys.exc_info()[:2]
788 etype,evalue = str,sys.exc_info()[:2]
786 etype_str,evalue_str = map(str,(etype,evalue))
789 etype_str,evalue_str = map(str,(etype,evalue))
787 # ... and format it
790 # ... and format it
788 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
791 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
789 ColorsNormal, evalue_str)]
792 ColorsNormal, evalue_str)]
790 if type(evalue) is types.InstanceType:
793 if type(evalue) is types.InstanceType:
791 try:
794 try:
792 names = [w for w in dir(evalue) if isinstance(w, basestring)]
795 names = [w for w in dir(evalue) if isinstance(w, basestring)]
793 except:
796 except:
794 # Every now and then, an object with funny inernals blows up
797 # Every now and then, an object with funny inernals blows up
795 # when dir() is called on it. We do the best we can to report
798 # when dir() is called on it. We do the best we can to report
796 # the problem and continue
799 # the problem and continue
797 _m = '%sException reporting error (object with broken dir())%s:'
800 _m = '%sException reporting error (object with broken dir())%s:'
798 exception.append(_m % (Colors.excName,ColorsNormal))
801 exception.append(_m % (Colors.excName,ColorsNormal))
799 etype_str,evalue_str = map(str,sys.exc_info()[:2])
802 etype_str,evalue_str = map(str,sys.exc_info()[:2])
800 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
803 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
801 ColorsNormal, evalue_str))
804 ColorsNormal, evalue_str))
802 names = []
805 names = []
803 for name in names:
806 for name in names:
804 value = text_repr(getattr(evalue, name))
807 value = text_repr(getattr(evalue, name))
805 exception.append('\n%s%s = %s' % (indent, name, value))
808 exception.append('\n%s%s = %s' % (indent, name, value))
806
809
807 # vds: >>
810 # vds: >>
808 if records:
811 if records:
809 filepath, lnum = records[-1][1:3]
812 filepath, lnum = records[-1][1:3]
810 #print "file:", str(file), "linenb", str(lnum) # dbg
813 #print "file:", str(file), "linenb", str(lnum) # dbg
811 filepath = os.path.abspath(filepath)
814 filepath = os.path.abspath(filepath)
812 ipapi.get().IP.hooks.synchronize_with_editor(filepath, lnum, 0)
815 ipinst = ipapi.get()
816 if ipinst is not None:
817 ipinst.IP.hooks.synchronize_with_editor(filepath, lnum, 0)
813 # vds: <<
818 # vds: <<
814
819
815 # return all our info assembled as a single string
820 # return all our info assembled as a single string
816 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
821 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
817
822
818 def debugger(self,force=False):
823 def debugger(self,force=False):
819 """Call up the pdb debugger if desired, always clean up the tb
824 """Call up the pdb debugger if desired, always clean up the tb
820 reference.
825 reference.
821
826
822 Keywords:
827 Keywords:
823
828
824 - force(False): by default, this routine checks the instance call_pdb
829 - force(False): by default, this routine checks the instance call_pdb
825 flag and does not actually invoke the debugger if the flag is false.
830 flag and does not actually invoke the debugger if the flag is false.
826 The 'force' option forces the debugger to activate even if the flag
831 The 'force' option forces the debugger to activate even if the flag
827 is false.
832 is false.
828
833
829 If the call_pdb flag is set, the pdb interactive debugger is
834 If the call_pdb flag is set, the pdb interactive debugger is
830 invoked. In all cases, the self.tb reference to the current traceback
835 invoked. In all cases, the self.tb reference to the current traceback
831 is deleted to prevent lingering references which hamper memory
836 is deleted to prevent lingering references which hamper memory
832 management.
837 management.
833
838
834 Note that each call to pdb() does an 'import readline', so if your app
839 Note that each call to pdb() does an 'import readline', so if your app
835 requires a special setup for the readline completers, you'll have to
840 requires a special setup for the readline completers, you'll have to
836 fix that by hand after invoking the exception handler."""
841 fix that by hand after invoking the exception handler."""
837
842
838 if force or self.call_pdb:
843 if force or self.call_pdb:
839 if self.pdb is None:
844 if self.pdb is None:
840 self.pdb = Debugger.Pdb(
845 self.pdb = Debugger.Pdb(
841 self.color_scheme_table.active_scheme_name)
846 self.color_scheme_table.active_scheme_name)
842 # the system displayhook may have changed, restore the original
847 # the system displayhook may have changed, restore the original
843 # for pdb
848 # for pdb
844 dhook = sys.displayhook
849 dhook = sys.displayhook
845 sys.displayhook = sys.__displayhook__
850 sys.displayhook = sys.__displayhook__
846 self.pdb.reset()
851 self.pdb.reset()
847 # Find the right frame so we don't pop up inside ipython itself
852 # Find the right frame so we don't pop up inside ipython itself
848 if hasattr(self,'tb'):
853 if hasattr(self,'tb'):
849 etb = self.tb
854 etb = self.tb
850 else:
855 else:
851 etb = self.tb = sys.last_traceback
856 etb = self.tb = sys.last_traceback
852 while self.tb.tb_next is not None:
857 while self.tb.tb_next is not None:
853 self.tb = self.tb.tb_next
858 self.tb = self.tb.tb_next
854 try:
859 try:
855 if etb and etb.tb_next:
860 if etb and etb.tb_next:
856 etb = etb.tb_next
861 etb = etb.tb_next
857 self.pdb.botframe = etb.tb_frame
862 self.pdb.botframe = etb.tb_frame
858 self.pdb.interaction(self.tb.tb_frame, self.tb)
863 self.pdb.interaction(self.tb.tb_frame, self.tb)
859 finally:
864 finally:
860 sys.displayhook = dhook
865 sys.displayhook = dhook
861
866
862 if hasattr(self,'tb'):
867 if hasattr(self,'tb'):
863 del self.tb
868 del self.tb
864
869
865 def handler(self, info=None):
870 def handler(self, info=None):
866 (etype, evalue, etb) = info or sys.exc_info()
871 (etype, evalue, etb) = info or sys.exc_info()
867 self.tb = etb
872 self.tb = etb
868 Term.cout.flush()
873 Term.cout.flush()
869 print >> Term.cerr, self.text(etype, evalue, etb)
874 print >> Term.cerr, self.text(etype, evalue, etb)
870 Term.cerr.flush()
875 Term.cerr.flush()
871
876
872 # Changed so an instance can just be called as VerboseTB_inst() and print
877 # Changed so an instance can just be called as VerboseTB_inst() and print
873 # out the right info on its own.
878 # out the right info on its own.
874 def __call__(self, etype=None, evalue=None, etb=None):
879 def __call__(self, etype=None, evalue=None, etb=None):
875 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
880 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
876 if etb is None:
881 if etb is None:
877 self.handler()
882 self.handler()
878 else:
883 else:
879 self.handler((etype, evalue, etb))
884 self.handler((etype, evalue, etb))
880 try:
885 try:
881 self.debugger()
886 self.debugger()
882 except KeyboardInterrupt:
887 except KeyboardInterrupt:
883 print "\nKeyboardInterrupt"
888 print "\nKeyboardInterrupt"
884
889
885 #----------------------------------------------------------------------------
890 #----------------------------------------------------------------------------
886 class FormattedTB(VerboseTB,ListTB):
891 class FormattedTB(VerboseTB,ListTB):
887 """Subclass ListTB but allow calling with a traceback.
892 """Subclass ListTB but allow calling with a traceback.
888
893
889 It can thus be used as a sys.excepthook for Python > 2.1.
894 It can thus be used as a sys.excepthook for Python > 2.1.
890
895
891 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
896 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
892
897
893 Allows a tb_offset to be specified. This is useful for situations where
898 Allows a tb_offset to be specified. This is useful for situations where
894 one needs to remove a number of topmost frames from the traceback (such as
899 one needs to remove a number of topmost frames from the traceback (such as
895 occurs with python programs that themselves execute other python code,
900 occurs with python programs that themselves execute other python code,
896 like Python shells). """
901 like Python shells). """
897
902
898 def __init__(self, mode = 'Plain', color_scheme='Linux',
903 def __init__(self, mode = 'Plain', color_scheme='Linux',
899 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
904 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
900
905
901 # NEVER change the order of this list. Put new modes at the end:
906 # NEVER change the order of this list. Put new modes at the end:
902 self.valid_modes = ['Plain','Context','Verbose']
907 self.valid_modes = ['Plain','Context','Verbose']
903 self.verbose_modes = self.valid_modes[1:3]
908 self.verbose_modes = self.valid_modes[1:3]
904
909
905 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
910 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
906 call_pdb=call_pdb,include_vars=include_vars)
911 call_pdb=call_pdb,include_vars=include_vars)
907 self.set_mode(mode)
912 self.set_mode(mode)
908
913
909 def _extract_tb(self,tb):
914 def _extract_tb(self,tb):
910 if tb:
915 if tb:
911 return traceback.extract_tb(tb)
916 return traceback.extract_tb(tb)
912 else:
917 else:
913 return None
918 return None
914
919
915 def text(self, etype, value, tb,context=5,mode=None):
920 def text(self, etype, value, tb,context=5,mode=None):
916 """Return formatted traceback.
921 """Return formatted traceback.
917
922
918 If the optional mode parameter is given, it overrides the current
923 If the optional mode parameter is given, it overrides the current
919 mode."""
924 mode."""
920
925
921 if mode is None:
926 if mode is None:
922 mode = self.mode
927 mode = self.mode
923 if mode in self.verbose_modes:
928 if mode in self.verbose_modes:
924 # verbose modes need a full traceback
929 # verbose modes need a full traceback
925 return VerboseTB.text(self,etype, value, tb,context=5)
930 return VerboseTB.text(self,etype, value, tb,context=5)
926 else:
931 else:
927 # We must check the source cache because otherwise we can print
932 # We must check the source cache because otherwise we can print
928 # out-of-date source code.
933 # out-of-date source code.
929 linecache.checkcache()
934 linecache.checkcache()
930 # Now we can extract and format the exception
935 # Now we can extract and format the exception
931 elist = self._extract_tb(tb)
936 elist = self._extract_tb(tb)
932 if len(elist) > self.tb_offset:
937 if len(elist) > self.tb_offset:
933 del elist[:self.tb_offset]
938 del elist[:self.tb_offset]
934 return ListTB.text(self,etype,value,elist)
939 return ListTB.text(self,etype,value,elist)
935
940
936 def set_mode(self,mode=None):
941 def set_mode(self,mode=None):
937 """Switch to the desired mode.
942 """Switch to the desired mode.
938
943
939 If mode is not specified, cycles through the available modes."""
944 If mode is not specified, cycles through the available modes."""
940
945
941 if not mode:
946 if not mode:
942 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
947 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
943 len(self.valid_modes)
948 len(self.valid_modes)
944 self.mode = self.valid_modes[new_idx]
949 self.mode = self.valid_modes[new_idx]
945 elif mode not in self.valid_modes:
950 elif mode not in self.valid_modes:
946 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
951 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
947 'Valid modes: '+str(self.valid_modes)
952 'Valid modes: '+str(self.valid_modes)
948 else:
953 else:
949 self.mode = mode
954 self.mode = mode
950 # include variable details only in 'Verbose' mode
955 # include variable details only in 'Verbose' mode
951 self.include_vars = (self.mode == self.valid_modes[2])
956 self.include_vars = (self.mode == self.valid_modes[2])
952
957
953 # some convenient shorcuts
958 # some convenient shorcuts
954 def plain(self):
959 def plain(self):
955 self.set_mode(self.valid_modes[0])
960 self.set_mode(self.valid_modes[0])
956
961
957 def context(self):
962 def context(self):
958 self.set_mode(self.valid_modes[1])
963 self.set_mode(self.valid_modes[1])
959
964
960 def verbose(self):
965 def verbose(self):
961 self.set_mode(self.valid_modes[2])
966 self.set_mode(self.valid_modes[2])
962
967
963 #----------------------------------------------------------------------------
968 #----------------------------------------------------------------------------
964 class AutoFormattedTB(FormattedTB):
969 class AutoFormattedTB(FormattedTB):
965 """A traceback printer which can be called on the fly.
970 """A traceback printer which can be called on the fly.
966
971
967 It will find out about exceptions by itself.
972 It will find out about exceptions by itself.
968
973
969 A brief example:
974 A brief example:
970
975
971 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
976 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
972 try:
977 try:
973 ...
978 ...
974 except:
979 except:
975 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
980 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
976 """
981 """
977 def __call__(self,etype=None,evalue=None,etb=None,
982 def __call__(self,etype=None,evalue=None,etb=None,
978 out=None,tb_offset=None):
983 out=None,tb_offset=None):
979 """Print out a formatted exception traceback.
984 """Print out a formatted exception traceback.
980
985
981 Optional arguments:
986 Optional arguments:
982 - out: an open file-like object to direct output to.
987 - out: an open file-like object to direct output to.
983
988
984 - tb_offset: the number of frames to skip over in the stack, on a
989 - tb_offset: the number of frames to skip over in the stack, on a
985 per-call basis (this overrides temporarily the instance's tb_offset
990 per-call basis (this overrides temporarily the instance's tb_offset
986 given at initialization time. """
991 given at initialization time. """
987
992
988 if out is None:
993 if out is None:
989 out = Term.cerr
994 out = Term.cerr
990 Term.cout.flush()
995 Term.cout.flush()
991 if tb_offset is not None:
996 if tb_offset is not None:
992 tb_offset, self.tb_offset = self.tb_offset, tb_offset
997 tb_offset, self.tb_offset = self.tb_offset, tb_offset
993 print >> out, self.text(etype, evalue, etb)
998 print >> out, self.text(etype, evalue, etb)
994 self.tb_offset = tb_offset
999 self.tb_offset = tb_offset
995 else:
1000 else:
996 print >> out, self.text(etype, evalue, etb)
1001 print >> out, self.text(etype, evalue, etb)
997 out.flush()
1002 out.flush()
998 try:
1003 try:
999 self.debugger()
1004 self.debugger()
1000 except KeyboardInterrupt:
1005 except KeyboardInterrupt:
1001 print "\nKeyboardInterrupt"
1006 print "\nKeyboardInterrupt"
1002
1007
1003 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1008 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1004 if etype is None:
1009 if etype is None:
1005 etype,value,tb = sys.exc_info()
1010 etype,value,tb = sys.exc_info()
1006 self.tb = tb
1011 self.tb = tb
1007 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1012 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1008
1013
1009 #---------------------------------------------------------------------------
1014 #---------------------------------------------------------------------------
1010 # A simple class to preserve Nathan's original functionality.
1015 # A simple class to preserve Nathan's original functionality.
1011 class ColorTB(FormattedTB):
1016 class ColorTB(FormattedTB):
1012 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1017 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1013 def __init__(self,color_scheme='Linux',call_pdb=0):
1018 def __init__(self,color_scheme='Linux',call_pdb=0):
1014 FormattedTB.__init__(self,color_scheme=color_scheme,
1019 FormattedTB.__init__(self,color_scheme=color_scheme,
1015 call_pdb=call_pdb)
1020 call_pdb=call_pdb)
1016
1021
1017 #----------------------------------------------------------------------------
1022 #----------------------------------------------------------------------------
1018 # module testing (minimal)
1023 # module testing (minimal)
1019 if __name__ == "__main__":
1024 if __name__ == "__main__":
1020 def spam(c, (d, e)):
1025 def spam(c, (d, e)):
1021 x = c + d
1026 x = c + d
1022 y = c * d
1027 y = c * d
1023 foo(x, y)
1028 foo(x, y)
1024
1029
1025 def foo(a, b, bar=1):
1030 def foo(a, b, bar=1):
1026 eggs(a, b + bar)
1031 eggs(a, b + bar)
1027
1032
1028 def eggs(f, g, z=globals()):
1033 def eggs(f, g, z=globals()):
1029 h = f + g
1034 h = f + g
1030 i = f - g
1035 i = f - g
1031 return h / i
1036 return h / i
1032
1037
1033 print ''
1038 print ''
1034 print '*** Before ***'
1039 print '*** Before ***'
1035 try:
1040 try:
1036 print spam(1, (2, 3))
1041 print spam(1, (2, 3))
1037 except:
1042 except:
1038 traceback.print_exc()
1043 traceback.print_exc()
1039 print ''
1044 print ''
1040
1045
1041 handler = ColorTB()
1046 handler = ColorTB()
1042 print '*** ColorTB ***'
1047 print '*** ColorTB ***'
1043 try:
1048 try:
1044 print spam(1, (2, 3))
1049 print spam(1, (2, 3))
1045 except:
1050 except:
1046 apply(handler, sys.exc_info() )
1051 apply(handler, sys.exc_info() )
1047 print ''
1052 print ''
1048
1053
1049 handler = VerboseTB()
1054 handler = VerboseTB()
1050 print '*** VerboseTB ***'
1055 print '*** VerboseTB ***'
1051 try:
1056 try:
1052 print spam(1, (2, 3))
1057 print spam(1, (2, 3))
1053 except:
1058 except:
1054 apply(handler, sys.exc_info() )
1059 apply(handler, sys.exc_info() )
1055 print ''
1060 print ''
1056
1061
@@ -1,1056 +1,1061 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 # Required modules
72 # Required modules
73 import inspect
73 import inspect
74 import keyword
74 import keyword
75 import linecache
75 import linecache
76 import os
76 import os
77 import pydoc
77 import pydoc
78 import re
78 import re
79 import string
79 import string
80 import sys
80 import sys
81 import time
81 import time
82 import tokenize
82 import tokenize
83 import traceback
83 import traceback
84 import types
84 import types
85
85
86 # For purposes of monkeypatching inspect to fix a bug in it.
86 # For purposes of monkeypatching inspect to fix a bug in it.
87 from inspect import getsourcefile, getfile, getmodule,\
87 from inspect import getsourcefile, getfile, getmodule,\
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89
89
90
90
91 # IPython's own modules
91 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
92 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython import Debugger, PyColorize, ipapi
93 from IPython import Debugger, PyColorize, ipapi
94 from IPython.ipstruct import Struct
94 from IPython.ipstruct import Struct
95 from IPython.excolors import exception_colors
95 from IPython.excolors import exception_colors
96 from IPython.genutils import Term,uniq_stable,error,info
96 from IPython.genutils import Term,uniq_stable,error,info
97
97
98 # Globals
98 # Globals
99 # amount of space to put line numbers before verbose tracebacks
99 # amount of space to put line numbers before verbose tracebacks
100 INDENT_SIZE = 8
100 INDENT_SIZE = 8
101
101
102 # Default color scheme. This is used, for example, by the traceback
102 # Default color scheme. This is used, for example, by the traceback
103 # formatter. When running in an actual IPython instance, the user's rc.colors
103 # formatter. When running in an actual IPython instance, the user's rc.colors
104 # value is used, but havinga module global makes this functionality available
104 # value is used, but havinga module global makes this functionality available
105 # to users of ultraTB who are NOT running inside ipython.
105 # to users of ultraTB who are NOT running inside ipython.
106 DEFAULT_SCHEME = 'NoColor'
106 DEFAULT_SCHEME = 'NoColor'
107
107
108 #---------------------------------------------------------------------------
108 #---------------------------------------------------------------------------
109 # Code begins
109 # Code begins
110
110
111 # Utility functions
111 # Utility functions
112 def inspect_error():
112 def inspect_error():
113 """Print a message about internal inspect errors.
113 """Print a message about internal inspect errors.
114
114
115 These are unfortunately quite common."""
115 These are unfortunately quite common."""
116
116
117 error('Internal Python error in the inspect module.\n'
117 error('Internal Python error in the inspect module.\n'
118 'Below is the traceback from this internal error.\n')
118 'Below is the traceback from this internal error.\n')
119
119
120
120
121 def findsource(object):
121 def findsource(object):
122 """Return the entire source file and starting line number for an object.
122 """Return the entire source file and starting line number for an object.
123
123
124 The argument may be a module, class, method, function, traceback, frame,
124 The argument may be a module, class, method, function, traceback, frame,
125 or code object. The source code is returned as a list of all the lines
125 or code object. The source code is returned as a list of all the lines
126 in the file and the line number indexes a line in that list. An IOError
126 in the file and the line number indexes a line in that list. An IOError
127 is raised if the source code cannot be retrieved.
127 is raised if the source code cannot be retrieved.
128
128
129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
130
130
131 file = getsourcefile(object) or getfile(object)
131 file = getsourcefile(object) or getfile(object)
132 # If the object is a frame, then trying to get the globals dict from its
132 # If the object is a frame, then trying to get the globals dict from its
133 # module won't work. Instead, the frame object itself has the globals
133 # module won't work. Instead, the frame object itself has the globals
134 # dictionary.
134 # dictionary.
135 globals_dict = None
135 globals_dict = None
136 if inspect.isframe(object):
136 if inspect.isframe(object):
137 # XXX: can this ever be false?
137 # XXX: can this ever be false?
138 globals_dict = object.f_globals
138 globals_dict = object.f_globals
139 else:
139 else:
140 module = getmodule(object, file)
140 module = getmodule(object, file)
141 if module:
141 if module:
142 globals_dict = module.__dict__
142 globals_dict = module.__dict__
143 lines = linecache.getlines(file, globals_dict)
143 lines = linecache.getlines(file, globals_dict)
144 if not lines:
144 if not lines:
145 raise IOError('could not get source code')
145 raise IOError('could not get source code')
146
146
147 if ismodule(object):
147 if ismodule(object):
148 return lines, 0
148 return lines, 0
149
149
150 if isclass(object):
150 if isclass(object):
151 name = object.__name__
151 name = object.__name__
152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
153 # make some effort to find the best matching class definition:
153 # make some effort to find the best matching class definition:
154 # use the one with the least indentation, which is the one
154 # use the one with the least indentation, which is the one
155 # that's most probably not inside a function definition.
155 # that's most probably not inside a function definition.
156 candidates = []
156 candidates = []
157 for i in range(len(lines)):
157 for i in range(len(lines)):
158 match = pat.match(lines[i])
158 match = pat.match(lines[i])
159 if match:
159 if match:
160 # if it's at toplevel, it's already the best one
160 # if it's at toplevel, it's already the best one
161 if lines[i][0] == 'c':
161 if lines[i][0] == 'c':
162 return lines, i
162 return lines, i
163 # else add whitespace to candidate list
163 # else add whitespace to candidate list
164 candidates.append((match.group(1), i))
164 candidates.append((match.group(1), i))
165 if candidates:
165 if candidates:
166 # this will sort by whitespace, and by line number,
166 # this will sort by whitespace, and by line number,
167 # less whitespace first
167 # less whitespace first
168 candidates.sort()
168 candidates.sort()
169 return lines, candidates[0][1]
169 return lines, candidates[0][1]
170 else:
170 else:
171 raise IOError('could not find class definition')
171 raise IOError('could not find class definition')
172
172
173 if ismethod(object):
173 if ismethod(object):
174 object = object.im_func
174 object = object.im_func
175 if isfunction(object):
175 if isfunction(object):
176 object = object.func_code
176 object = object.func_code
177 if istraceback(object):
177 if istraceback(object):
178 object = object.tb_frame
178 object = object.tb_frame
179 if isframe(object):
179 if isframe(object):
180 object = object.f_code
180 object = object.f_code
181 if iscode(object):
181 if iscode(object):
182 if not hasattr(object, 'co_firstlineno'):
182 if not hasattr(object, 'co_firstlineno'):
183 raise IOError('could not find function definition')
183 raise IOError('could not find function definition')
184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
185 pmatch = pat.match
185 pmatch = pat.match
186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
187 # the length of lines, which causes an error. Safeguard against that.
187 # the length of lines, which causes an error. Safeguard against that.
188 lnum = min(object.co_firstlineno,len(lines))-1
188 lnum = min(object.co_firstlineno,len(lines))-1
189 while lnum > 0:
189 while lnum > 0:
190 if pmatch(lines[lnum]): break
190 if pmatch(lines[lnum]): break
191 lnum -= 1
191 lnum -= 1
192
192
193 return lines, lnum
193 return lines, lnum
194 raise IOError('could not find code object')
194 raise IOError('could not find code object')
195
195
196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
197 if sys.version_info[:2] >= (2,5):
197 if sys.version_info[:2] >= (2,5):
198 inspect.findsource = findsource
198 inspect.findsource = findsource
199
199
200 def fix_frame_records_filenames(records):
200 def fix_frame_records_filenames(records):
201 """Try to fix the filenames in each record from inspect.getinnerframes().
201 """Try to fix the filenames in each record from inspect.getinnerframes().
202
202
203 Particularly, modules loaded from within zip files have useless filenames
203 Particularly, modules loaded from within zip files have useless filenames
204 attached to their code object, and inspect.getinnerframes() just uses it.
204 attached to their code object, and inspect.getinnerframes() just uses it.
205 """
205 """
206 fixed_records = []
206 fixed_records = []
207 for frame, filename, line_no, func_name, lines, index in records:
207 for frame, filename, line_no, func_name, lines, index in records:
208 # Look inside the frame's globals dictionary for __file__, which should
208 # Look inside the frame's globals dictionary for __file__, which should
209 # be better.
209 # be better.
210 better_fn = frame.f_globals.get('__file__', None)
210 better_fn = frame.f_globals.get('__file__', None)
211 if isinstance(better_fn, str):
211 if isinstance(better_fn, str):
212 # Check the type just in case someone did something weird with
212 # Check the type just in case someone did something weird with
213 # __file__. It might also be None if the error occurred during
213 # __file__. It might also be None if the error occurred during
214 # import.
214 # import.
215 filename = better_fn
215 filename = better_fn
216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
217 return fixed_records
217 return fixed_records
218
218
219
219
220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
221 import linecache
221 import linecache
222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
223
223
224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
225
225
226 # If the error is at the console, don't build any context, since it would
226 # If the error is at the console, don't build any context, since it would
227 # otherwise produce 5 blank lines printed out (there is no file at the
227 # otherwise produce 5 blank lines printed out (there is no file at the
228 # console)
228 # console)
229 rec_check = records[tb_offset:]
229 rec_check = records[tb_offset:]
230 try:
230 try:
231 rname = rec_check[0][1]
231 rname = rec_check[0][1]
232 if rname == '<ipython console>' or rname.endswith('<string>'):
232 if rname == '<ipython console>' or rname.endswith('<string>'):
233 return rec_check
233 return rec_check
234 except IndexError:
234 except IndexError:
235 pass
235 pass
236
236
237 aux = traceback.extract_tb(etb)
237 aux = traceback.extract_tb(etb)
238 assert len(records) == len(aux)
238 assert len(records) == len(aux)
239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
240 maybeStart = lnum-1 - context//2
240 maybeStart = lnum-1 - context//2
241 start = max(maybeStart, 0)
241 start = max(maybeStart, 0)
242 end = start + context
242 end = start + context
243 lines = linecache.getlines(file)[start:end]
243 lines = linecache.getlines(file)[start:end]
244 # pad with empty lines if necessary
244 # pad with empty lines if necessary
245 if maybeStart < 0:
245 if maybeStart < 0:
246 lines = (['\n'] * -maybeStart) + lines
246 lines = (['\n'] * -maybeStart) + lines
247 if len(lines) < context:
247 if len(lines) < context:
248 lines += ['\n'] * (context - len(lines))
248 lines += ['\n'] * (context - len(lines))
249 buf = list(records[i])
249 buf = list(records[i])
250 buf[LNUM_POS] = lnum
250 buf[LNUM_POS] = lnum
251 buf[INDEX_POS] = lnum - 1 - start
251 buf[INDEX_POS] = lnum - 1 - start
252 buf[LINES_POS] = lines
252 buf[LINES_POS] = lines
253 records[i] = tuple(buf)
253 records[i] = tuple(buf)
254 return records[tb_offset:]
254 return records[tb_offset:]
255
255
256 # Helper function -- largely belongs to VerboseTB, but we need the same
256 # Helper function -- largely belongs to VerboseTB, but we need the same
257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
258 # can be recognized properly by ipython.el's py-traceback-line-re
258 # can be recognized properly by ipython.el's py-traceback-line-re
259 # (SyntaxErrors have to be treated specially because they have no traceback)
259 # (SyntaxErrors have to be treated specially because they have no traceback)
260
260
261 _parser = PyColorize.Parser()
261 _parser = PyColorize.Parser()
262
262
263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
264 numbers_width = INDENT_SIZE - 1
264 numbers_width = INDENT_SIZE - 1
265 res = []
265 res = []
266 i = lnum - index
266 i = lnum - index
267
267
268 # This lets us get fully syntax-highlighted tracebacks.
268 # This lets us get fully syntax-highlighted tracebacks.
269 if scheme is None:
269 if scheme is None:
270 try:
270 ipinst = ipapi.get()
271 scheme = ipapi.get().IP.rc.colors
271 if ipinst is not None:
272 except:
272 scheme = ipinst.IP.rc.colors
273 else:
273 scheme = DEFAULT_SCHEME
274 scheme = DEFAULT_SCHEME
274 _line_format = _parser.format2
275 _line_format = _parser.format2
275
276
276 for line in lines:
277 for line in lines:
277 new_line, err = _line_format(line,'str',scheme)
278 new_line, err = _line_format(line,'str',scheme)
278 if not err: line = new_line
279 if not err: line = new_line
279
280
280 if i == lnum:
281 if i == lnum:
281 # This is the line with the error
282 # This is the line with the error
282 pad = numbers_width - len(str(i))
283 pad = numbers_width - len(str(i))
283 if pad >= 3:
284 if pad >= 3:
284 marker = '-'*(pad-3) + '-> '
285 marker = '-'*(pad-3) + '-> '
285 elif pad == 2:
286 elif pad == 2:
286 marker = '> '
287 marker = '> '
287 elif pad == 1:
288 elif pad == 1:
288 marker = '>'
289 marker = '>'
289 else:
290 else:
290 marker = ''
291 marker = ''
291 num = marker + str(i)
292 num = marker + str(i)
292 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
293 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
293 Colors.line, line, Colors.Normal)
294 Colors.line, line, Colors.Normal)
294 else:
295 else:
295 num = '%*s' % (numbers_width,i)
296 num = '%*s' % (numbers_width,i)
296 line = '%s%s%s %s' %(Colors.lineno, num,
297 line = '%s%s%s %s' %(Colors.lineno, num,
297 Colors.Normal, line)
298 Colors.Normal, line)
298
299
299 res.append(line)
300 res.append(line)
300 if lvals and i == lnum:
301 if lvals and i == lnum:
301 res.append(lvals + '\n')
302 res.append(lvals + '\n')
302 i = i + 1
303 i = i + 1
303 return res
304 return res
304
305
305
306
306 #---------------------------------------------------------------------------
307 #---------------------------------------------------------------------------
307 # Module classes
308 # Module classes
308 class TBTools:
309 class TBTools:
309 """Basic tools used by all traceback printer classes."""
310 """Basic tools used by all traceback printer classes."""
310
311
311 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
312 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
312 # Whether to call the interactive pdb debugger after printing
313 # Whether to call the interactive pdb debugger after printing
313 # tracebacks or not
314 # tracebacks or not
314 self.call_pdb = call_pdb
315 self.call_pdb = call_pdb
315
316
316 # Create color table
317 # Create color table
317 self.color_scheme_table = exception_colors()
318 self.color_scheme_table = exception_colors()
318
319
319 self.set_colors(color_scheme)
320 self.set_colors(color_scheme)
320 self.old_scheme = color_scheme # save initial value for toggles
321 self.old_scheme = color_scheme # save initial value for toggles
321
322
322 if call_pdb:
323 if call_pdb:
323 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
324 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
324 else:
325 else:
325 self.pdb = None
326 self.pdb = None
326
327
327 def set_colors(self,*args,**kw):
328 def set_colors(self,*args,**kw):
328 """Shorthand access to the color table scheme selector method."""
329 """Shorthand access to the color table scheme selector method."""
329
330
330 # Set own color table
331 # Set own color table
331 self.color_scheme_table.set_active_scheme(*args,**kw)
332 self.color_scheme_table.set_active_scheme(*args,**kw)
332 # for convenience, set Colors to the active scheme
333 # for convenience, set Colors to the active scheme
333 self.Colors = self.color_scheme_table.active_colors
334 self.Colors = self.color_scheme_table.active_colors
334 # Also set colors of debugger
335 # Also set colors of debugger
335 if hasattr(self,'pdb') and self.pdb is not None:
336 if hasattr(self,'pdb') and self.pdb is not None:
336 self.pdb.set_colors(*args,**kw)
337 self.pdb.set_colors(*args,**kw)
337
338
338 def color_toggle(self):
339 def color_toggle(self):
339 """Toggle between the currently active color scheme and NoColor."""
340 """Toggle between the currently active color scheme and NoColor."""
340
341
341 if self.color_scheme_table.active_scheme_name == 'NoColor':
342 if self.color_scheme_table.active_scheme_name == 'NoColor':
342 self.color_scheme_table.set_active_scheme(self.old_scheme)
343 self.color_scheme_table.set_active_scheme(self.old_scheme)
343 self.Colors = self.color_scheme_table.active_colors
344 self.Colors = self.color_scheme_table.active_colors
344 else:
345 else:
345 self.old_scheme = self.color_scheme_table.active_scheme_name
346 self.old_scheme = self.color_scheme_table.active_scheme_name
346 self.color_scheme_table.set_active_scheme('NoColor')
347 self.color_scheme_table.set_active_scheme('NoColor')
347 self.Colors = self.color_scheme_table.active_colors
348 self.Colors = self.color_scheme_table.active_colors
348
349
349 #---------------------------------------------------------------------------
350 #---------------------------------------------------------------------------
350 class ListTB(TBTools):
351 class ListTB(TBTools):
351 """Print traceback information from a traceback list, with optional color.
352 """Print traceback information from a traceback list, with optional color.
352
353
353 Calling: requires 3 arguments:
354 Calling: requires 3 arguments:
354 (etype, evalue, elist)
355 (etype, evalue, elist)
355 as would be obtained by:
356 as would be obtained by:
356 etype, evalue, tb = sys.exc_info()
357 etype, evalue, tb = sys.exc_info()
357 if tb:
358 if tb:
358 elist = traceback.extract_tb(tb)
359 elist = traceback.extract_tb(tb)
359 else:
360 else:
360 elist = None
361 elist = None
361
362
362 It can thus be used by programs which need to process the traceback before
363 It can thus be used by programs which need to process the traceback before
363 printing (such as console replacements based on the code module from the
364 printing (such as console replacements based on the code module from the
364 standard library).
365 standard library).
365
366
366 Because they are meant to be called without a full traceback (only a
367 Because they are meant to be called without a full traceback (only a
367 list), instances of this class can't call the interactive pdb debugger."""
368 list), instances of this class can't call the interactive pdb debugger."""
368
369
369 def __init__(self,color_scheme = 'NoColor'):
370 def __init__(self,color_scheme = 'NoColor'):
370 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
371 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
371
372
372 def __call__(self, etype, value, elist):
373 def __call__(self, etype, value, elist):
373 Term.cout.flush()
374 Term.cout.flush()
374 print >> Term.cerr, self.text(etype,value,elist)
375 print >> Term.cerr, self.text(etype,value,elist)
375 Term.cerr.flush()
376 Term.cerr.flush()
376
377
377 def text(self,etype, value, elist,context=5):
378 def text(self,etype, value, elist,context=5):
378 """Return a color formatted string with the traceback info."""
379 """Return a color formatted string with the traceback info."""
379
380
380 Colors = self.Colors
381 Colors = self.Colors
381 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
382 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
382 if elist:
383 if elist:
383 out_string.append('Traceback %s(most recent call last)%s:' % \
384 out_string.append('Traceback %s(most recent call last)%s:' % \
384 (Colors.normalEm, Colors.Normal) + '\n')
385 (Colors.normalEm, Colors.Normal) + '\n')
385 out_string.extend(self._format_list(elist))
386 out_string.extend(self._format_list(elist))
386 lines = self._format_exception_only(etype, value)
387 lines = self._format_exception_only(etype, value)
387 for line in lines[:-1]:
388 for line in lines[:-1]:
388 out_string.append(" "+line)
389 out_string.append(" "+line)
389 out_string.append(lines[-1])
390 out_string.append(lines[-1])
390 return ''.join(out_string)
391 return ''.join(out_string)
391
392
392 def _format_list(self, extracted_list):
393 def _format_list(self, extracted_list):
393 """Format a list of traceback entry tuples for printing.
394 """Format a list of traceback entry tuples for printing.
394
395
395 Given a list of tuples as returned by extract_tb() or
396 Given a list of tuples as returned by extract_tb() or
396 extract_stack(), return a list of strings ready for printing.
397 extract_stack(), return a list of strings ready for printing.
397 Each string in the resulting list corresponds to the item with the
398 Each string in the resulting list corresponds to the item with the
398 same index in the argument list. Each string ends in a newline;
399 same index in the argument list. Each string ends in a newline;
399 the strings may contain internal newlines as well, for those items
400 the strings may contain internal newlines as well, for those items
400 whose source text line is not None.
401 whose source text line is not None.
401
402
402 Lifted almost verbatim from traceback.py
403 Lifted almost verbatim from traceback.py
403 """
404 """
404
405
405 Colors = self.Colors
406 Colors = self.Colors
406 list = []
407 list = []
407 for filename, lineno, name, line in extracted_list[:-1]:
408 for filename, lineno, name, line in extracted_list[:-1]:
408 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
409 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
409 (Colors.filename, filename, Colors.Normal,
410 (Colors.filename, filename, Colors.Normal,
410 Colors.lineno, lineno, Colors.Normal,
411 Colors.lineno, lineno, Colors.Normal,
411 Colors.name, name, Colors.Normal)
412 Colors.name, name, Colors.Normal)
412 if line:
413 if line:
413 item = item + ' %s\n' % line.strip()
414 item = item + ' %s\n' % line.strip()
414 list.append(item)
415 list.append(item)
415 # Emphasize the last entry
416 # Emphasize the last entry
416 filename, lineno, name, line = extracted_list[-1]
417 filename, lineno, name, line = extracted_list[-1]
417 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
418 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
418 (Colors.normalEm,
419 (Colors.normalEm,
419 Colors.filenameEm, filename, Colors.normalEm,
420 Colors.filenameEm, filename, Colors.normalEm,
420 Colors.linenoEm, lineno, Colors.normalEm,
421 Colors.linenoEm, lineno, Colors.normalEm,
421 Colors.nameEm, name, Colors.normalEm,
422 Colors.nameEm, name, Colors.normalEm,
422 Colors.Normal)
423 Colors.Normal)
423 if line:
424 if line:
424 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
425 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
425 Colors.Normal)
426 Colors.Normal)
426 list.append(item)
427 list.append(item)
427 return list
428 return list
428
429
429 def _format_exception_only(self, etype, value):
430 def _format_exception_only(self, etype, value):
430 """Format the exception part of a traceback.
431 """Format the exception part of a traceback.
431
432
432 The arguments are the exception type and value such as given by
433 The arguments are the exception type and value such as given by
433 sys.exc_info()[:2]. The return value is a list of strings, each ending
434 sys.exc_info()[:2]. The return value is a list of strings, each ending
434 in a newline. Normally, the list contains a single string; however,
435 in a newline. Normally, the list contains a single string; however,
435 for SyntaxError exceptions, it contains several lines that (when
436 for SyntaxError exceptions, it contains several lines that (when
436 printed) display detailed information about where the syntax error
437 printed) display detailed information about where the syntax error
437 occurred. The message indicating which exception occurred is the
438 occurred. The message indicating which exception occurred is the
438 always last string in the list.
439 always last string in the list.
439
440
440 Also lifted nearly verbatim from traceback.py
441 Also lifted nearly verbatim from traceback.py
441 """
442 """
442
443
443 have_filedata = False
444 have_filedata = False
444 Colors = self.Colors
445 Colors = self.Colors
445 list = []
446 list = []
446 try:
447 try:
447 stype = Colors.excName + etype.__name__ + Colors.Normal
448 stype = Colors.excName + etype.__name__ + Colors.Normal
448 except AttributeError:
449 except AttributeError:
449 stype = etype # String exceptions don't get special coloring
450 stype = etype # String exceptions don't get special coloring
450 if value is None:
451 if value is None:
451 list.append( str(stype) + '\n')
452 list.append( str(stype) + '\n')
452 else:
453 else:
453 if etype is SyntaxError:
454 if etype is SyntaxError:
454 try:
455 try:
455 msg, (filename, lineno, offset, line) = value
456 msg, (filename, lineno, offset, line) = value
456 except:
457 except:
457 have_filedata = False
458 have_filedata = False
458 else:
459 else:
459 have_filedata = True
460 have_filedata = True
460 #print 'filename is',filename # dbg
461 #print 'filename is',filename # dbg
461 if not filename: filename = "<string>"
462 if not filename: filename = "<string>"
462 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
463 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
463 (Colors.normalEm,
464 (Colors.normalEm,
464 Colors.filenameEm, filename, Colors.normalEm,
465 Colors.filenameEm, filename, Colors.normalEm,
465 Colors.linenoEm, lineno, Colors.Normal ))
466 Colors.linenoEm, lineno, Colors.Normal ))
466 if line is not None:
467 if line is not None:
467 i = 0
468 i = 0
468 while i < len(line) and line[i].isspace():
469 while i < len(line) and line[i].isspace():
469 i = i+1
470 i = i+1
470 list.append('%s %s%s\n' % (Colors.line,
471 list.append('%s %s%s\n' % (Colors.line,
471 line.strip(),
472 line.strip(),
472 Colors.Normal))
473 Colors.Normal))
473 if offset is not None:
474 if offset is not None:
474 s = ' '
475 s = ' '
475 for c in line[i:offset-1]:
476 for c in line[i:offset-1]:
476 if c.isspace():
477 if c.isspace():
477 s = s + c
478 s = s + c
478 else:
479 else:
479 s = s + ' '
480 s = s + ' '
480 list.append('%s%s^%s\n' % (Colors.caret, s,
481 list.append('%s%s^%s\n' % (Colors.caret, s,
481 Colors.Normal) )
482 Colors.Normal) )
482 value = msg
483 value = msg
483 s = self._some_str(value)
484 s = self._some_str(value)
484 if s:
485 if s:
485 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
486 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
486 Colors.Normal, s))
487 Colors.Normal, s))
487 else:
488 else:
488 list.append('%s\n' % str(stype))
489 list.append('%s\n' % str(stype))
489
490
490 # vds:>>
491 # vds:>>
491 if have_filedata:
492 if have_filedata:
492 ipapi.get().IP.hooks.synchronize_with_editor(filename, lineno, 0)
493 ipinst = ipapi.get()
494 if ipinst is not None:
495 ipinst.IP.hooks.synchronize_with_editor(filename, lineno, 0)
493 # vds:<<
496 # vds:<<
494
497
495 return list
498 return list
496
499
497 def _some_str(self, value):
500 def _some_str(self, value):
498 # Lifted from traceback.py
501 # Lifted from traceback.py
499 try:
502 try:
500 return str(value)
503 return str(value)
501 except:
504 except:
502 return '<unprintable %s object>' % type(value).__name__
505 return '<unprintable %s object>' % type(value).__name__
503
506
504 #----------------------------------------------------------------------------
507 #----------------------------------------------------------------------------
505 class VerboseTB(TBTools):
508 class VerboseTB(TBTools):
506 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
509 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
507 of HTML. Requires inspect and pydoc. Crazy, man.
510 of HTML. Requires inspect and pydoc. Crazy, man.
508
511
509 Modified version which optionally strips the topmost entries from the
512 Modified version which optionally strips the topmost entries from the
510 traceback, to be used with alternate interpreters (because their own code
513 traceback, to be used with alternate interpreters (because their own code
511 would appear in the traceback)."""
514 would appear in the traceback)."""
512
515
513 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
516 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
514 call_pdb = 0, include_vars=1):
517 call_pdb = 0, include_vars=1):
515 """Specify traceback offset, headers and color scheme.
518 """Specify traceback offset, headers and color scheme.
516
519
517 Define how many frames to drop from the tracebacks. Calling it with
520 Define how many frames to drop from the tracebacks. Calling it with
518 tb_offset=1 allows use of this handler in interpreters which will have
521 tb_offset=1 allows use of this handler in interpreters which will have
519 their own code at the top of the traceback (VerboseTB will first
522 their own code at the top of the traceback (VerboseTB will first
520 remove that frame before printing the traceback info)."""
523 remove that frame before printing the traceback info)."""
521 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
524 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
522 self.tb_offset = tb_offset
525 self.tb_offset = tb_offset
523 self.long_header = long_header
526 self.long_header = long_header
524 self.include_vars = include_vars
527 self.include_vars = include_vars
525
528
526 def text(self, etype, evalue, etb, context=5):
529 def text(self, etype, evalue, etb, context=5):
527 """Return a nice text document describing the traceback."""
530 """Return a nice text document describing the traceback."""
528
531
529 # some locals
532 # some locals
530 try:
533 try:
531 etype = etype.__name__
534 etype = etype.__name__
532 except AttributeError:
535 except AttributeError:
533 pass
536 pass
534 Colors = self.Colors # just a shorthand + quicker name lookup
537 Colors = self.Colors # just a shorthand + quicker name lookup
535 ColorsNormal = Colors.Normal # used a lot
538 ColorsNormal = Colors.Normal # used a lot
536 col_scheme = self.color_scheme_table.active_scheme_name
539 col_scheme = self.color_scheme_table.active_scheme_name
537 indent = ' '*INDENT_SIZE
540 indent = ' '*INDENT_SIZE
538 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
541 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
539 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
542 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
540 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
543 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
541
544
542 # some internal-use functions
545 # some internal-use functions
543 def text_repr(value):
546 def text_repr(value):
544 """Hopefully pretty robust repr equivalent."""
547 """Hopefully pretty robust repr equivalent."""
545 # this is pretty horrible but should always return *something*
548 # this is pretty horrible but should always return *something*
546 try:
549 try:
547 return pydoc.text.repr(value)
550 return pydoc.text.repr(value)
548 except KeyboardInterrupt:
551 except KeyboardInterrupt:
549 raise
552 raise
550 except:
553 except:
551 try:
554 try:
552 return repr(value)
555 return repr(value)
553 except KeyboardInterrupt:
556 except KeyboardInterrupt:
554 raise
557 raise
555 except:
558 except:
556 try:
559 try:
557 # all still in an except block so we catch
560 # all still in an except block so we catch
558 # getattr raising
561 # getattr raising
559 name = getattr(value, '__name__', None)
562 name = getattr(value, '__name__', None)
560 if name:
563 if name:
561 # ick, recursion
564 # ick, recursion
562 return text_repr(name)
565 return text_repr(name)
563 klass = getattr(value, '__class__', None)
566 klass = getattr(value, '__class__', None)
564 if klass:
567 if klass:
565 return '%s instance' % text_repr(klass)
568 return '%s instance' % text_repr(klass)
566 except KeyboardInterrupt:
569 except KeyboardInterrupt:
567 raise
570 raise
568 except:
571 except:
569 return 'UNRECOVERABLE REPR FAILURE'
572 return 'UNRECOVERABLE REPR FAILURE'
570 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
573 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
571 def nullrepr(value, repr=text_repr): return ''
574 def nullrepr(value, repr=text_repr): return ''
572
575
573 # meat of the code begins
576 # meat of the code begins
574 try:
577 try:
575 etype = etype.__name__
578 etype = etype.__name__
576 except AttributeError:
579 except AttributeError:
577 pass
580 pass
578
581
579 if self.long_header:
582 if self.long_header:
580 # Header with the exception type, python version, and date
583 # Header with the exception type, python version, and date
581 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
584 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
582 date = time.ctime(time.time())
585 date = time.ctime(time.time())
583
586
584 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
587 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
585 exc, ' '*(75-len(str(etype))-len(pyver)),
588 exc, ' '*(75-len(str(etype))-len(pyver)),
586 pyver, string.rjust(date, 75) )
589 pyver, string.rjust(date, 75) )
587 head += "\nA problem occured executing Python code. Here is the sequence of function"\
590 head += "\nA problem occured executing Python code. Here is the sequence of function"\
588 "\ncalls leading up to the error, with the most recent (innermost) call last."
591 "\ncalls leading up to the error, with the most recent (innermost) call last."
589 else:
592 else:
590 # Simplified header
593 # Simplified header
591 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
594 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
592 string.rjust('Traceback (most recent call last)',
595 string.rjust('Traceback (most recent call last)',
593 75 - len(str(etype)) ) )
596 75 - len(str(etype)) ) )
594 frames = []
597 frames = []
595 # Flush cache before calling inspect. This helps alleviate some of the
598 # Flush cache before calling inspect. This helps alleviate some of the
596 # problems with python 2.3's inspect.py.
599 # problems with python 2.3's inspect.py.
597 linecache.checkcache()
600 linecache.checkcache()
598 # Drop topmost frames if requested
601 # Drop topmost frames if requested
599 try:
602 try:
600 # Try the default getinnerframes and Alex's: Alex's fixes some
603 # Try the default getinnerframes and Alex's: Alex's fixes some
601 # problems, but it generates empty tracebacks for console errors
604 # problems, but it generates empty tracebacks for console errors
602 # (5 blanks lines) where none should be returned.
605 # (5 blanks lines) where none should be returned.
603 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
606 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
604 #print 'python records:', records # dbg
607 #print 'python records:', records # dbg
605 records = _fixed_getinnerframes(etb, context,self.tb_offset)
608 records = _fixed_getinnerframes(etb, context,self.tb_offset)
606 #print 'alex records:', records # dbg
609 #print 'alex records:', records # dbg
607 except:
610 except:
608
611
609 # FIXME: I've been getting many crash reports from python 2.3
612 # FIXME: I've been getting many crash reports from python 2.3
610 # users, traceable to inspect.py. If I can find a small test-case
613 # users, traceable to inspect.py. If I can find a small test-case
611 # to reproduce this, I should either write a better workaround or
614 # to reproduce this, I should either write a better workaround or
612 # file a bug report against inspect (if that's the real problem).
615 # file a bug report against inspect (if that's the real problem).
613 # So far, I haven't been able to find an isolated example to
616 # So far, I haven't been able to find an isolated example to
614 # reproduce the problem.
617 # reproduce the problem.
615 inspect_error()
618 inspect_error()
616 traceback.print_exc(file=Term.cerr)
619 traceback.print_exc(file=Term.cerr)
617 info('\nUnfortunately, your original traceback can not be constructed.\n')
620 info('\nUnfortunately, your original traceback can not be constructed.\n')
618 return ''
621 return ''
619
622
620 # build some color string templates outside these nested loops
623 # build some color string templates outside these nested loops
621 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
624 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
622 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
625 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
623 ColorsNormal)
626 ColorsNormal)
624 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
627 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
625 (Colors.vName, Colors.valEm, ColorsNormal)
628 (Colors.vName, Colors.valEm, ColorsNormal)
626 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
629 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
627 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
630 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
628 Colors.vName, ColorsNormal)
631 Colors.vName, ColorsNormal)
629 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
632 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
630 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
633 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
631 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
634 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
632 ColorsNormal)
635 ColorsNormal)
633
636
634 # now, loop over all records printing context and info
637 # now, loop over all records printing context and info
635 abspath = os.path.abspath
638 abspath = os.path.abspath
636 for frame, file, lnum, func, lines, index in records:
639 for frame, file, lnum, func, lines, index in records:
637 #print '*** record:',file,lnum,func,lines,index # dbg
640 #print '*** record:',file,lnum,func,lines,index # dbg
638 try:
641 try:
639 file = file and abspath(file) or '?'
642 file = file and abspath(file) or '?'
640 except OSError:
643 except OSError:
641 # if file is '<console>' or something not in the filesystem,
644 # if file is '<console>' or something not in the filesystem,
642 # the abspath call will throw an OSError. Just ignore it and
645 # the abspath call will throw an OSError. Just ignore it and
643 # keep the original file string.
646 # keep the original file string.
644 pass
647 pass
645 link = tpl_link % file
648 link = tpl_link % file
646 try:
649 try:
647 args, varargs, varkw, locals = inspect.getargvalues(frame)
650 args, varargs, varkw, locals = inspect.getargvalues(frame)
648 except:
651 except:
649 # This can happen due to a bug in python2.3. We should be
652 # This can happen due to a bug in python2.3. We should be
650 # able to remove this try/except when 2.4 becomes a
653 # able to remove this try/except when 2.4 becomes a
651 # requirement. Bug details at http://python.org/sf/1005466
654 # requirement. Bug details at http://python.org/sf/1005466
652 inspect_error()
655 inspect_error()
653 traceback.print_exc(file=Term.cerr)
656 traceback.print_exc(file=Term.cerr)
654 info("\nIPython's exception reporting continues...\n")
657 info("\nIPython's exception reporting continues...\n")
655
658
656 if func == '?':
659 if func == '?':
657 call = ''
660 call = ''
658 else:
661 else:
659 # Decide whether to include variable details or not
662 # Decide whether to include variable details or not
660 var_repr = self.include_vars and eqrepr or nullrepr
663 var_repr = self.include_vars and eqrepr or nullrepr
661 try:
664 try:
662 call = tpl_call % (func,inspect.formatargvalues(args,
665 call = tpl_call % (func,inspect.formatargvalues(args,
663 varargs, varkw,
666 varargs, varkw,
664 locals,formatvalue=var_repr))
667 locals,formatvalue=var_repr))
665 except KeyError:
668 except KeyError:
666 # Very odd crash from inspect.formatargvalues(). The
669 # Very odd crash from inspect.formatargvalues(). The
667 # scenario under which it appeared was a call to
670 # scenario under which it appeared was a call to
668 # view(array,scale) in NumTut.view.view(), where scale had
671 # view(array,scale) in NumTut.view.view(), where scale had
669 # been defined as a scalar (it should be a tuple). Somehow
672 # been defined as a scalar (it should be a tuple). Somehow
670 # inspect messes up resolving the argument list of view()
673 # inspect messes up resolving the argument list of view()
671 # and barfs out. At some point I should dig into this one
674 # and barfs out. At some point I should dig into this one
672 # and file a bug report about it.
675 # and file a bug report about it.
673 inspect_error()
676 inspect_error()
674 traceback.print_exc(file=Term.cerr)
677 traceback.print_exc(file=Term.cerr)
675 info("\nIPython's exception reporting continues...\n")
678 info("\nIPython's exception reporting continues...\n")
676 call = tpl_call_fail % func
679 call = tpl_call_fail % func
677
680
678 # Initialize a list of names on the current line, which the
681 # Initialize a list of names on the current line, which the
679 # tokenizer below will populate.
682 # tokenizer below will populate.
680 names = []
683 names = []
681
684
682 def tokeneater(token_type, token, start, end, line):
685 def tokeneater(token_type, token, start, end, line):
683 """Stateful tokeneater which builds dotted names.
686 """Stateful tokeneater which builds dotted names.
684
687
685 The list of names it appends to (from the enclosing scope) can
688 The list of names it appends to (from the enclosing scope) can
686 contain repeated composite names. This is unavoidable, since
689 contain repeated composite names. This is unavoidable, since
687 there is no way to disambguate partial dotted structures until
690 there is no way to disambguate partial dotted structures until
688 the full list is known. The caller is responsible for pruning
691 the full list is known. The caller is responsible for pruning
689 the final list of duplicates before using it."""
692 the final list of duplicates before using it."""
690
693
691 # build composite names
694 # build composite names
692 if token == '.':
695 if token == '.':
693 try:
696 try:
694 names[-1] += '.'
697 names[-1] += '.'
695 # store state so the next token is added for x.y.z names
698 # store state so the next token is added for x.y.z names
696 tokeneater.name_cont = True
699 tokeneater.name_cont = True
697 return
700 return
698 except IndexError:
701 except IndexError:
699 pass
702 pass
700 if token_type == tokenize.NAME and token not in keyword.kwlist:
703 if token_type == tokenize.NAME and token not in keyword.kwlist:
701 if tokeneater.name_cont:
704 if tokeneater.name_cont:
702 # Dotted names
705 # Dotted names
703 names[-1] += token
706 names[-1] += token
704 tokeneater.name_cont = False
707 tokeneater.name_cont = False
705 else:
708 else:
706 # Regular new names. We append everything, the caller
709 # Regular new names. We append everything, the caller
707 # will be responsible for pruning the list later. It's
710 # will be responsible for pruning the list later. It's
708 # very tricky to try to prune as we go, b/c composite
711 # very tricky to try to prune as we go, b/c composite
709 # names can fool us. The pruning at the end is easy
712 # names can fool us. The pruning at the end is easy
710 # to do (or the caller can print a list with repeated
713 # to do (or the caller can print a list with repeated
711 # names if so desired.
714 # names if so desired.
712 names.append(token)
715 names.append(token)
713 elif token_type == tokenize.NEWLINE:
716 elif token_type == tokenize.NEWLINE:
714 raise IndexError
717 raise IndexError
715 # we need to store a bit of state in the tokenizer to build
718 # we need to store a bit of state in the tokenizer to build
716 # dotted names
719 # dotted names
717 tokeneater.name_cont = False
720 tokeneater.name_cont = False
718
721
719 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
722 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
720 line = getline(file, lnum[0])
723 line = getline(file, lnum[0])
721 lnum[0] += 1
724 lnum[0] += 1
722 return line
725 return line
723
726
724 # Build the list of names on this line of code where the exception
727 # Build the list of names on this line of code where the exception
725 # occurred.
728 # occurred.
726 try:
729 try:
727 # This builds the names list in-place by capturing it from the
730 # This builds the names list in-place by capturing it from the
728 # enclosing scope.
731 # enclosing scope.
729 tokenize.tokenize(linereader, tokeneater)
732 tokenize.tokenize(linereader, tokeneater)
730 except IndexError:
733 except IndexError:
731 # signals exit of tokenizer
734 # signals exit of tokenizer
732 pass
735 pass
733 except tokenize.TokenError,msg:
736 except tokenize.TokenError,msg:
734 _m = ("An unexpected error occurred while tokenizing input\n"
737 _m = ("An unexpected error occurred while tokenizing input\n"
735 "The following traceback may be corrupted or invalid\n"
738 "The following traceback may be corrupted or invalid\n"
736 "The error message is: %s\n" % msg)
739 "The error message is: %s\n" % msg)
737 error(_m)
740 error(_m)
738
741
739 # prune names list of duplicates, but keep the right order
742 # prune names list of duplicates, but keep the right order
740 unique_names = uniq_stable(names)
743 unique_names = uniq_stable(names)
741
744
742 # Start loop over vars
745 # Start loop over vars
743 lvals = []
746 lvals = []
744 if self.include_vars:
747 if self.include_vars:
745 for name_full in unique_names:
748 for name_full in unique_names:
746 name_base = name_full.split('.',1)[0]
749 name_base = name_full.split('.',1)[0]
747 if name_base in frame.f_code.co_varnames:
750 if name_base in frame.f_code.co_varnames:
748 if locals.has_key(name_base):
751 if locals.has_key(name_base):
749 try:
752 try:
750 value = repr(eval(name_full,locals))
753 value = repr(eval(name_full,locals))
751 except:
754 except:
752 value = undefined
755 value = undefined
753 else:
756 else:
754 value = undefined
757 value = undefined
755 name = tpl_local_var % name_full
758 name = tpl_local_var % name_full
756 else:
759 else:
757 if frame.f_globals.has_key(name_base):
760 if frame.f_globals.has_key(name_base):
758 try:
761 try:
759 value = repr(eval(name_full,frame.f_globals))
762 value = repr(eval(name_full,frame.f_globals))
760 except:
763 except:
761 value = undefined
764 value = undefined
762 else:
765 else:
763 value = undefined
766 value = undefined
764 name = tpl_global_var % name_full
767 name = tpl_global_var % name_full
765 lvals.append(tpl_name_val % (name,value))
768 lvals.append(tpl_name_val % (name,value))
766 if lvals:
769 if lvals:
767 lvals = '%s%s' % (indent,em_normal.join(lvals))
770 lvals = '%s%s' % (indent,em_normal.join(lvals))
768 else:
771 else:
769 lvals = ''
772 lvals = ''
770
773
771 level = '%s %s\n' % (link,call)
774 level = '%s %s\n' % (link,call)
772
775
773 if index is None:
776 if index is None:
774 frames.append(level)
777 frames.append(level)
775 else:
778 else:
776 frames.append('%s%s' % (level,''.join(
779 frames.append('%s%s' % (level,''.join(
777 _formatTracebackLines(lnum,index,lines,Colors,lvals,
780 _formatTracebackLines(lnum,index,lines,Colors,lvals,
778 col_scheme))))
781 col_scheme))))
779
782
780 # Get (safely) a string form of the exception info
783 # Get (safely) a string form of the exception info
781 try:
784 try:
782 etype_str,evalue_str = map(str,(etype,evalue))
785 etype_str,evalue_str = map(str,(etype,evalue))
783 except:
786 except:
784 # User exception is improperly defined.
787 # User exception is improperly defined.
785 etype,evalue = str,sys.exc_info()[:2]
788 etype,evalue = str,sys.exc_info()[:2]
786 etype_str,evalue_str = map(str,(etype,evalue))
789 etype_str,evalue_str = map(str,(etype,evalue))
787 # ... and format it
790 # ... and format it
788 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
791 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
789 ColorsNormal, evalue_str)]
792 ColorsNormal, evalue_str)]
790 if type(evalue) is types.InstanceType:
793 if type(evalue) is types.InstanceType:
791 try:
794 try:
792 names = [w for w in dir(evalue) if isinstance(w, basestring)]
795 names = [w for w in dir(evalue) if isinstance(w, basestring)]
793 except:
796 except:
794 # Every now and then, an object with funny inernals blows up
797 # Every now and then, an object with funny inernals blows up
795 # when dir() is called on it. We do the best we can to report
798 # when dir() is called on it. We do the best we can to report
796 # the problem and continue
799 # the problem and continue
797 _m = '%sException reporting error (object with broken dir())%s:'
800 _m = '%sException reporting error (object with broken dir())%s:'
798 exception.append(_m % (Colors.excName,ColorsNormal))
801 exception.append(_m % (Colors.excName,ColorsNormal))
799 etype_str,evalue_str = map(str,sys.exc_info()[:2])
802 etype_str,evalue_str = map(str,sys.exc_info()[:2])
800 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
803 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
801 ColorsNormal, evalue_str))
804 ColorsNormal, evalue_str))
802 names = []
805 names = []
803 for name in names:
806 for name in names:
804 value = text_repr(getattr(evalue, name))
807 value = text_repr(getattr(evalue, name))
805 exception.append('\n%s%s = %s' % (indent, name, value))
808 exception.append('\n%s%s = %s' % (indent, name, value))
806
809
807 # vds: >>
810 # vds: >>
808 if records:
811 if records:
809 filepath, lnum = records[-1][1:3]
812 filepath, lnum = records[-1][1:3]
810 #print "file:", str(file), "linenb", str(lnum) # dbg
813 #print "file:", str(file), "linenb", str(lnum) # dbg
811 filepath = os.path.abspath(filepath)
814 filepath = os.path.abspath(filepath)
812 ipapi.get().IP.hooks.synchronize_with_editor(filepath, lnum, 0)
815 ipinst = ipapi.get()
816 if ipinst is not None:
817 ipinst.IP.hooks.synchronize_with_editor(filepath, lnum, 0)
813 # vds: <<
818 # vds: <<
814
819
815 # return all our info assembled as a single string
820 # return all our info assembled as a single string
816 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
821 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
817
822
818 def debugger(self,force=False):
823 def debugger(self,force=False):
819 """Call up the pdb debugger if desired, always clean up the tb
824 """Call up the pdb debugger if desired, always clean up the tb
820 reference.
825 reference.
821
826
822 Keywords:
827 Keywords:
823
828
824 - force(False): by default, this routine checks the instance call_pdb
829 - force(False): by default, this routine checks the instance call_pdb
825 flag and does not actually invoke the debugger if the flag is false.
830 flag and does not actually invoke the debugger if the flag is false.
826 The 'force' option forces the debugger to activate even if the flag
831 The 'force' option forces the debugger to activate even if the flag
827 is false.
832 is false.
828
833
829 If the call_pdb flag is set, the pdb interactive debugger is
834 If the call_pdb flag is set, the pdb interactive debugger is
830 invoked. In all cases, the self.tb reference to the current traceback
835 invoked. In all cases, the self.tb reference to the current traceback
831 is deleted to prevent lingering references which hamper memory
836 is deleted to prevent lingering references which hamper memory
832 management.
837 management.
833
838
834 Note that each call to pdb() does an 'import readline', so if your app
839 Note that each call to pdb() does an 'import readline', so if your app
835 requires a special setup for the readline completers, you'll have to
840 requires a special setup for the readline completers, you'll have to
836 fix that by hand after invoking the exception handler."""
841 fix that by hand after invoking the exception handler."""
837
842
838 if force or self.call_pdb:
843 if force or self.call_pdb:
839 if self.pdb is None:
844 if self.pdb is None:
840 self.pdb = Debugger.Pdb(
845 self.pdb = Debugger.Pdb(
841 self.color_scheme_table.active_scheme_name)
846 self.color_scheme_table.active_scheme_name)
842 # the system displayhook may have changed, restore the original
847 # the system displayhook may have changed, restore the original
843 # for pdb
848 # for pdb
844 dhook = sys.displayhook
849 dhook = sys.displayhook
845 sys.displayhook = sys.__displayhook__
850 sys.displayhook = sys.__displayhook__
846 self.pdb.reset()
851 self.pdb.reset()
847 # Find the right frame so we don't pop up inside ipython itself
852 # Find the right frame so we don't pop up inside ipython itself
848 if hasattr(self,'tb'):
853 if hasattr(self,'tb'):
849 etb = self.tb
854 etb = self.tb
850 else:
855 else:
851 etb = self.tb = sys.last_traceback
856 etb = self.tb = sys.last_traceback
852 while self.tb.tb_next is not None:
857 while self.tb.tb_next is not None:
853 self.tb = self.tb.tb_next
858 self.tb = self.tb.tb_next
854 try:
859 try:
855 if etb and etb.tb_next:
860 if etb and etb.tb_next:
856 etb = etb.tb_next
861 etb = etb.tb_next
857 self.pdb.botframe = etb.tb_frame
862 self.pdb.botframe = etb.tb_frame
858 self.pdb.interaction(self.tb.tb_frame, self.tb)
863 self.pdb.interaction(self.tb.tb_frame, self.tb)
859 finally:
864 finally:
860 sys.displayhook = dhook
865 sys.displayhook = dhook
861
866
862 if hasattr(self,'tb'):
867 if hasattr(self,'tb'):
863 del self.tb
868 del self.tb
864
869
865 def handler(self, info=None):
870 def handler(self, info=None):
866 (etype, evalue, etb) = info or sys.exc_info()
871 (etype, evalue, etb) = info or sys.exc_info()
867 self.tb = etb
872 self.tb = etb
868 Term.cout.flush()
873 Term.cout.flush()
869 print >> Term.cerr, self.text(etype, evalue, etb)
874 print >> Term.cerr, self.text(etype, evalue, etb)
870 Term.cerr.flush()
875 Term.cerr.flush()
871
876
872 # Changed so an instance can just be called as VerboseTB_inst() and print
877 # Changed so an instance can just be called as VerboseTB_inst() and print
873 # out the right info on its own.
878 # out the right info on its own.
874 def __call__(self, etype=None, evalue=None, etb=None):
879 def __call__(self, etype=None, evalue=None, etb=None):
875 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
880 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
876 if etb is None:
881 if etb is None:
877 self.handler()
882 self.handler()
878 else:
883 else:
879 self.handler((etype, evalue, etb))
884 self.handler((etype, evalue, etb))
880 try:
885 try:
881 self.debugger()
886 self.debugger()
882 except KeyboardInterrupt:
887 except KeyboardInterrupt:
883 print "\nKeyboardInterrupt"
888 print "\nKeyboardInterrupt"
884
889
885 #----------------------------------------------------------------------------
890 #----------------------------------------------------------------------------
886 class FormattedTB(VerboseTB,ListTB):
891 class FormattedTB(VerboseTB,ListTB):
887 """Subclass ListTB but allow calling with a traceback.
892 """Subclass ListTB but allow calling with a traceback.
888
893
889 It can thus be used as a sys.excepthook for Python > 2.1.
894 It can thus be used as a sys.excepthook for Python > 2.1.
890
895
891 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
896 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
892
897
893 Allows a tb_offset to be specified. This is useful for situations where
898 Allows a tb_offset to be specified. This is useful for situations where
894 one needs to remove a number of topmost frames from the traceback (such as
899 one needs to remove a number of topmost frames from the traceback (such as
895 occurs with python programs that themselves execute other python code,
900 occurs with python programs that themselves execute other python code,
896 like Python shells). """
901 like Python shells). """
897
902
898 def __init__(self, mode = 'Plain', color_scheme='Linux',
903 def __init__(self, mode = 'Plain', color_scheme='Linux',
899 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
904 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
900
905
901 # NEVER change the order of this list. Put new modes at the end:
906 # NEVER change the order of this list. Put new modes at the end:
902 self.valid_modes = ['Plain','Context','Verbose']
907 self.valid_modes = ['Plain','Context','Verbose']
903 self.verbose_modes = self.valid_modes[1:3]
908 self.verbose_modes = self.valid_modes[1:3]
904
909
905 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
910 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
906 call_pdb=call_pdb,include_vars=include_vars)
911 call_pdb=call_pdb,include_vars=include_vars)
907 self.set_mode(mode)
912 self.set_mode(mode)
908
913
909 def _extract_tb(self,tb):
914 def _extract_tb(self,tb):
910 if tb:
915 if tb:
911 return traceback.extract_tb(tb)
916 return traceback.extract_tb(tb)
912 else:
917 else:
913 return None
918 return None
914
919
915 def text(self, etype, value, tb,context=5,mode=None):
920 def text(self, etype, value, tb,context=5,mode=None):
916 """Return formatted traceback.
921 """Return formatted traceback.
917
922
918 If the optional mode parameter is given, it overrides the current
923 If the optional mode parameter is given, it overrides the current
919 mode."""
924 mode."""
920
925
921 if mode is None:
926 if mode is None:
922 mode = self.mode
927 mode = self.mode
923 if mode in self.verbose_modes:
928 if mode in self.verbose_modes:
924 # verbose modes need a full traceback
929 # verbose modes need a full traceback
925 return VerboseTB.text(self,etype, value, tb,context=5)
930 return VerboseTB.text(self,etype, value, tb,context=5)
926 else:
931 else:
927 # We must check the source cache because otherwise we can print
932 # We must check the source cache because otherwise we can print
928 # out-of-date source code.
933 # out-of-date source code.
929 linecache.checkcache()
934 linecache.checkcache()
930 # Now we can extract and format the exception
935 # Now we can extract and format the exception
931 elist = self._extract_tb(tb)
936 elist = self._extract_tb(tb)
932 if len(elist) > self.tb_offset:
937 if len(elist) > self.tb_offset:
933 del elist[:self.tb_offset]
938 del elist[:self.tb_offset]
934 return ListTB.text(self,etype,value,elist)
939 return ListTB.text(self,etype,value,elist)
935
940
936 def set_mode(self,mode=None):
941 def set_mode(self,mode=None):
937 """Switch to the desired mode.
942 """Switch to the desired mode.
938
943
939 If mode is not specified, cycles through the available modes."""
944 If mode is not specified, cycles through the available modes."""
940
945
941 if not mode:
946 if not mode:
942 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
947 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
943 len(self.valid_modes)
948 len(self.valid_modes)
944 self.mode = self.valid_modes[new_idx]
949 self.mode = self.valid_modes[new_idx]
945 elif mode not in self.valid_modes:
950 elif mode not in self.valid_modes:
946 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
951 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
947 'Valid modes: '+str(self.valid_modes)
952 'Valid modes: '+str(self.valid_modes)
948 else:
953 else:
949 self.mode = mode
954 self.mode = mode
950 # include variable details only in 'Verbose' mode
955 # include variable details only in 'Verbose' mode
951 self.include_vars = (self.mode == self.valid_modes[2])
956 self.include_vars = (self.mode == self.valid_modes[2])
952
957
953 # some convenient shorcuts
958 # some convenient shorcuts
954 def plain(self):
959 def plain(self):
955 self.set_mode(self.valid_modes[0])
960 self.set_mode(self.valid_modes[0])
956
961
957 def context(self):
962 def context(self):
958 self.set_mode(self.valid_modes[1])
963 self.set_mode(self.valid_modes[1])
959
964
960 def verbose(self):
965 def verbose(self):
961 self.set_mode(self.valid_modes[2])
966 self.set_mode(self.valid_modes[2])
962
967
963 #----------------------------------------------------------------------------
968 #----------------------------------------------------------------------------
964 class AutoFormattedTB(FormattedTB):
969 class AutoFormattedTB(FormattedTB):
965 """A traceback printer which can be called on the fly.
970 """A traceback printer which can be called on the fly.
966
971
967 It will find out about exceptions by itself.
972 It will find out about exceptions by itself.
968
973
969 A brief example:
974 A brief example:
970
975
971 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
976 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
972 try:
977 try:
973 ...
978 ...
974 except:
979 except:
975 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
980 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
976 """
981 """
977 def __call__(self,etype=None,evalue=None,etb=None,
982 def __call__(self,etype=None,evalue=None,etb=None,
978 out=None,tb_offset=None):
983 out=None,tb_offset=None):
979 """Print out a formatted exception traceback.
984 """Print out a formatted exception traceback.
980
985
981 Optional arguments:
986 Optional arguments:
982 - out: an open file-like object to direct output to.
987 - out: an open file-like object to direct output to.
983
988
984 - tb_offset: the number of frames to skip over in the stack, on a
989 - tb_offset: the number of frames to skip over in the stack, on a
985 per-call basis (this overrides temporarily the instance's tb_offset
990 per-call basis (this overrides temporarily the instance's tb_offset
986 given at initialization time. """
991 given at initialization time. """
987
992
988 if out is None:
993 if out is None:
989 out = Term.cerr
994 out = Term.cerr
990 Term.cout.flush()
995 Term.cout.flush()
991 if tb_offset is not None:
996 if tb_offset is not None:
992 tb_offset, self.tb_offset = self.tb_offset, tb_offset
997 tb_offset, self.tb_offset = self.tb_offset, tb_offset
993 print >> out, self.text(etype, evalue, etb)
998 print >> out, self.text(etype, evalue, etb)
994 self.tb_offset = tb_offset
999 self.tb_offset = tb_offset
995 else:
1000 else:
996 print >> out, self.text(etype, evalue, etb)
1001 print >> out, self.text(etype, evalue, etb)
997 out.flush()
1002 out.flush()
998 try:
1003 try:
999 self.debugger()
1004 self.debugger()
1000 except KeyboardInterrupt:
1005 except KeyboardInterrupt:
1001 print "\nKeyboardInterrupt"
1006 print "\nKeyboardInterrupt"
1002
1007
1003 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1008 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1004 if etype is None:
1009 if etype is None:
1005 etype,value,tb = sys.exc_info()
1010 etype,value,tb = sys.exc_info()
1006 self.tb = tb
1011 self.tb = tb
1007 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1012 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1008
1013
1009 #---------------------------------------------------------------------------
1014 #---------------------------------------------------------------------------
1010 # A simple class to preserve Nathan's original functionality.
1015 # A simple class to preserve Nathan's original functionality.
1011 class ColorTB(FormattedTB):
1016 class ColorTB(FormattedTB):
1012 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1017 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1013 def __init__(self,color_scheme='Linux',call_pdb=0):
1018 def __init__(self,color_scheme='Linux',call_pdb=0):
1014 FormattedTB.__init__(self,color_scheme=color_scheme,
1019 FormattedTB.__init__(self,color_scheme=color_scheme,
1015 call_pdb=call_pdb)
1020 call_pdb=call_pdb)
1016
1021
1017 #----------------------------------------------------------------------------
1022 #----------------------------------------------------------------------------
1018 # module testing (minimal)
1023 # module testing (minimal)
1019 if __name__ == "__main__":
1024 if __name__ == "__main__":
1020 def spam(c, (d, e)):
1025 def spam(c, (d, e)):
1021 x = c + d
1026 x = c + d
1022 y = c * d
1027 y = c * d
1023 foo(x, y)
1028 foo(x, y)
1024
1029
1025 def foo(a, b, bar=1):
1030 def foo(a, b, bar=1):
1026 eggs(a, b + bar)
1031 eggs(a, b + bar)
1027
1032
1028 def eggs(f, g, z=globals()):
1033 def eggs(f, g, z=globals()):
1029 h = f + g
1034 h = f + g
1030 i = f - g
1035 i = f - g
1031 return h / i
1036 return h / i
1032
1037
1033 print ''
1038 print ''
1034 print '*** Before ***'
1039 print '*** Before ***'
1035 try:
1040 try:
1036 print spam(1, (2, 3))
1041 print spam(1, (2, 3))
1037 except:
1042 except:
1038 traceback.print_exc()
1043 traceback.print_exc()
1039 print ''
1044 print ''
1040
1045
1041 handler = ColorTB()
1046 handler = ColorTB()
1042 print '*** ColorTB ***'
1047 print '*** ColorTB ***'
1043 try:
1048 try:
1044 print spam(1, (2, 3))
1049 print spam(1, (2, 3))
1045 except:
1050 except:
1046 apply(handler, sys.exc_info() )
1051 apply(handler, sys.exc_info() )
1047 print ''
1052 print ''
1048
1053
1049 handler = VerboseTB()
1054 handler = VerboseTB()
1050 print '*** VerboseTB ***'
1055 print '*** VerboseTB ***'
1051 try:
1056 try:
1052 print spam(1, (2, 3))
1057 print spam(1, (2, 3))
1053 except:
1058 except:
1054 apply(handler, sys.exc_info() )
1059 apply(handler, sys.exc_info() )
1055 print ''
1060 print ''
1056
1061
General Comments 0
You need to be logged in to leave comments. Login now