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