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