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