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