##// END OF EJS Templates
add docs and cleanup bad code style
Matthias Bussonnier -
Show More
@@ -1,1471 +1,1479 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Verbose and colourful traceback formatting.
3 Verbose and colourful traceback formatting.
4
4
5 **ColorTB**
5 **ColorTB**
6
6
7 I've always found it a bit hard to visually parse tracebacks in Python. The
7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 ColorTB class is a solution to that problem. It colors the different parts of a
8 ColorTB class is a solution to that problem. It colors the different parts of a
9 traceback in a manner similar to what you would expect from a syntax-highlighting
9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 text editor.
10 text editor.
11
11
12 Installation instructions for ColorTB::
12 Installation instructions for ColorTB::
13
13
14 import sys,ultratb
14 import sys,ultratb
15 sys.excepthook = ultratb.ColorTB()
15 sys.excepthook = ultratb.ColorTB()
16
16
17 **VerboseTB**
17 **VerboseTB**
18
18
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 and intended it for CGI programmers, but why should they have all the fun? I
21 and intended it for CGI programmers, but why should they have all the fun? I
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 but kind of neat, and maybe useful for long-running programs that you believe
23 but kind of neat, and maybe useful for long-running programs that you believe
24 are bug-free. If a crash *does* occur in that type of program you want details.
24 are bug-free. If a crash *does* occur in that type of program you want details.
25 Give it a shot--you'll love it or you'll hate it.
25 Give it a shot--you'll love it or you'll hate it.
26
26
27 .. note::
27 .. note::
28
28
29 The Verbose mode prints the variables currently visible where the exception
29 The Verbose mode prints the variables currently visible where the exception
30 happened (shortening their strings if too long). This can potentially be
30 happened (shortening their strings if too long). This can potentially be
31 very slow, if you happen to have a huge data structure whose string
31 very slow, if you happen to have a huge data structure whose string
32 representation is complex to compute. Your computer may appear to freeze for
32 representation is complex to compute. Your computer may appear to freeze for
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 with Ctrl-C (maybe hitting it more than once).
34 with Ctrl-C (maybe hitting it more than once).
35
35
36 If you encounter this kind of situation often, you may want to use the
36 If you encounter this kind of situation often, you may want to use the
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 variables (but otherwise includes the information and context given by
38 variables (but otherwise includes the information and context given by
39 Verbose).
39 Verbose).
40
40
41 .. note::
42
43 The verbose mode print all variables in the stack, which means it can
44 potentially leak sensitive information like access keys, or unencryted
45 password.
41
46
42 Installation instructions for VerboseTB::
47 Installation instructions for VerboseTB::
43
48
44 import sys,ultratb
49 import sys,ultratb
45 sys.excepthook = ultratb.VerboseTB()
50 sys.excepthook = ultratb.VerboseTB()
46
51
47 Note: Much of the code in this module was lifted verbatim from the standard
52 Note: Much of the code in this module was lifted verbatim from the standard
48 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
49
54
50 Color schemes
55 Color schemes
51 -------------
56 -------------
52
57
53 The colors are defined in the class TBTools through the use of the
58 The colors are defined in the class TBTools through the use of the
54 ColorSchemeTable class. Currently the following exist:
59 ColorSchemeTable class. Currently the following exist:
55
60
56 - NoColor: allows all of this module to be used in any terminal (the color
61 - NoColor: allows all of this module to be used in any terminal (the color
57 escapes are just dummy blank strings).
62 escapes are just dummy blank strings).
58
63
59 - Linux: is meant to look good in a terminal like the Linux console (black
64 - Linux: is meant to look good in a terminal like the Linux console (black
60 or very dark background).
65 or very dark background).
61
66
62 - LightBG: similar to Linux but swaps dark/light colors to be more readable
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
63 in light background terminals.
68 in light background terminals.
64
69
65 You can implement other color schemes easily, the syntax is fairly
70 You can implement other color schemes easily, the syntax is fairly
66 self-explanatory. Please send back new schemes you develop to the author for
71 self-explanatory. Please send back new schemes you develop to the author for
67 possible inclusion in future releases.
72 possible inclusion in future releases.
68
73
69 Inheritance diagram:
74 Inheritance diagram:
70
75
71 .. inheritance-diagram:: IPython.core.ultratb
76 .. inheritance-diagram:: IPython.core.ultratb
72 :parts: 3
77 :parts: 3
73 """
78 """
74
79
75 #*****************************************************************************
80 #*****************************************************************************
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
81 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
82 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
78 #
83 #
79 # Distributed under the terms of the BSD License. The full license is in
84 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
85 # the file COPYING, distributed as part of this software.
81 #*****************************************************************************
86 #*****************************************************************************
82
87
83 from __future__ import unicode_literals
88 from __future__ import unicode_literals
84 from __future__ import print_function
89 from __future__ import print_function
85
90
86 import dis
91 import dis
87 import inspect
92 import inspect
88 import keyword
93 import keyword
89 import linecache
94 import linecache
90 import os
95 import os
91 import pydoc
96 import pydoc
92 import re
97 import re
93 import sys
98 import sys
94 import time
99 import time
95 import tokenize
100 import tokenize
96 import traceback
101 import traceback
97 import types
102 import types
98
103
99 try: # Python 2
104 try: # Python 2
100 generate_tokens = tokenize.generate_tokens
105 generate_tokens = tokenize.generate_tokens
101 except AttributeError: # Python 3
106 except AttributeError: # Python 3
102 generate_tokens = tokenize.tokenize
107 generate_tokens = tokenize.tokenize
103
108
104 # For purposes of monkeypatching inspect to fix a bug in it.
109 # For purposes of monkeypatching inspect to fix a bug in it.
105 from inspect import getsourcefile, getfile, getmodule, \
110 from inspect import getsourcefile, getfile, getmodule, \
106 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
107
112
108 # IPython's own modules
113 # IPython's own modules
109 # Modified pdb which doesn't damage IPython's readline handling
114 # Modified pdb which doesn't damage IPython's readline handling
110 from IPython import get_ipython
115 from IPython import get_ipython
111 from IPython.core import debugger
116 from IPython.core import debugger
112 from IPython.core.display_trap import DisplayTrap
117 from IPython.core.display_trap import DisplayTrap
113 from IPython.core.excolors import exception_colors
118 from IPython.core.excolors import exception_colors
114 from IPython.utils import PyColorize
119 from IPython.utils import PyColorize
115 from IPython.utils import io
120 from IPython.utils import io
116 from IPython.utils import openpy
121 from IPython.utils import openpy
117 from IPython.utils import path as util_path
122 from IPython.utils import path as util_path
118 from IPython.utils import py3compat
123 from IPython.utils import py3compat
119 from IPython.utils import ulinecache
124 from IPython.utils import ulinecache
120 from IPython.utils.data import uniq_stable
125 from IPython.utils.data import uniq_stable
121 from IPython.utils.warn import info, error
126 from IPython.utils.warn import info, error
122
127
123 # Globals
128 # Globals
124 # amount of space to put line numbers before verbose tracebacks
129 # amount of space to put line numbers before verbose tracebacks
125 INDENT_SIZE = 8
130 INDENT_SIZE = 8
126
131
127 # Default color scheme. This is used, for example, by the traceback
132 # Default color scheme. This is used, for example, by the traceback
128 # formatter. When running in an actual IPython instance, the user's rc.colors
133 # formatter. When running in an actual IPython instance, the user's rc.colors
129 # value is used, but having a module global makes this functionality available
134 # value is used, but having a module global makes this functionality available
130 # to users of ultratb who are NOT running inside ipython.
135 # to users of ultratb who are NOT running inside ipython.
131 DEFAULT_SCHEME = 'NoColor'
136 DEFAULT_SCHEME = 'NoColor'
132
137
133 # ---------------------------------------------------------------------------
138 # ---------------------------------------------------------------------------
134 # Code begins
139 # Code begins
135
140
136 # Utility functions
141 # Utility functions
137 def inspect_error():
142 def inspect_error():
138 """Print a message about internal inspect errors.
143 """Print a message about internal inspect errors.
139
144
140 These are unfortunately quite common."""
145 These are unfortunately quite common."""
141
146
142 error('Internal Python error in the inspect module.\n'
147 error('Internal Python error in the inspect module.\n'
143 'Below is the traceback from this internal error.\n')
148 'Below is the traceback from this internal error.\n')
144
149
145
150
146 # This function is a monkeypatch we apply to the Python inspect module. We have
151 # This function is a monkeypatch we apply to the Python inspect module. We have
147 # now found when it's needed (see discussion on issue gh-1456), and we have a
152 # now found when it's needed (see discussion on issue gh-1456), and we have a
148 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
153 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
149 # the monkeypatch is not applied. TK, Aug 2012.
154 # the monkeypatch is not applied. TK, Aug 2012.
150 def findsource(object):
155 def findsource(object):
151 """Return the entire source file and starting line number for an object.
156 """Return the entire source file and starting line number for an object.
152
157
153 The argument may be a module, class, method, function, traceback, frame,
158 The argument may be a module, class, method, function, traceback, frame,
154 or code object. The source code is returned as a list of all the lines
159 or code object. The source code is returned as a list of all the lines
155 in the file and the line number indexes a line in that list. An IOError
160 in the file and the line number indexes a line in that list. An IOError
156 is raised if the source code cannot be retrieved.
161 is raised if the source code cannot be retrieved.
157
162
158 FIXED version with which we monkeypatch the stdlib to work around a bug."""
163 FIXED version with which we monkeypatch the stdlib to work around a bug."""
159
164
160 file = getsourcefile(object) or getfile(object)
165 file = getsourcefile(object) or getfile(object)
161 # If the object is a frame, then trying to get the globals dict from its
166 # If the object is a frame, then trying to get the globals dict from its
162 # module won't work. Instead, the frame object itself has the globals
167 # module won't work. Instead, the frame object itself has the globals
163 # dictionary.
168 # dictionary.
164 globals_dict = None
169 globals_dict = None
165 if inspect.isframe(object):
170 if inspect.isframe(object):
166 # XXX: can this ever be false?
171 # XXX: can this ever be false?
167 globals_dict = object.f_globals
172 globals_dict = object.f_globals
168 else:
173 else:
169 module = getmodule(object, file)
174 module = getmodule(object, file)
170 if module:
175 if module:
171 globals_dict = module.__dict__
176 globals_dict = module.__dict__
172 lines = linecache.getlines(file, globals_dict)
177 lines = linecache.getlines(file, globals_dict)
173 if not lines:
178 if not lines:
174 raise IOError('could not get source code')
179 raise IOError('could not get source code')
175
180
176 if ismodule(object):
181 if ismodule(object):
177 return lines, 0
182 return lines, 0
178
183
179 if isclass(object):
184 if isclass(object):
180 name = object.__name__
185 name = object.__name__
181 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
186 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
182 # make some effort to find the best matching class definition:
187 # make some effort to find the best matching class definition:
183 # use the one with the least indentation, which is the one
188 # use the one with the least indentation, which is the one
184 # that's most probably not inside a function definition.
189 # that's most probably not inside a function definition.
185 candidates = []
190 candidates = []
186 for i in range(len(lines)):
191 for i in range(len(lines)):
187 match = pat.match(lines[i])
192 match = pat.match(lines[i])
188 if match:
193 if match:
189 # if it's at toplevel, it's already the best one
194 # if it's at toplevel, it's already the best one
190 if lines[i][0] == 'c':
195 if lines[i][0] == 'c':
191 return lines, i
196 return lines, i
192 # else add whitespace to candidate list
197 # else add whitespace to candidate list
193 candidates.append((match.group(1), i))
198 candidates.append((match.group(1), i))
194 if candidates:
199 if candidates:
195 # this will sort by whitespace, and by line number,
200 # this will sort by whitespace, and by line number,
196 # less whitespace first
201 # less whitespace first
197 candidates.sort()
202 candidates.sort()
198 return lines, candidates[0][1]
203 return lines, candidates[0][1]
199 else:
204 else:
200 raise IOError('could not find class definition')
205 raise IOError('could not find class definition')
201
206
202 if ismethod(object):
207 if ismethod(object):
203 object = object.__func__
208 object = object.__func__
204 if isfunction(object):
209 if isfunction(object):
205 object = object.__code__
210 object = object.__code__
206 if istraceback(object):
211 if istraceback(object):
207 object = object.tb_frame
212 object = object.tb_frame
208 if isframe(object):
213 if isframe(object):
209 object = object.f_code
214 object = object.f_code
210 if iscode(object):
215 if iscode(object):
211 if not hasattr(object, 'co_firstlineno'):
216 if not hasattr(object, 'co_firstlineno'):
212 raise IOError('could not find function definition')
217 raise IOError('could not find function definition')
213 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
218 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
214 pmatch = pat.match
219 pmatch = pat.match
215 # fperez - fix: sometimes, co_firstlineno can give a number larger than
220 # fperez - fix: sometimes, co_firstlineno can give a number larger than
216 # the length of lines, which causes an error. Safeguard against that.
221 # the length of lines, which causes an error. Safeguard against that.
217 lnum = min(object.co_firstlineno, len(lines)) - 1
222 lnum = min(object.co_firstlineno, len(lines)) - 1
218 while lnum > 0:
223 while lnum > 0:
219 if pmatch(lines[lnum]): break
224 if pmatch(lines[lnum]):
225 break
220 lnum -= 1
226 lnum -= 1
221
227
222 return lines, lnum
228 return lines, lnum
223 raise IOError('could not find code object')
229 raise IOError('could not find code object')
224
230
225
231
226 # This is a patched version of inspect.getargs that applies the (unmerged)
232 # This is a patched version of inspect.getargs that applies the (unmerged)
227 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
233 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
228 # https://github.com/ipython/ipython/issues/8205 and
234 # https://github.com/ipython/ipython/issues/8205 and
229 # https://github.com/ipython/ipython/issues/8293
235 # https://github.com/ipython/ipython/issues/8293
230 def getargs(co):
236 def getargs(co):
231 """Get information about the arguments accepted by a code object.
237 """Get information about the arguments accepted by a code object.
232
238
233 Three things are returned: (args, varargs, varkw), where 'args' is
239 Three things are returned: (args, varargs, varkw), where 'args' is
234 a list of argument names (possibly containing nested lists), and
240 a list of argument names (possibly containing nested lists), and
235 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
241 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
236 if not iscode(co):
242 if not iscode(co):
237 raise TypeError('{!r} is not a code object'.format(co))
243 raise TypeError('{!r} is not a code object'.format(co))
238
244
239 nargs = co.co_argcount
245 nargs = co.co_argcount
240 names = co.co_varnames
246 names = co.co_varnames
241 args = list(names[:nargs])
247 args = list(names[:nargs])
242 step = 0
248 step = 0
243
249
244 # The following acrobatics are for anonymous (tuple) arguments.
250 # The following acrobatics are for anonymous (tuple) arguments.
245 for i in range(nargs):
251 for i in range(nargs):
246 if args[i][:1] in ('', '.'):
252 if args[i][:1] in ('', '.'):
247 stack, remain, count = [], [], []
253 stack, remain, count = [], [], []
248 while step < len(co.co_code):
254 while step < len(co.co_code):
249 op = ord(co.co_code[step])
255 op = ord(co.co_code[step])
250 step = step + 1
256 step = step + 1
251 if op >= dis.HAVE_ARGUMENT:
257 if op >= dis.HAVE_ARGUMENT:
252 opname = dis.opname[op]
258 opname = dis.opname[op]
253 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
259 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
254 step = step + 2
260 step = step + 2
255 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
261 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
256 remain.append(value)
262 remain.append(value)
257 count.append(value)
263 count.append(value)
258 elif opname in ('STORE_FAST', 'STORE_DEREF'):
264 elif opname in ('STORE_FAST', 'STORE_DEREF'):
259 if op in dis.haslocal:
265 if op in dis.haslocal:
260 stack.append(co.co_varnames[value])
266 stack.append(co.co_varnames[value])
261 elif op in dis.hasfree:
267 elif op in dis.hasfree:
262 stack.append((co.co_cellvars + co.co_freevars)[value])
268 stack.append((co.co_cellvars + co.co_freevars)[value])
263 # Special case for sublists of length 1: def foo((bar))
269 # Special case for sublists of length 1: def foo((bar))
264 # doesn't generate the UNPACK_TUPLE bytecode, so if
270 # doesn't generate the UNPACK_TUPLE bytecode, so if
265 # `remain` is empty here, we have such a sublist.
271 # `remain` is empty here, we have such a sublist.
266 if not remain:
272 if not remain:
267 stack[0] = [stack[0]]
273 stack[0] = [stack[0]]
268 break
274 break
269 else:
275 else:
270 remain[-1] = remain[-1] - 1
276 remain[-1] = remain[-1] - 1
271 while remain[-1] == 0:
277 while remain[-1] == 0:
272 remain.pop()
278 remain.pop()
273 size = count.pop()
279 size = count.pop()
274 stack[-size:] = [stack[-size:]]
280 stack[-size:] = [stack[-size:]]
275 if not remain: break
281 if not remain:
282 break
276 remain[-1] = remain[-1] - 1
283 remain[-1] = remain[-1] - 1
277 if not remain: break
284 if not remain:
285 break
278 args[i] = stack[0]
286 args[i] = stack[0]
279
287
280 varargs = None
288 varargs = None
281 if co.co_flags & inspect.CO_VARARGS:
289 if co.co_flags & inspect.CO_VARARGS:
282 varargs = co.co_varnames[nargs]
290 varargs = co.co_varnames[nargs]
283 nargs = nargs + 1
291 nargs = nargs + 1
284 varkw = None
292 varkw = None
285 if co.co_flags & inspect.CO_VARKEYWORDS:
293 if co.co_flags & inspect.CO_VARKEYWORDS:
286 varkw = co.co_varnames[nargs]
294 varkw = co.co_varnames[nargs]
287 return inspect.Arguments(args, varargs, varkw)
295 return inspect.Arguments(args, varargs, varkw)
288
296
289
297
290 # Monkeypatch inspect to apply our bugfix.
298 # Monkeypatch inspect to apply our bugfix.
291 def with_patch_inspect(f):
299 def with_patch_inspect(f):
292 """decorator for monkeypatching inspect.findsource"""
300 """decorator for monkeypatching inspect.findsource"""
293
301
294 def wrapped(*args, **kwargs):
302 def wrapped(*args, **kwargs):
295 save_findsource = inspect.findsource
303 save_findsource = inspect.findsource
296 save_getargs = inspect.getargs
304 save_getargs = inspect.getargs
297 inspect.findsource = findsource
305 inspect.findsource = findsource
298 inspect.getargs = getargs
306 inspect.getargs = getargs
299 try:
307 try:
300 return f(*args, **kwargs)
308 return f(*args, **kwargs)
301 finally:
309 finally:
302 inspect.findsource = save_findsource
310 inspect.findsource = save_findsource
303 inspect.getargs = save_getargs
311 inspect.getargs = save_getargs
304
312
305 return wrapped
313 return wrapped
306
314
307
315
308 if py3compat.PY3:
316 if py3compat.PY3:
309 fixed_getargvalues = inspect.getargvalues
317 fixed_getargvalues = inspect.getargvalues
310 else:
318 else:
311 # Fixes for https://github.com/ipython/ipython/issues/8293
319 # Fixes for https://github.com/ipython/ipython/issues/8293
312 # and https://github.com/ipython/ipython/issues/8205.
320 # and https://github.com/ipython/ipython/issues/8205.
313 # The relevant bug is caused by failure to correctly handle anonymous tuple
321 # The relevant bug is caused by failure to correctly handle anonymous tuple
314 # unpacking, which only exists in Python 2.
322 # unpacking, which only exists in Python 2.
315 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
323 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
316
324
317
325
318 def fix_frame_records_filenames(records):
326 def fix_frame_records_filenames(records):
319 """Try to fix the filenames in each record from inspect.getinnerframes().
327 """Try to fix the filenames in each record from inspect.getinnerframes().
320
328
321 Particularly, modules loaded from within zip files have useless filenames
329 Particularly, modules loaded from within zip files have useless filenames
322 attached to their code object, and inspect.getinnerframes() just uses it.
330 attached to their code object, and inspect.getinnerframes() just uses it.
323 """
331 """
324 fixed_records = []
332 fixed_records = []
325 for frame, filename, line_no, func_name, lines, index in records:
333 for frame, filename, line_no, func_name, lines, index in records:
326 # Look inside the frame's globals dictionary for __file__,
334 # Look inside the frame's globals dictionary for __file__,
327 # which should be better. However, keep Cython filenames since
335 # which should be better. However, keep Cython filenames since
328 # we prefer the source filenames over the compiled .so file.
336 # we prefer the source filenames over the compiled .so file.
329 filename = py3compat.cast_unicode_py2(filename, "utf-8")
337 filename = py3compat.cast_unicode_py2(filename, "utf-8")
330 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
338 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
331 better_fn = frame.f_globals.get('__file__', None)
339 better_fn = frame.f_globals.get('__file__', None)
332 if isinstance(better_fn, str):
340 if isinstance(better_fn, str):
333 # Check the type just in case someone did something weird with
341 # Check the type just in case someone did something weird with
334 # __file__. It might also be None if the error occurred during
342 # __file__. It might also be None if the error occurred during
335 # import.
343 # import.
336 filename = better_fn
344 filename = better_fn
337 fixed_records.append((frame, filename, line_no, func_name, lines, index))
345 fixed_records.append((frame, filename, line_no, func_name, lines, index))
338 return fixed_records
346 return fixed_records
339
347
340
348
341 @with_patch_inspect
349 @with_patch_inspect
342 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
350 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
343 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
351 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
344
352
345 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
353 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
346 # If the error is at the console, don't build any context, since it would
354 # If the error is at the console, don't build any context, since it would
347 # otherwise produce 5 blank lines printed out (there is no file at the
355 # otherwise produce 5 blank lines printed out (there is no file at the
348 # console)
356 # console)
349 rec_check = records[tb_offset:]
357 rec_check = records[tb_offset:]
350 try:
358 try:
351 rname = rec_check[0][1]
359 rname = rec_check[0][1]
352 if rname == '<ipython console>' or rname.endswith('<string>'):
360 if rname == '<ipython console>' or rname.endswith('<string>'):
353 return rec_check
361 return rec_check
354 except IndexError:
362 except IndexError:
355 pass
363 pass
356
364
357 aux = traceback.extract_tb(etb)
365 aux = traceback.extract_tb(etb)
358 assert len(records) == len(aux)
366 assert len(records) == len(aux)
359 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
367 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
360 maybeStart = lnum - 1 - context // 2
368 maybeStart = lnum - 1 - context // 2
361 start = max(maybeStart, 0)
369 start = max(maybeStart, 0)
362 end = start + context
370 end = start + context
363 lines = ulinecache.getlines(file)[start:end]
371 lines = ulinecache.getlines(file)[start:end]
364 buf = list(records[i])
372 buf = list(records[i])
365 buf[LNUM_POS] = lnum
373 buf[LNUM_POS] = lnum
366 buf[INDEX_POS] = lnum - 1 - start
374 buf[INDEX_POS] = lnum - 1 - start
367 buf[LINES_POS] = lines
375 buf[LINES_POS] = lines
368 records[i] = tuple(buf)
376 records[i] = tuple(buf)
369 return records[tb_offset:]
377 return records[tb_offset:]
370
378
371 # Helper function -- largely belongs to VerboseTB, but we need the same
379 # Helper function -- largely belongs to VerboseTB, but we need the same
372 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
380 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
373 # can be recognized properly by ipython.el's py-traceback-line-re
381 # can be recognized properly by ipython.el's py-traceback-line-re
374 # (SyntaxErrors have to be treated specially because they have no traceback)
382 # (SyntaxErrors have to be treated specially because they have no traceback)
375
383
376 _parser = PyColorize.Parser()
384 _parser = PyColorize.Parser()
377
385
378
386
379 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
387 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
380 numbers_width = INDENT_SIZE - 1
388 numbers_width = INDENT_SIZE - 1
381 res = []
389 res = []
382 i = lnum - index
390 i = lnum - index
383
391
384 # This lets us get fully syntax-highlighted tracebacks.
392 # This lets us get fully syntax-highlighted tracebacks.
385 if scheme is None:
393 if scheme is None:
386 ipinst = get_ipython()
394 ipinst = get_ipython()
387 if ipinst is not None:
395 if ipinst is not None:
388 scheme = ipinst.colors
396 scheme = ipinst.colors
389 else:
397 else:
390 scheme = DEFAULT_SCHEME
398 scheme = DEFAULT_SCHEME
391
399
392 _line_format = _parser.format2
400 _line_format = _parser.format2
393
401
394 for line in lines:
402 for line in lines:
395 line = py3compat.cast_unicode(line)
403 line = py3compat.cast_unicode(line)
396
404
397 new_line, err = _line_format(line, 'str', scheme)
405 new_line, err = _line_format(line, 'str', scheme)
398 if not err: line = new_line
406 if not err: line = new_line
399
407
400 if i == lnum:
408 if i == lnum:
401 # This is the line with the error
409 # This is the line with the error
402 pad = numbers_width - len(str(i))
410 pad = numbers_width - len(str(i))
403 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
411 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
404 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
412 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
405 Colors.line, line, Colors.Normal)
413 Colors.line, line, Colors.Normal)
406 else:
414 else:
407 num = '%*s' % (numbers_width, i)
415 num = '%*s' % (numbers_width, i)
408 line = '%s%s%s %s' % (Colors.lineno, num,
416 line = '%s%s%s %s' % (Colors.lineno, num,
409 Colors.Normal, line)
417 Colors.Normal, line)
410
418
411 res.append(line)
419 res.append(line)
412 if lvals and i == lnum:
420 if lvals and i == lnum:
413 res.append(lvals + '\n')
421 res.append(lvals + '\n')
414 i = i + 1
422 i = i + 1
415 return res
423 return res
416
424
417 def is_recursion_error(etype, value, records):
425 def is_recursion_error(etype, value, records):
418 try:
426 try:
419 # RecursionError is new in Python 3.5
427 # RecursionError is new in Python 3.5
420 recursion_error_type = RecursionError
428 recursion_error_type = RecursionError
421 except NameError:
429 except NameError:
422 recursion_error_type = RuntimeError
430 recursion_error_type = RuntimeError
423
431
424 # The default recursion limit is 1000, but some of that will be taken up
432 # The default recursion limit is 1000, but some of that will be taken up
425 # by stack frames in IPython itself. >500 frames probably indicates
433 # by stack frames in IPython itself. >500 frames probably indicates
426 # a recursion error.
434 # a recursion error.
427 return (etype is recursion_error_type) \
435 return (etype is recursion_error_type) \
428 and "recursion" in str(value).lower() \
436 and "recursion" in str(value).lower() \
429 and len(records) > 500
437 and len(records) > 500
430
438
431 def find_recursion(etype, value, records):
439 def find_recursion(etype, value, records):
432 """Identify the repeating stack frames from a RecursionError traceback
440 """Identify the repeating stack frames from a RecursionError traceback
433
441
434 'records' is a list as returned by VerboseTB.get_records()
442 'records' is a list as returned by VerboseTB.get_records()
435
443
436 Returns (last_unique, repeat_length)
444 Returns (last_unique, repeat_length)
437 """
445 """
438 # This involves a bit of guesswork - we want to show enough of the traceback
446 # This involves a bit of guesswork - we want to show enough of the traceback
439 # to indicate where the recursion is occurring. We guess that the innermost
447 # to indicate where the recursion is occurring. We guess that the innermost
440 # quarter of the traceback (250 frames by default) is repeats, and find the
448 # quarter of the traceback (250 frames by default) is repeats, and find the
441 # first frame (from in to out) that looks different.
449 # first frame (from in to out) that looks different.
442 if not is_recursion_error(etype, value, records):
450 if not is_recursion_error(etype, value, records):
443 return len(records), 0
451 return len(records), 0
444
452
445 # Select filename, lineno, func_name to track frames with
453 # Select filename, lineno, func_name to track frames with
446 records = [r[1:4] for r in records]
454 records = [r[1:4] for r in records]
447 inner_frames = records[-(len(records)//4):]
455 inner_frames = records[-(len(records)//4):]
448 frames_repeated = set(inner_frames)
456 frames_repeated = set(inner_frames)
449
457
450 last_seen_at = {}
458 last_seen_at = {}
451 longest_repeat = 0
459 longest_repeat = 0
452 i = len(records)
460 i = len(records)
453 for frame in reversed(records):
461 for frame in reversed(records):
454 i -= 1
462 i -= 1
455 if frame not in frames_repeated:
463 if frame not in frames_repeated:
456 last_unique = i
464 last_unique = i
457 break
465 break
458
466
459 if frame in last_seen_at:
467 if frame in last_seen_at:
460 distance = last_seen_at[frame] - i
468 distance = last_seen_at[frame] - i
461 longest_repeat = max(longest_repeat, distance)
469 longest_repeat = max(longest_repeat, distance)
462
470
463 last_seen_at[frame] = i
471 last_seen_at[frame] = i
464 else:
472 else:
465 last_unique = 0 # The whole traceback was recursion
473 last_unique = 0 # The whole traceback was recursion
466
474
467 return last_unique, longest_repeat
475 return last_unique, longest_repeat
468
476
469 #---------------------------------------------------------------------------
477 #---------------------------------------------------------------------------
470 # Module classes
478 # Module classes
471 class TBTools(object):
479 class TBTools(object):
472 """Basic tools used by all traceback printer classes."""
480 """Basic tools used by all traceback printer classes."""
473
481
474 # Number of frames to skip when reporting tracebacks
482 # Number of frames to skip when reporting tracebacks
475 tb_offset = 0
483 tb_offset = 0
476
484
477 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
485 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
478 # Whether to call the interactive pdb debugger after printing
486 # Whether to call the interactive pdb debugger after printing
479 # tracebacks or not
487 # tracebacks or not
480 self.call_pdb = call_pdb
488 self.call_pdb = call_pdb
481
489
482 # Output stream to write to. Note that we store the original value in
490 # Output stream to write to. Note that we store the original value in
483 # a private attribute and then make the public ostream a property, so
491 # a private attribute and then make the public ostream a property, so
484 # that we can delay accessing io.stdout until runtime. The way
492 # that we can delay accessing io.stdout until runtime. The way
485 # things are written now, the io.stdout object is dynamically managed
493 # things are written now, the io.stdout object is dynamically managed
486 # so a reference to it should NEVER be stored statically. This
494 # so a reference to it should NEVER be stored statically. This
487 # property approach confines this detail to a single location, and all
495 # property approach confines this detail to a single location, and all
488 # subclasses can simply access self.ostream for writing.
496 # subclasses can simply access self.ostream for writing.
489 self._ostream = ostream
497 self._ostream = ostream
490
498
491 # Create color table
499 # Create color table
492 self.color_scheme_table = exception_colors()
500 self.color_scheme_table = exception_colors()
493
501
494 self.set_colors(color_scheme)
502 self.set_colors(color_scheme)
495 self.old_scheme = color_scheme # save initial value for toggles
503 self.old_scheme = color_scheme # save initial value for toggles
496
504
497 if call_pdb:
505 if call_pdb:
498 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
506 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
499 else:
507 else:
500 self.pdb = None
508 self.pdb = None
501
509
502 def _get_ostream(self):
510 def _get_ostream(self):
503 """Output stream that exceptions are written to.
511 """Output stream that exceptions are written to.
504
512
505 Valid values are:
513 Valid values are:
506
514
507 - None: the default, which means that IPython will dynamically resolve
515 - None: the default, which means that IPython will dynamically resolve
508 to io.stdout. This ensures compatibility with most tools, including
516 to io.stdout. This ensures compatibility with most tools, including
509 Windows (where plain stdout doesn't recognize ANSI escapes).
517 Windows (where plain stdout doesn't recognize ANSI escapes).
510
518
511 - Any object with 'write' and 'flush' attributes.
519 - Any object with 'write' and 'flush' attributes.
512 """
520 """
513 return io.stdout if self._ostream is None else self._ostream
521 return io.stdout if self._ostream is None else self._ostream
514
522
515 def _set_ostream(self, val):
523 def _set_ostream(self, val):
516 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
524 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
517 self._ostream = val
525 self._ostream = val
518
526
519 ostream = property(_get_ostream, _set_ostream)
527 ostream = property(_get_ostream, _set_ostream)
520
528
521 def set_colors(self, *args, **kw):
529 def set_colors(self, *args, **kw):
522 """Shorthand access to the color table scheme selector method."""
530 """Shorthand access to the color table scheme selector method."""
523
531
524 # Set own color table
532 # Set own color table
525 self.color_scheme_table.set_active_scheme(*args, **kw)
533 self.color_scheme_table.set_active_scheme(*args, **kw)
526 # for convenience, set Colors to the active scheme
534 # for convenience, set Colors to the active scheme
527 self.Colors = self.color_scheme_table.active_colors
535 self.Colors = self.color_scheme_table.active_colors
528 # Also set colors of debugger
536 # Also set colors of debugger
529 if hasattr(self, 'pdb') and self.pdb is not None:
537 if hasattr(self, 'pdb') and self.pdb is not None:
530 self.pdb.set_colors(*args, **kw)
538 self.pdb.set_colors(*args, **kw)
531
539
532 def color_toggle(self):
540 def color_toggle(self):
533 """Toggle between the currently active color scheme and NoColor."""
541 """Toggle between the currently active color scheme and NoColor."""
534
542
535 if self.color_scheme_table.active_scheme_name == 'NoColor':
543 if self.color_scheme_table.active_scheme_name == 'NoColor':
536 self.color_scheme_table.set_active_scheme(self.old_scheme)
544 self.color_scheme_table.set_active_scheme(self.old_scheme)
537 self.Colors = self.color_scheme_table.active_colors
545 self.Colors = self.color_scheme_table.active_colors
538 else:
546 else:
539 self.old_scheme = self.color_scheme_table.active_scheme_name
547 self.old_scheme = self.color_scheme_table.active_scheme_name
540 self.color_scheme_table.set_active_scheme('NoColor')
548 self.color_scheme_table.set_active_scheme('NoColor')
541 self.Colors = self.color_scheme_table.active_colors
549 self.Colors = self.color_scheme_table.active_colors
542
550
543 def stb2text(self, stb):
551 def stb2text(self, stb):
544 """Convert a structured traceback (a list) to a string."""
552 """Convert a structured traceback (a list) to a string."""
545 return '\n'.join(stb)
553 return '\n'.join(stb)
546
554
547 def text(self, etype, value, tb, tb_offset=None, context=5):
555 def text(self, etype, value, tb, tb_offset=None, context=5):
548 """Return formatted traceback.
556 """Return formatted traceback.
549
557
550 Subclasses may override this if they add extra arguments.
558 Subclasses may override this if they add extra arguments.
551 """
559 """
552 tb_list = self.structured_traceback(etype, value, tb,
560 tb_list = self.structured_traceback(etype, value, tb,
553 tb_offset, context)
561 tb_offset, context)
554 return self.stb2text(tb_list)
562 return self.stb2text(tb_list)
555
563
556 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
564 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
557 context=5, mode=None):
565 context=5, mode=None):
558 """Return a list of traceback frames.
566 """Return a list of traceback frames.
559
567
560 Must be implemented by each class.
568 Must be implemented by each class.
561 """
569 """
562 raise NotImplementedError()
570 raise NotImplementedError()
563
571
564
572
565 #---------------------------------------------------------------------------
573 #---------------------------------------------------------------------------
566 class ListTB(TBTools):
574 class ListTB(TBTools):
567 """Print traceback information from a traceback list, with optional color.
575 """Print traceback information from a traceback list, with optional color.
568
576
569 Calling requires 3 arguments: (etype, evalue, elist)
577 Calling requires 3 arguments: (etype, evalue, elist)
570 as would be obtained by::
578 as would be obtained by::
571
579
572 etype, evalue, tb = sys.exc_info()
580 etype, evalue, tb = sys.exc_info()
573 if tb:
581 if tb:
574 elist = traceback.extract_tb(tb)
582 elist = traceback.extract_tb(tb)
575 else:
583 else:
576 elist = None
584 elist = None
577
585
578 It can thus be used by programs which need to process the traceback before
586 It can thus be used by programs which need to process the traceback before
579 printing (such as console replacements based on the code module from the
587 printing (such as console replacements based on the code module from the
580 standard library).
588 standard library).
581
589
582 Because they are meant to be called without a full traceback (only a
590 Because they are meant to be called without a full traceback (only a
583 list), instances of this class can't call the interactive pdb debugger."""
591 list), instances of this class can't call the interactive pdb debugger."""
584
592
585 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
593 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
586 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
594 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
587 ostream=ostream)
595 ostream=ostream)
588
596
589 def __call__(self, etype, value, elist):
597 def __call__(self, etype, value, elist):
590 self.ostream.flush()
598 self.ostream.flush()
591 self.ostream.write(self.text(etype, value, elist))
599 self.ostream.write(self.text(etype, value, elist))
592 self.ostream.write('\n')
600 self.ostream.write('\n')
593
601
594 def structured_traceback(self, etype, value, elist, tb_offset=None,
602 def structured_traceback(self, etype, value, elist, tb_offset=None,
595 context=5):
603 context=5):
596 """Return a color formatted string with the traceback info.
604 """Return a color formatted string with the traceback info.
597
605
598 Parameters
606 Parameters
599 ----------
607 ----------
600 etype : exception type
608 etype : exception type
601 Type of the exception raised.
609 Type of the exception raised.
602
610
603 value : object
611 value : object
604 Data stored in the exception
612 Data stored in the exception
605
613
606 elist : list
614 elist : list
607 List of frames, see class docstring for details.
615 List of frames, see class docstring for details.
608
616
609 tb_offset : int, optional
617 tb_offset : int, optional
610 Number of frames in the traceback to skip. If not given, the
618 Number of frames in the traceback to skip. If not given, the
611 instance value is used (set in constructor).
619 instance value is used (set in constructor).
612
620
613 context : int, optional
621 context : int, optional
614 Number of lines of context information to print.
622 Number of lines of context information to print.
615
623
616 Returns
624 Returns
617 -------
625 -------
618 String with formatted exception.
626 String with formatted exception.
619 """
627 """
620 tb_offset = self.tb_offset if tb_offset is None else tb_offset
628 tb_offset = self.tb_offset if tb_offset is None else tb_offset
621 Colors = self.Colors
629 Colors = self.Colors
622 out_list = []
630 out_list = []
623 if elist:
631 if elist:
624
632
625 if tb_offset and len(elist) > tb_offset:
633 if tb_offset and len(elist) > tb_offset:
626 elist = elist[tb_offset:]
634 elist = elist[tb_offset:]
627
635
628 out_list.append('Traceback %s(most recent call last)%s:' %
636 out_list.append('Traceback %s(most recent call last)%s:' %
629 (Colors.normalEm, Colors.Normal) + '\n')
637 (Colors.normalEm, Colors.Normal) + '\n')
630 out_list.extend(self._format_list(elist))
638 out_list.extend(self._format_list(elist))
631 # The exception info should be a single entry in the list.
639 # The exception info should be a single entry in the list.
632 lines = ''.join(self._format_exception_only(etype, value))
640 lines = ''.join(self._format_exception_only(etype, value))
633 out_list.append(lines)
641 out_list.append(lines)
634
642
635 # Note: this code originally read:
643 # Note: this code originally read:
636
644
637 ## for line in lines[:-1]:
645 ## for line in lines[:-1]:
638 ## out_list.append(" "+line)
646 ## out_list.append(" "+line)
639 ## out_list.append(lines[-1])
647 ## out_list.append(lines[-1])
640
648
641 # This means it was indenting everything but the last line by a little
649 # This means it was indenting everything but the last line by a little
642 # bit. I've disabled this for now, but if we see ugliness somewhere we
650 # bit. I've disabled this for now, but if we see ugliness somewhere we
643 # can restore it.
651 # can restore it.
644
652
645 return out_list
653 return out_list
646
654
647 def _format_list(self, extracted_list):
655 def _format_list(self, extracted_list):
648 """Format a list of traceback entry tuples for printing.
656 """Format a list of traceback entry tuples for printing.
649
657
650 Given a list of tuples as returned by extract_tb() or
658 Given a list of tuples as returned by extract_tb() or
651 extract_stack(), return a list of strings ready for printing.
659 extract_stack(), return a list of strings ready for printing.
652 Each string in the resulting list corresponds to the item with the
660 Each string in the resulting list corresponds to the item with the
653 same index in the argument list. Each string ends in a newline;
661 same index in the argument list. Each string ends in a newline;
654 the strings may contain internal newlines as well, for those items
662 the strings may contain internal newlines as well, for those items
655 whose source text line is not None.
663 whose source text line is not None.
656
664
657 Lifted almost verbatim from traceback.py
665 Lifted almost verbatim from traceback.py
658 """
666 """
659
667
660 Colors = self.Colors
668 Colors = self.Colors
661 list = []
669 list = []
662 for filename, lineno, name, line in extracted_list[:-1]:
670 for filename, lineno, name, line in extracted_list[:-1]:
663 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
671 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
664 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
672 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
665 Colors.lineno, lineno, Colors.Normal,
673 Colors.lineno, lineno, Colors.Normal,
666 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
674 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
667 if line:
675 if line:
668 item += ' %s\n' % line.strip()
676 item += ' %s\n' % line.strip()
669 list.append(item)
677 list.append(item)
670 # Emphasize the last entry
678 # Emphasize the last entry
671 filename, lineno, name, line = extracted_list[-1]
679 filename, lineno, name, line = extracted_list[-1]
672 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
680 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
673 (Colors.normalEm,
681 (Colors.normalEm,
674 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
682 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
675 Colors.linenoEm, lineno, Colors.normalEm,
683 Colors.linenoEm, lineno, Colors.normalEm,
676 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
684 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
677 Colors.Normal)
685 Colors.Normal)
678 if line:
686 if line:
679 item += '%s %s%s\n' % (Colors.line, line.strip(),
687 item += '%s %s%s\n' % (Colors.line, line.strip(),
680 Colors.Normal)
688 Colors.Normal)
681 list.append(item)
689 list.append(item)
682 return list
690 return list
683
691
684 def _format_exception_only(self, etype, value):
692 def _format_exception_only(self, etype, value):
685 """Format the exception part of a traceback.
693 """Format the exception part of a traceback.
686
694
687 The arguments are the exception type and value such as given by
695 The arguments are the exception type and value such as given by
688 sys.exc_info()[:2]. The return value is a list of strings, each ending
696 sys.exc_info()[:2]. The return value is a list of strings, each ending
689 in a newline. Normally, the list contains a single string; however,
697 in a newline. Normally, the list contains a single string; however,
690 for SyntaxError exceptions, it contains several lines that (when
698 for SyntaxError exceptions, it contains several lines that (when
691 printed) display detailed information about where the syntax error
699 printed) display detailed information about where the syntax error
692 occurred. The message indicating which exception occurred is the
700 occurred. The message indicating which exception occurred is the
693 always last string in the list.
701 always last string in the list.
694
702
695 Also lifted nearly verbatim from traceback.py
703 Also lifted nearly verbatim from traceback.py
696 """
704 """
697 have_filedata = False
705 have_filedata = False
698 Colors = self.Colors
706 Colors = self.Colors
699 list = []
707 list = []
700 stype = Colors.excName + etype.__name__ + Colors.Normal
708 stype = Colors.excName + etype.__name__ + Colors.Normal
701 if value is None:
709 if value is None:
702 # Not sure if this can still happen in Python 2.6 and above
710 # Not sure if this can still happen in Python 2.6 and above
703 list.append(py3compat.cast_unicode(stype) + '\n')
711 list.append(py3compat.cast_unicode(stype) + '\n')
704 else:
712 else:
705 if issubclass(etype, SyntaxError):
713 if issubclass(etype, SyntaxError):
706 have_filedata = True
714 have_filedata = True
707 if not value.filename: value.filename = "<string>"
715 if not value.filename: value.filename = "<string>"
708 if value.lineno:
716 if value.lineno:
709 lineno = value.lineno
717 lineno = value.lineno
710 textline = ulinecache.getline(value.filename, value.lineno)
718 textline = ulinecache.getline(value.filename, value.lineno)
711 else:
719 else:
712 lineno = 'unknown'
720 lineno = 'unknown'
713 textline = ''
721 textline = ''
714 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
722 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
715 (Colors.normalEm,
723 (Colors.normalEm,
716 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
724 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
717 Colors.linenoEm, lineno, Colors.Normal ))
725 Colors.linenoEm, lineno, Colors.Normal ))
718 if textline == '':
726 if textline == '':
719 textline = py3compat.cast_unicode(value.text, "utf-8")
727 textline = py3compat.cast_unicode(value.text, "utf-8")
720
728
721 if textline is not None:
729 if textline is not None:
722 i = 0
730 i = 0
723 while i < len(textline) and textline[i].isspace():
731 while i < len(textline) and textline[i].isspace():
724 i += 1
732 i += 1
725 list.append('%s %s%s\n' % (Colors.line,
733 list.append('%s %s%s\n' % (Colors.line,
726 textline.strip(),
734 textline.strip(),
727 Colors.Normal))
735 Colors.Normal))
728 if value.offset is not None:
736 if value.offset is not None:
729 s = ' '
737 s = ' '
730 for c in textline[i:value.offset - 1]:
738 for c in textline[i:value.offset - 1]:
731 if c.isspace():
739 if c.isspace():
732 s += c
740 s += c
733 else:
741 else:
734 s += ' '
742 s += ' '
735 list.append('%s%s^%s\n' % (Colors.caret, s,
743 list.append('%s%s^%s\n' % (Colors.caret, s,
736 Colors.Normal))
744 Colors.Normal))
737
745
738 try:
746 try:
739 s = value.msg
747 s = value.msg
740 except Exception:
748 except Exception:
741 s = self._some_str(value)
749 s = self._some_str(value)
742 if s:
750 if s:
743 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
751 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
744 Colors.Normal, s))
752 Colors.Normal, s))
745 else:
753 else:
746 list.append('%s\n' % str(stype))
754 list.append('%s\n' % str(stype))
747
755
748 # sync with user hooks
756 # sync with user hooks
749 if have_filedata:
757 if have_filedata:
750 ipinst = get_ipython()
758 ipinst = get_ipython()
751 if ipinst is not None:
759 if ipinst is not None:
752 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
760 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
753
761
754 return list
762 return list
755
763
756 def get_exception_only(self, etype, value):
764 def get_exception_only(self, etype, value):
757 """Only print the exception type and message, without a traceback.
765 """Only print the exception type and message, without a traceback.
758
766
759 Parameters
767 Parameters
760 ----------
768 ----------
761 etype : exception type
769 etype : exception type
762 value : exception value
770 value : exception value
763 """
771 """
764 return ListTB.structured_traceback(self, etype, value, [])
772 return ListTB.structured_traceback(self, etype, value, [])
765
773
766 def show_exception_only(self, etype, evalue):
774 def show_exception_only(self, etype, evalue):
767 """Only print the exception type and message, without a traceback.
775 """Only print the exception type and message, without a traceback.
768
776
769 Parameters
777 Parameters
770 ----------
778 ----------
771 etype : exception type
779 etype : exception type
772 value : exception value
780 value : exception value
773 """
781 """
774 # This method needs to use __call__ from *this* class, not the one from
782 # This method needs to use __call__ from *this* class, not the one from
775 # a subclass whose signature or behavior may be different
783 # a subclass whose signature or behavior may be different
776 ostream = self.ostream
784 ostream = self.ostream
777 ostream.flush()
785 ostream.flush()
778 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
786 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
779 ostream.flush()
787 ostream.flush()
780
788
781 def _some_str(self, value):
789 def _some_str(self, value):
782 # Lifted from traceback.py
790 # Lifted from traceback.py
783 try:
791 try:
784 return str(value)
792 return str(value)
785 except:
793 except:
786 return '<unprintable %s object>' % type(value).__name__
794 return '<unprintable %s object>' % type(value).__name__
787
795
788
796
789 #----------------------------------------------------------------------------
797 #----------------------------------------------------------------------------
790 class VerboseTB(TBTools):
798 class VerboseTB(TBTools):
791 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
799 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
792 of HTML. Requires inspect and pydoc. Crazy, man.
800 of HTML. Requires inspect and pydoc. Crazy, man.
793
801
794 Modified version which optionally strips the topmost entries from the
802 Modified version which optionally strips the topmost entries from the
795 traceback, to be used with alternate interpreters (because their own code
803 traceback, to be used with alternate interpreters (because their own code
796 would appear in the traceback)."""
804 would appear in the traceback)."""
797
805
798 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
806 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
799 tb_offset=0, long_header=False, include_vars=True,
807 tb_offset=0, long_header=False, include_vars=True,
800 check_cache=None):
808 check_cache=None):
801 """Specify traceback offset, headers and color scheme.
809 """Specify traceback offset, headers and color scheme.
802
810
803 Define how many frames to drop from the tracebacks. Calling it with
811 Define how many frames to drop from the tracebacks. Calling it with
804 tb_offset=1 allows use of this handler in interpreters which will have
812 tb_offset=1 allows use of this handler in interpreters which will have
805 their own code at the top of the traceback (VerboseTB will first
813 their own code at the top of the traceback (VerboseTB will first
806 remove that frame before printing the traceback info)."""
814 remove that frame before printing the traceback info)."""
807 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
815 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
808 ostream=ostream)
816 ostream=ostream)
809 self.tb_offset = tb_offset
817 self.tb_offset = tb_offset
810 self.long_header = long_header
818 self.long_header = long_header
811 self.include_vars = include_vars
819 self.include_vars = include_vars
812 # By default we use linecache.checkcache, but the user can provide a
820 # By default we use linecache.checkcache, but the user can provide a
813 # different check_cache implementation. This is used by the IPython
821 # different check_cache implementation. This is used by the IPython
814 # kernel to provide tracebacks for interactive code that is cached,
822 # kernel to provide tracebacks for interactive code that is cached,
815 # by a compiler instance that flushes the linecache but preserves its
823 # by a compiler instance that flushes the linecache but preserves its
816 # own code cache.
824 # own code cache.
817 if check_cache is None:
825 if check_cache is None:
818 check_cache = linecache.checkcache
826 check_cache = linecache.checkcache
819 self.check_cache = check_cache
827 self.check_cache = check_cache
820
828
821 def format_records(self, records, last_unique, recursion_repeat):
829 def format_records(self, records, last_unique, recursion_repeat):
822 """Format the stack frames of the traceback"""
830 """Format the stack frames of the traceback"""
823 frames = []
831 frames = []
824 for r in records[:last_unique+recursion_repeat+1]:
832 for r in records[:last_unique+recursion_repeat+1]:
825 #print '*** record:',file,lnum,func,lines,index # dbg
833 #print '*** record:',file,lnum,func,lines,index # dbg
826 frames.append(self.format_record(*r))
834 frames.append(self.format_record(*r))
827
835
828 if recursion_repeat:
836 if recursion_repeat:
829 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
837 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
830 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
838 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
831
839
832 return frames
840 return frames
833
841
834 def format_record(self, frame, file, lnum, func, lines, index):
842 def format_record(self, frame, file, lnum, func, lines, index):
835 """Format a single stack frame"""
843 """Format a single stack frame"""
836 Colors = self.Colors # just a shorthand + quicker name lookup
844 Colors = self.Colors # just a shorthand + quicker name lookup
837 ColorsNormal = Colors.Normal # used a lot
845 ColorsNormal = Colors.Normal # used a lot
838 col_scheme = self.color_scheme_table.active_scheme_name
846 col_scheme = self.color_scheme_table.active_scheme_name
839 indent = ' ' * INDENT_SIZE
847 indent = ' ' * INDENT_SIZE
840 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
848 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
841 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
849 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
842 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
850 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
843 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
851 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
844 ColorsNormal)
852 ColorsNormal)
845 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
853 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
846 (Colors.vName, Colors.valEm, ColorsNormal)
854 (Colors.vName, Colors.valEm, ColorsNormal)
847 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
855 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
848 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
856 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
849 Colors.vName, ColorsNormal)
857 Colors.vName, ColorsNormal)
850 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
858 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
851
859
852 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
860 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
853 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
861 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
854 ColorsNormal)
862 ColorsNormal)
855
863
856 abspath = os.path.abspath
864 abspath = os.path.abspath
857
865
858
866
859 if not file:
867 if not file:
860 file = '?'
868 file = '?'
861 elif file.startswith(str("<")) and file.endswith(str(">")):
869 elif file.startswith(str("<")) and file.endswith(str(">")):
862 # Not a real filename, no problem...
870 # Not a real filename, no problem...
863 pass
871 pass
864 elif not os.path.isabs(file):
872 elif not os.path.isabs(file):
865 # Try to make the filename absolute by trying all
873 # Try to make the filename absolute by trying all
866 # sys.path entries (which is also what linecache does)
874 # sys.path entries (which is also what linecache does)
867 for dirname in sys.path:
875 for dirname in sys.path:
868 try:
876 try:
869 fullname = os.path.join(dirname, file)
877 fullname = os.path.join(dirname, file)
870 if os.path.isfile(fullname):
878 if os.path.isfile(fullname):
871 file = os.path.abspath(fullname)
879 file = os.path.abspath(fullname)
872 break
880 break
873 except Exception:
881 except Exception:
874 # Just in case that sys.path contains very
882 # Just in case that sys.path contains very
875 # strange entries...
883 # strange entries...
876 pass
884 pass
877
885
878 file = py3compat.cast_unicode(file, util_path.fs_encoding)
886 file = py3compat.cast_unicode(file, util_path.fs_encoding)
879 link = tpl_link % file
887 link = tpl_link % file
880 args, varargs, varkw, locals = fixed_getargvalues(frame)
888 args, varargs, varkw, locals = fixed_getargvalues(frame)
881
889
882 if func == '?':
890 if func == '?':
883 call = ''
891 call = ''
884 else:
892 else:
885 # Decide whether to include variable details or not
893 # Decide whether to include variable details or not
886 var_repr = self.include_vars and eqrepr or nullrepr
894 var_repr = self.include_vars and eqrepr or nullrepr
887 try:
895 try:
888 call = tpl_call % (func, inspect.formatargvalues(args,
896 call = tpl_call % (func, inspect.formatargvalues(args,
889 varargs, varkw,
897 varargs, varkw,
890 locals, formatvalue=var_repr))
898 locals, formatvalue=var_repr))
891 except KeyError:
899 except KeyError:
892 # This happens in situations like errors inside generator
900 # This happens in situations like errors inside generator
893 # expressions, where local variables are listed in the
901 # expressions, where local variables are listed in the
894 # line, but can't be extracted from the frame. I'm not
902 # line, but can't be extracted from the frame. I'm not
895 # 100% sure this isn't actually a bug in inspect itself,
903 # 100% sure this isn't actually a bug in inspect itself,
896 # but since there's no info for us to compute with, the
904 # but since there's no info for us to compute with, the
897 # best we can do is report the failure and move on. Here
905 # best we can do is report the failure and move on. Here
898 # we must *not* call any traceback construction again,
906 # we must *not* call any traceback construction again,
899 # because that would mess up use of %debug later on. So we
907 # because that would mess up use of %debug later on. So we
900 # simply report the failure and move on. The only
908 # simply report the failure and move on. The only
901 # limitation will be that this frame won't have locals
909 # limitation will be that this frame won't have locals
902 # listed in the call signature. Quite subtle problem...
910 # listed in the call signature. Quite subtle problem...
903 # I can't think of a good way to validate this in a unit
911 # I can't think of a good way to validate this in a unit
904 # test, but running a script consisting of:
912 # test, but running a script consisting of:
905 # dict( (k,v.strip()) for (k,v) in range(10) )
913 # dict( (k,v.strip()) for (k,v) in range(10) )
906 # will illustrate the error, if this exception catch is
914 # will illustrate the error, if this exception catch is
907 # disabled.
915 # disabled.
908 call = tpl_call_fail % func
916 call = tpl_call_fail % func
909
917
910 # Don't attempt to tokenize binary files.
918 # Don't attempt to tokenize binary files.
911 if file.endswith(('.so', '.pyd', '.dll')):
919 if file.endswith(('.so', '.pyd', '.dll')):
912 return '%s %s\n' % (link, call)
920 return '%s %s\n' % (link, call)
913
921
914 elif file.endswith(('.pyc', '.pyo')):
922 elif file.endswith(('.pyc', '.pyo')):
915 # Look up the corresponding source file.
923 # Look up the corresponding source file.
916 file = openpy.source_from_cache(file)
924 file = openpy.source_from_cache(file)
917
925
918 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
926 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
919 line = getline(file, lnum[0])
927 line = getline(file, lnum[0])
920 lnum[0] += 1
928 lnum[0] += 1
921 return line
929 return line
922
930
923 # Build the list of names on this line of code where the exception
931 # Build the list of names on this line of code where the exception
924 # occurred.
932 # occurred.
925 try:
933 try:
926 names = []
934 names = []
927 name_cont = False
935 name_cont = False
928
936
929 for token_type, token, start, end, line in generate_tokens(linereader):
937 for token_type, token, start, end, line in generate_tokens(linereader):
930 # build composite names
938 # build composite names
931 if token_type == tokenize.NAME and token not in keyword.kwlist:
939 if token_type == tokenize.NAME and token not in keyword.kwlist:
932 if name_cont:
940 if name_cont:
933 # Continuation of a dotted name
941 # Continuation of a dotted name
934 try:
942 try:
935 names[-1].append(token)
943 names[-1].append(token)
936 except IndexError:
944 except IndexError:
937 names.append([token])
945 names.append([token])
938 name_cont = False
946 name_cont = False
939 else:
947 else:
940 # Regular new names. We append everything, the caller
948 # Regular new names. We append everything, the caller
941 # will be responsible for pruning the list later. It's
949 # will be responsible for pruning the list later. It's
942 # very tricky to try to prune as we go, b/c composite
950 # very tricky to try to prune as we go, b/c composite
943 # names can fool us. The pruning at the end is easy
951 # names can fool us. The pruning at the end is easy
944 # to do (or the caller can print a list with repeated
952 # to do (or the caller can print a list with repeated
945 # names if so desired.
953 # names if so desired.
946 names.append([token])
954 names.append([token])
947 elif token == '.':
955 elif token == '.':
948 name_cont = True
956 name_cont = True
949 elif token_type == tokenize.NEWLINE:
957 elif token_type == tokenize.NEWLINE:
950 break
958 break
951
959
952 except (IndexError, UnicodeDecodeError, SyntaxError):
960 except (IndexError, UnicodeDecodeError, SyntaxError):
953 # signals exit of tokenizer
961 # signals exit of tokenizer
954 # SyntaxError can occur if the file is not actually Python
962 # SyntaxError can occur if the file is not actually Python
955 # - see gh-6300
963 # - see gh-6300
956 pass
964 pass
957 except tokenize.TokenError as msg:
965 except tokenize.TokenError as msg:
958 _m = ("An unexpected error occurred while tokenizing input\n"
966 _m = ("An unexpected error occurred while tokenizing input\n"
959 "The following traceback may be corrupted or invalid\n"
967 "The following traceback may be corrupted or invalid\n"
960 "The error message is: %s\n" % msg)
968 "The error message is: %s\n" % msg)
961 error(_m)
969 error(_m)
962
970
963 # Join composite names (e.g. "dict.fromkeys")
971 # Join composite names (e.g. "dict.fromkeys")
964 names = ['.'.join(n) for n in names]
972 names = ['.'.join(n) for n in names]
965 # prune names list of duplicates, but keep the right order
973 # prune names list of duplicates, but keep the right order
966 unique_names = uniq_stable(names)
974 unique_names = uniq_stable(names)
967
975
968 # Start loop over vars
976 # Start loop over vars
969 lvals = []
977 lvals = []
970 if self.include_vars:
978 if self.include_vars:
971 for name_full in unique_names:
979 for name_full in unique_names:
972 name_base = name_full.split('.', 1)[0]
980 name_base = name_full.split('.', 1)[0]
973 if name_base in frame.f_code.co_varnames:
981 if name_base in frame.f_code.co_varnames:
974 if name_base in locals:
982 if name_base in locals:
975 try:
983 try:
976 value = repr(eval(name_full, locals))
984 value = repr(eval(name_full, locals))
977 except:
985 except:
978 value = undefined
986 value = undefined
979 else:
987 else:
980 value = undefined
988 value = undefined
981 name = tpl_local_var % name_full
989 name = tpl_local_var % name_full
982 else:
990 else:
983 if name_base in frame.f_globals:
991 if name_base in frame.f_globals:
984 try:
992 try:
985 value = repr(eval(name_full, frame.f_globals))
993 value = repr(eval(name_full, frame.f_globals))
986 except:
994 except:
987 value = undefined
995 value = undefined
988 else:
996 else:
989 value = undefined
997 value = undefined
990 name = tpl_global_var % name_full
998 name = tpl_global_var % name_full
991 lvals.append(tpl_name_val % (name, value))
999 lvals.append(tpl_name_val % (name, value))
992 if lvals:
1000 if lvals:
993 lvals = '%s%s' % (indent, em_normal.join(lvals))
1001 lvals = '%s%s' % (indent, em_normal.join(lvals))
994 else:
1002 else:
995 lvals = ''
1003 lvals = ''
996
1004
997 level = '%s %s\n' % (link, call)
1005 level = '%s %s\n' % (link, call)
998
1006
999 if index is None:
1007 if index is None:
1000 return level
1008 return level
1001 else:
1009 else:
1002 return '%s%s' % (level, ''.join(
1010 return '%s%s' % (level, ''.join(
1003 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1011 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1004 col_scheme)))
1012 col_scheme)))
1005
1013
1006 def prepare_chained_exception_message(self, cause):
1014 def prepare_chained_exception_message(self, cause):
1007 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1015 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1008 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1016 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1009
1017
1010 if cause:
1018 if cause:
1011 message = [[direct_cause]]
1019 message = [[direct_cause]]
1012 else:
1020 else:
1013 message = [[exception_during_handling]]
1021 message = [[exception_during_handling]]
1014 return message
1022 return message
1015
1023
1016 def prepare_header(self, etype, long_version=False):
1024 def prepare_header(self, etype, long_version=False):
1017 colors = self.Colors # just a shorthand + quicker name lookup
1025 colors = self.Colors # just a shorthand + quicker name lookup
1018 colorsnormal = colors.Normal # used a lot
1026 colorsnormal = colors.Normal # used a lot
1019 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1027 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1020 if long_version:
1028 if long_version:
1021 # Header with the exception type, python version, and date
1029 # Header with the exception type, python version, and date
1022 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1030 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1023 date = time.ctime(time.time())
1031 date = time.ctime(time.time())
1024
1032
1025 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
1033 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
1026 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
1034 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
1027 pyver, date.rjust(75) )
1035 pyver, date.rjust(75) )
1028 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1036 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1029 "\ncalls leading up to the error, with the most recent (innermost) call last."
1037 "\ncalls leading up to the error, with the most recent (innermost) call last."
1030 else:
1038 else:
1031 # Simplified header
1039 # Simplified header
1032 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1040 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1033 rjust(75 - len(str(etype))) )
1041 rjust(75 - len(str(etype))) )
1034
1042
1035 return head
1043 return head
1036
1044
1037 def format_exception(self, etype, evalue):
1045 def format_exception(self, etype, evalue):
1038 colors = self.Colors # just a shorthand + quicker name lookup
1046 colors = self.Colors # just a shorthand + quicker name lookup
1039 colorsnormal = colors.Normal # used a lot
1047 colorsnormal = colors.Normal # used a lot
1040 indent = ' ' * INDENT_SIZE
1048 indent = ' ' * INDENT_SIZE
1041 # Get (safely) a string form of the exception info
1049 # Get (safely) a string form of the exception info
1042 try:
1050 try:
1043 etype_str, evalue_str = map(str, (etype, evalue))
1051 etype_str, evalue_str = map(str, (etype, evalue))
1044 except:
1052 except:
1045 # User exception is improperly defined.
1053 # User exception is improperly defined.
1046 etype, evalue = str, sys.exc_info()[:2]
1054 etype, evalue = str, sys.exc_info()[:2]
1047 etype_str, evalue_str = map(str, (etype, evalue))
1055 etype_str, evalue_str = map(str, (etype, evalue))
1048 # ... and format it
1056 # ... and format it
1049 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1057 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1050 colorsnormal, py3compat.cast_unicode(evalue_str))]
1058 colorsnormal, py3compat.cast_unicode(evalue_str))]
1051
1059
1052 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1060 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1053 try:
1061 try:
1054 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1062 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1055 except:
1063 except:
1056 # Every now and then, an object with funny internals blows up
1064 # Every now and then, an object with funny internals blows up
1057 # when dir() is called on it. We do the best we can to report
1065 # when dir() is called on it. We do the best we can to report
1058 # the problem and continue
1066 # the problem and continue
1059 _m = '%sException reporting error (object with broken dir())%s:'
1067 _m = '%sException reporting error (object with broken dir())%s:'
1060 exception.append(_m % (colors.excName, colorsnormal))
1068 exception.append(_m % (colors.excName, colorsnormal))
1061 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1069 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1062 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1070 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1063 colorsnormal, py3compat.cast_unicode(evalue_str)))
1071 colorsnormal, py3compat.cast_unicode(evalue_str)))
1064 names = []
1072 names = []
1065 for name in names:
1073 for name in names:
1066 value = text_repr(getattr(evalue, name))
1074 value = text_repr(getattr(evalue, name))
1067 exception.append('\n%s%s = %s' % (indent, name, value))
1075 exception.append('\n%s%s = %s' % (indent, name, value))
1068
1076
1069 return exception
1077 return exception
1070
1078
1071 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1079 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1072 """Formats the header, traceback and exception message for a single exception.
1080 """Formats the header, traceback and exception message for a single exception.
1073
1081
1074 This may be called multiple times by Python 3 exception chaining
1082 This may be called multiple times by Python 3 exception chaining
1075 (PEP 3134).
1083 (PEP 3134).
1076 """
1084 """
1077 # some locals
1085 # some locals
1078 orig_etype = etype
1086 orig_etype = etype
1079 try:
1087 try:
1080 etype = etype.__name__
1088 etype = etype.__name__
1081 except AttributeError:
1089 except AttributeError:
1082 pass
1090 pass
1083
1091
1084 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1092 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1085 head = self.prepare_header(etype, self.long_header)
1093 head = self.prepare_header(etype, self.long_header)
1086 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1094 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1087
1095
1088 if records is None:
1096 if records is None:
1089 return ""
1097 return ""
1090
1098
1091 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1099 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1092
1100
1093 frames = self.format_records(records, last_unique, recursion_repeat)
1101 frames = self.format_records(records, last_unique, recursion_repeat)
1094
1102
1095 formatted_exception = self.format_exception(etype, evalue)
1103 formatted_exception = self.format_exception(etype, evalue)
1096 if records:
1104 if records:
1097 filepath, lnum = records[-1][1:3]
1105 filepath, lnum = records[-1][1:3]
1098 filepath = os.path.abspath(filepath)
1106 filepath = os.path.abspath(filepath)
1099 ipinst = get_ipython()
1107 ipinst = get_ipython()
1100 if ipinst is not None:
1108 if ipinst is not None:
1101 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1109 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1102
1110
1103 return [[head] + frames + [''.join(formatted_exception[0])]]
1111 return [[head] + frames + [''.join(formatted_exception[0])]]
1104
1112
1105 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1113 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1106 try:
1114 try:
1107 # Try the default getinnerframes and Alex's: Alex's fixes some
1115 # Try the default getinnerframes and Alex's: Alex's fixes some
1108 # problems, but it generates empty tracebacks for console errors
1116 # problems, but it generates empty tracebacks for console errors
1109 # (5 blanks lines) where none should be returned.
1117 # (5 blanks lines) where none should be returned.
1110 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1118 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1111 except:
1119 except:
1112 # FIXME: I've been getting many crash reports from python 2.3
1120 # FIXME: I've been getting many crash reports from python 2.3
1113 # users, traceable to inspect.py. If I can find a small test-case
1121 # users, traceable to inspect.py. If I can find a small test-case
1114 # to reproduce this, I should either write a better workaround or
1122 # to reproduce this, I should either write a better workaround or
1115 # file a bug report against inspect (if that's the real problem).
1123 # file a bug report against inspect (if that's the real problem).
1116 # So far, I haven't been able to find an isolated example to
1124 # So far, I haven't been able to find an isolated example to
1117 # reproduce the problem.
1125 # reproduce the problem.
1118 inspect_error()
1126 inspect_error()
1119 traceback.print_exc(file=self.ostream)
1127 traceback.print_exc(file=self.ostream)
1120 info('\nUnfortunately, your original traceback can not be constructed.\n')
1128 info('\nUnfortunately, your original traceback can not be constructed.\n')
1121 return None
1129 return None
1122
1130
1123 def get_parts_of_chained_exception(self, evalue):
1131 def get_parts_of_chained_exception(self, evalue):
1124 def get_chained_exception(exception_value):
1132 def get_chained_exception(exception_value):
1125 cause = getattr(exception_value, '__cause__', None)
1133 cause = getattr(exception_value, '__cause__', None)
1126 if cause:
1134 if cause:
1127 return cause
1135 return cause
1128 if getattr(exception_value, '__suppress_context__', False):
1136 if getattr(exception_value, '__suppress_context__', False):
1129 return None
1137 return None
1130 return getattr(exception_value, '__context__', None)
1138 return getattr(exception_value, '__context__', None)
1131
1139
1132 chained_evalue = get_chained_exception(evalue)
1140 chained_evalue = get_chained_exception(evalue)
1133
1141
1134 if chained_evalue:
1142 if chained_evalue:
1135 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1143 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1136
1144
1137 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1145 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1138 number_of_lines_of_context=5):
1146 number_of_lines_of_context=5):
1139 """Return a nice text document describing the traceback."""
1147 """Return a nice text document describing the traceback."""
1140
1148
1141 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1149 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1142 tb_offset)
1150 tb_offset)
1143
1151
1144 colors = self.Colors # just a shorthand + quicker name lookup
1152 colors = self.Colors # just a shorthand + quicker name lookup
1145 colorsnormal = colors.Normal # used a lot
1153 colorsnormal = colors.Normal # used a lot
1146 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
1154 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
1147 structured_traceback_parts = [head]
1155 structured_traceback_parts = [head]
1148 if py3compat.PY3:
1156 if py3compat.PY3:
1149 chained_exceptions_tb_offset = 0
1157 chained_exceptions_tb_offset = 0
1150 lines_of_context = 3
1158 lines_of_context = 3
1151 formatted_exceptions = formatted_exception
1159 formatted_exceptions = formatted_exception
1152 exception = self.get_parts_of_chained_exception(evalue)
1160 exception = self.get_parts_of_chained_exception(evalue)
1153 if exception:
1161 if exception:
1154 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1162 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1155 etype, evalue, etb = exception
1163 etype, evalue, etb = exception
1156 else:
1164 else:
1157 evalue = None
1165 evalue = None
1158 chained_exc_ids = set()
1166 chained_exc_ids = set()
1159 while evalue:
1167 while evalue:
1160 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1168 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1161 chained_exceptions_tb_offset)
1169 chained_exceptions_tb_offset)
1162 exception = self.get_parts_of_chained_exception(evalue)
1170 exception = self.get_parts_of_chained_exception(evalue)
1163
1171
1164 if exception and not id(exception[1]) in chained_exc_ids:
1172 if exception and not id(exception[1]) in chained_exc_ids:
1165 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1173 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1166 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1174 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1167 etype, evalue, etb = exception
1175 etype, evalue, etb = exception
1168 else:
1176 else:
1169 evalue = None
1177 evalue = None
1170
1178
1171 # we want to see exceptions in a reversed order:
1179 # we want to see exceptions in a reversed order:
1172 # the first exception should be on top
1180 # the first exception should be on top
1173 for formatted_exception in reversed(formatted_exceptions):
1181 for formatted_exception in reversed(formatted_exceptions):
1174 structured_traceback_parts += formatted_exception
1182 structured_traceback_parts += formatted_exception
1175 else:
1183 else:
1176 structured_traceback_parts += formatted_exception[0]
1184 structured_traceback_parts += formatted_exception[0]
1177
1185
1178 return structured_traceback_parts
1186 return structured_traceback_parts
1179
1187
1180 def debugger(self, force=False):
1188 def debugger(self, force=False):
1181 """Call up the pdb debugger if desired, always clean up the tb
1189 """Call up the pdb debugger if desired, always clean up the tb
1182 reference.
1190 reference.
1183
1191
1184 Keywords:
1192 Keywords:
1185
1193
1186 - force(False): by default, this routine checks the instance call_pdb
1194 - force(False): by default, this routine checks the instance call_pdb
1187 flag and does not actually invoke the debugger if the flag is false.
1195 flag and does not actually invoke the debugger if the flag is false.
1188 The 'force' option forces the debugger to activate even if the flag
1196 The 'force' option forces the debugger to activate even if the flag
1189 is false.
1197 is false.
1190
1198
1191 If the call_pdb flag is set, the pdb interactive debugger is
1199 If the call_pdb flag is set, the pdb interactive debugger is
1192 invoked. In all cases, the self.tb reference to the current traceback
1200 invoked. In all cases, the self.tb reference to the current traceback
1193 is deleted to prevent lingering references which hamper memory
1201 is deleted to prevent lingering references which hamper memory
1194 management.
1202 management.
1195
1203
1196 Note that each call to pdb() does an 'import readline', so if your app
1204 Note that each call to pdb() does an 'import readline', so if your app
1197 requires a special setup for the readline completers, you'll have to
1205 requires a special setup for the readline completers, you'll have to
1198 fix that by hand after invoking the exception handler."""
1206 fix that by hand after invoking the exception handler."""
1199
1207
1200 if force or self.call_pdb:
1208 if force or self.call_pdb:
1201 if self.pdb is None:
1209 if self.pdb is None:
1202 self.pdb = debugger.Pdb(
1210 self.pdb = debugger.Pdb(
1203 self.color_scheme_table.active_scheme_name)
1211 self.color_scheme_table.active_scheme_name)
1204 # the system displayhook may have changed, restore the original
1212 # the system displayhook may have changed, restore the original
1205 # for pdb
1213 # for pdb
1206 display_trap = DisplayTrap(hook=sys.__displayhook__)
1214 display_trap = DisplayTrap(hook=sys.__displayhook__)
1207 with display_trap:
1215 with display_trap:
1208 self.pdb.reset()
1216 self.pdb.reset()
1209 # Find the right frame so we don't pop up inside ipython itself
1217 # Find the right frame so we don't pop up inside ipython itself
1210 if hasattr(self, 'tb') and self.tb is not None:
1218 if hasattr(self, 'tb') and self.tb is not None:
1211 etb = self.tb
1219 etb = self.tb
1212 else:
1220 else:
1213 etb = self.tb = sys.last_traceback
1221 etb = self.tb = sys.last_traceback
1214 while self.tb is not None and self.tb.tb_next is not None:
1222 while self.tb is not None and self.tb.tb_next is not None:
1215 self.tb = self.tb.tb_next
1223 self.tb = self.tb.tb_next
1216 if etb and etb.tb_next:
1224 if etb and etb.tb_next:
1217 etb = etb.tb_next
1225 etb = etb.tb_next
1218 self.pdb.botframe = etb.tb_frame
1226 self.pdb.botframe = etb.tb_frame
1219 self.pdb.interaction(self.tb.tb_frame, self.tb)
1227 self.pdb.interaction(self.tb.tb_frame, self.tb)
1220
1228
1221 if hasattr(self, 'tb'):
1229 if hasattr(self, 'tb'):
1222 del self.tb
1230 del self.tb
1223
1231
1224 def handler(self, info=None):
1232 def handler(self, info=None):
1225 (etype, evalue, etb) = info or sys.exc_info()
1233 (etype, evalue, etb) = info or sys.exc_info()
1226 self.tb = etb
1234 self.tb = etb
1227 ostream = self.ostream
1235 ostream = self.ostream
1228 ostream.flush()
1236 ostream.flush()
1229 ostream.write(self.text(etype, evalue, etb))
1237 ostream.write(self.text(etype, evalue, etb))
1230 ostream.write('\n')
1238 ostream.write('\n')
1231 ostream.flush()
1239 ostream.flush()
1232
1240
1233 # Changed so an instance can just be called as VerboseTB_inst() and print
1241 # Changed so an instance can just be called as VerboseTB_inst() and print
1234 # out the right info on its own.
1242 # out the right info on its own.
1235 def __call__(self, etype=None, evalue=None, etb=None):
1243 def __call__(self, etype=None, evalue=None, etb=None):
1236 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1244 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1237 if etb is None:
1245 if etb is None:
1238 self.handler()
1246 self.handler()
1239 else:
1247 else:
1240 self.handler((etype, evalue, etb))
1248 self.handler((etype, evalue, etb))
1241 try:
1249 try:
1242 self.debugger()
1250 self.debugger()
1243 except KeyboardInterrupt:
1251 except KeyboardInterrupt:
1244 print("\nKeyboardInterrupt")
1252 print("\nKeyboardInterrupt")
1245
1253
1246
1254
1247 #----------------------------------------------------------------------------
1255 #----------------------------------------------------------------------------
1248 class FormattedTB(VerboseTB, ListTB):
1256 class FormattedTB(VerboseTB, ListTB):
1249 """Subclass ListTB but allow calling with a traceback.
1257 """Subclass ListTB but allow calling with a traceback.
1250
1258
1251 It can thus be used as a sys.excepthook for Python > 2.1.
1259 It can thus be used as a sys.excepthook for Python > 2.1.
1252
1260
1253 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1261 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1254
1262
1255 Allows a tb_offset to be specified. This is useful for situations where
1263 Allows a tb_offset to be specified. This is useful for situations where
1256 one needs to remove a number of topmost frames from the traceback (such as
1264 one needs to remove a number of topmost frames from the traceback (such as
1257 occurs with python programs that themselves execute other python code,
1265 occurs with python programs that themselves execute other python code,
1258 like Python shells). """
1266 like Python shells). """
1259
1267
1260 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1268 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1261 ostream=None,
1269 ostream=None,
1262 tb_offset=0, long_header=False, include_vars=False,
1270 tb_offset=0, long_header=False, include_vars=False,
1263 check_cache=None):
1271 check_cache=None):
1264
1272
1265 # NEVER change the order of this list. Put new modes at the end:
1273 # NEVER change the order of this list. Put new modes at the end:
1266 self.valid_modes = ['Plain', 'Context', 'Verbose']
1274 self.valid_modes = ['Plain', 'Context', 'Verbose']
1267 self.verbose_modes = self.valid_modes[1:3]
1275 self.verbose_modes = self.valid_modes[1:3]
1268
1276
1269 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1277 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1270 ostream=ostream, tb_offset=tb_offset,
1278 ostream=ostream, tb_offset=tb_offset,
1271 long_header=long_header, include_vars=include_vars,
1279 long_header=long_header, include_vars=include_vars,
1272 check_cache=check_cache)
1280 check_cache=check_cache)
1273
1281
1274 # Different types of tracebacks are joined with different separators to
1282 # Different types of tracebacks are joined with different separators to
1275 # form a single string. They are taken from this dict
1283 # form a single string. They are taken from this dict
1276 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1284 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1277 # set_mode also sets the tb_join_char attribute
1285 # set_mode also sets the tb_join_char attribute
1278 self.set_mode(mode)
1286 self.set_mode(mode)
1279
1287
1280 def _extract_tb(self, tb):
1288 def _extract_tb(self, tb):
1281 if tb:
1289 if tb:
1282 return traceback.extract_tb(tb)
1290 return traceback.extract_tb(tb)
1283 else:
1291 else:
1284 return None
1292 return None
1285
1293
1286 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1294 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1287 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1295 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1288 mode = self.mode
1296 mode = self.mode
1289 if mode in self.verbose_modes:
1297 if mode in self.verbose_modes:
1290 # Verbose modes need a full traceback
1298 # Verbose modes need a full traceback
1291 return VerboseTB.structured_traceback(
1299 return VerboseTB.structured_traceback(
1292 self, etype, value, tb, tb_offset, number_of_lines_of_context
1300 self, etype, value, tb, tb_offset, number_of_lines_of_context
1293 )
1301 )
1294 else:
1302 else:
1295 # We must check the source cache because otherwise we can print
1303 # We must check the source cache because otherwise we can print
1296 # out-of-date source code.
1304 # out-of-date source code.
1297 self.check_cache()
1305 self.check_cache()
1298 # Now we can extract and format the exception
1306 # Now we can extract and format the exception
1299 elist = self._extract_tb(tb)
1307 elist = self._extract_tb(tb)
1300 return ListTB.structured_traceback(
1308 return ListTB.structured_traceback(
1301 self, etype, value, elist, tb_offset, number_of_lines_of_context
1309 self, etype, value, elist, tb_offset, number_of_lines_of_context
1302 )
1310 )
1303
1311
1304 def stb2text(self, stb):
1312 def stb2text(self, stb):
1305 """Convert a structured traceback (a list) to a string."""
1313 """Convert a structured traceback (a list) to a string."""
1306 return self.tb_join_char.join(stb)
1314 return self.tb_join_char.join(stb)
1307
1315
1308
1316
1309 def set_mode(self, mode=None):
1317 def set_mode(self, mode=None):
1310 """Switch to the desired mode.
1318 """Switch to the desired mode.
1311
1319
1312 If mode is not specified, cycles through the available modes."""
1320 If mode is not specified, cycles through the available modes."""
1313
1321
1314 if not mode:
1322 if not mode:
1315 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1323 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1316 len(self.valid_modes)
1324 len(self.valid_modes)
1317 self.mode = self.valid_modes[new_idx]
1325 self.mode = self.valid_modes[new_idx]
1318 elif mode not in self.valid_modes:
1326 elif mode not in self.valid_modes:
1319 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1327 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1320 'Valid modes: ' + str(self.valid_modes))
1328 'Valid modes: ' + str(self.valid_modes))
1321 else:
1329 else:
1322 self.mode = mode
1330 self.mode = mode
1323 # include variable details only in 'Verbose' mode
1331 # include variable details only in 'Verbose' mode
1324 self.include_vars = (self.mode == self.valid_modes[2])
1332 self.include_vars = (self.mode == self.valid_modes[2])
1325 # Set the join character for generating text tracebacks
1333 # Set the join character for generating text tracebacks
1326 self.tb_join_char = self._join_chars[self.mode]
1334 self.tb_join_char = self._join_chars[self.mode]
1327
1335
1328 # some convenient shortcuts
1336 # some convenient shortcuts
1329 def plain(self):
1337 def plain(self):
1330 self.set_mode(self.valid_modes[0])
1338 self.set_mode(self.valid_modes[0])
1331
1339
1332 def context(self):
1340 def context(self):
1333 self.set_mode(self.valid_modes[1])
1341 self.set_mode(self.valid_modes[1])
1334
1342
1335 def verbose(self):
1343 def verbose(self):
1336 self.set_mode(self.valid_modes[2])
1344 self.set_mode(self.valid_modes[2])
1337
1345
1338
1346
1339 #----------------------------------------------------------------------------
1347 #----------------------------------------------------------------------------
1340 class AutoFormattedTB(FormattedTB):
1348 class AutoFormattedTB(FormattedTB):
1341 """A traceback printer which can be called on the fly.
1349 """A traceback printer which can be called on the fly.
1342
1350
1343 It will find out about exceptions by itself.
1351 It will find out about exceptions by itself.
1344
1352
1345 A brief example::
1353 A brief example::
1346
1354
1347 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1355 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1348 try:
1356 try:
1349 ...
1357 ...
1350 except:
1358 except:
1351 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1359 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1352 """
1360 """
1353
1361
1354 def __call__(self, etype=None, evalue=None, etb=None,
1362 def __call__(self, etype=None, evalue=None, etb=None,
1355 out=None, tb_offset=None):
1363 out=None, tb_offset=None):
1356 """Print out a formatted exception traceback.
1364 """Print out a formatted exception traceback.
1357
1365
1358 Optional arguments:
1366 Optional arguments:
1359 - out: an open file-like object to direct output to.
1367 - out: an open file-like object to direct output to.
1360
1368
1361 - tb_offset: the number of frames to skip over in the stack, on a
1369 - tb_offset: the number of frames to skip over in the stack, on a
1362 per-call basis (this overrides temporarily the instance's tb_offset
1370 per-call basis (this overrides temporarily the instance's tb_offset
1363 given at initialization time. """
1371 given at initialization time. """
1364
1372
1365 if out is None:
1373 if out is None:
1366 out = self.ostream
1374 out = self.ostream
1367 out.flush()
1375 out.flush()
1368 out.write(self.text(etype, evalue, etb, tb_offset))
1376 out.write(self.text(etype, evalue, etb, tb_offset))
1369 out.write('\n')
1377 out.write('\n')
1370 out.flush()
1378 out.flush()
1371 # FIXME: we should remove the auto pdb behavior from here and leave
1379 # FIXME: we should remove the auto pdb behavior from here and leave
1372 # that to the clients.
1380 # that to the clients.
1373 try:
1381 try:
1374 self.debugger()
1382 self.debugger()
1375 except KeyboardInterrupt:
1383 except KeyboardInterrupt:
1376 print("\nKeyboardInterrupt")
1384 print("\nKeyboardInterrupt")
1377
1385
1378 def structured_traceback(self, etype=None, value=None, tb=None,
1386 def structured_traceback(self, etype=None, value=None, tb=None,
1379 tb_offset=None, number_of_lines_of_context=5):
1387 tb_offset=None, number_of_lines_of_context=5):
1380 if etype is None:
1388 if etype is None:
1381 etype, value, tb = sys.exc_info()
1389 etype, value, tb = sys.exc_info()
1382 self.tb = tb
1390 self.tb = tb
1383 return FormattedTB.structured_traceback(
1391 return FormattedTB.structured_traceback(
1384 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1392 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1385
1393
1386
1394
1387 #---------------------------------------------------------------------------
1395 #---------------------------------------------------------------------------
1388
1396
1389 # A simple class to preserve Nathan's original functionality.
1397 # A simple class to preserve Nathan's original functionality.
1390 class ColorTB(FormattedTB):
1398 class ColorTB(FormattedTB):
1391 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1399 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1392
1400
1393 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1401 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1394 FormattedTB.__init__(self, color_scheme=color_scheme,
1402 FormattedTB.__init__(self, color_scheme=color_scheme,
1395 call_pdb=call_pdb, **kwargs)
1403 call_pdb=call_pdb, **kwargs)
1396
1404
1397
1405
1398 class SyntaxTB(ListTB):
1406 class SyntaxTB(ListTB):
1399 """Extension which holds some state: the last exception value"""
1407 """Extension which holds some state: the last exception value"""
1400
1408
1401 def __init__(self, color_scheme='NoColor'):
1409 def __init__(self, color_scheme='NoColor'):
1402 ListTB.__init__(self, color_scheme)
1410 ListTB.__init__(self, color_scheme)
1403 self.last_syntax_error = None
1411 self.last_syntax_error = None
1404
1412
1405 def __call__(self, etype, value, elist):
1413 def __call__(self, etype, value, elist):
1406 self.last_syntax_error = value
1414 self.last_syntax_error = value
1407
1415
1408 ListTB.__call__(self, etype, value, elist)
1416 ListTB.__call__(self, etype, value, elist)
1409
1417
1410 def structured_traceback(self, etype, value, elist, tb_offset=None,
1418 def structured_traceback(self, etype, value, elist, tb_offset=None,
1411 context=5):
1419 context=5):
1412 # If the source file has been edited, the line in the syntax error can
1420 # If the source file has been edited, the line in the syntax error can
1413 # be wrong (retrieved from an outdated cache). This replaces it with
1421 # be wrong (retrieved from an outdated cache). This replaces it with
1414 # the current value.
1422 # the current value.
1415 if isinstance(value, SyntaxError) \
1423 if isinstance(value, SyntaxError) \
1416 and isinstance(value.filename, py3compat.string_types) \
1424 and isinstance(value.filename, py3compat.string_types) \
1417 and isinstance(value.lineno, int):
1425 and isinstance(value.lineno, int):
1418 linecache.checkcache(value.filename)
1426 linecache.checkcache(value.filename)
1419 newtext = ulinecache.getline(value.filename, value.lineno)
1427 newtext = ulinecache.getline(value.filename, value.lineno)
1420 if newtext:
1428 if newtext:
1421 value.text = newtext
1429 value.text = newtext
1422 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1430 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1423 tb_offset=tb_offset, context=context)
1431 tb_offset=tb_offset, context=context)
1424
1432
1425 def clear_err_state(self):
1433 def clear_err_state(self):
1426 """Return the current error state and clear it"""
1434 """Return the current error state and clear it"""
1427 e = self.last_syntax_error
1435 e = self.last_syntax_error
1428 self.last_syntax_error = None
1436 self.last_syntax_error = None
1429 return e
1437 return e
1430
1438
1431 def stb2text(self, stb):
1439 def stb2text(self, stb):
1432 """Convert a structured traceback (a list) to a string."""
1440 """Convert a structured traceback (a list) to a string."""
1433 return ''.join(stb)
1441 return ''.join(stb)
1434
1442
1435
1443
1436 # some internal-use functions
1444 # some internal-use functions
1437 def text_repr(value):
1445 def text_repr(value):
1438 """Hopefully pretty robust repr equivalent."""
1446 """Hopefully pretty robust repr equivalent."""
1439 # this is pretty horrible but should always return *something*
1447 # this is pretty horrible but should always return *something*
1440 try:
1448 try:
1441 return pydoc.text.repr(value)
1449 return pydoc.text.repr(value)
1442 except KeyboardInterrupt:
1450 except KeyboardInterrupt:
1443 raise
1451 raise
1444 except:
1452 except:
1445 try:
1453 try:
1446 return repr(value)
1454 return repr(value)
1447 except KeyboardInterrupt:
1455 except KeyboardInterrupt:
1448 raise
1456 raise
1449 except:
1457 except:
1450 try:
1458 try:
1451 # all still in an except block so we catch
1459 # all still in an except block so we catch
1452 # getattr raising
1460 # getattr raising
1453 name = getattr(value, '__name__', None)
1461 name = getattr(value, '__name__', None)
1454 if name:
1462 if name:
1455 # ick, recursion
1463 # ick, recursion
1456 return text_repr(name)
1464 return text_repr(name)
1457 klass = getattr(value, '__class__', None)
1465 klass = getattr(value, '__class__', None)
1458 if klass:
1466 if klass:
1459 return '%s instance' % text_repr(klass)
1467 return '%s instance' % text_repr(klass)
1460 except KeyboardInterrupt:
1468 except KeyboardInterrupt:
1461 raise
1469 raise
1462 except:
1470 except:
1463 return 'UNRECOVERABLE REPR FAILURE'
1471 return 'UNRECOVERABLE REPR FAILURE'
1464
1472
1465
1473
1466 def eqrepr(value, repr=text_repr):
1474 def eqrepr(value, repr=text_repr):
1467 return '=%s' % repr(value)
1475 return '=%s' % repr(value)
1468
1476
1469
1477
1470 def nullrepr(value, repr=text_repr):
1478 def nullrepr(value, repr=text_repr):
1471 return ''
1479 return ''
General Comments 0
You need to be logged in to leave comments. Login now