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