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