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