##// END OF EJS Templates
Check user config to decide whether to use pygments
Alex Hall -
Show More
@@ -1,1051 +1,1063 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 unencrypted
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 inspect
93 93 import linecache
94 94 import pydoc
95 95 import sys
96 96 import time
97 97 import traceback
98 98
99 99 import stack_data
100 from pygments.formatters.terminal import TerminalFormatter
100 from pygments.formatters.terminal256 import Terminal256Formatter
101 101
102 102 # IPython's own modules
103 103 from IPython import get_ipython
104 104 from IPython.core import debugger
105 105 from IPython.core.display_trap import DisplayTrap
106 106 from IPython.core.excolors import exception_colors
107 107 from IPython.utils import path as util_path
108 108 from IPython.utils import py3compat
109 109 from IPython.utils.terminal import get_terminal_size
110 110
111 111 import IPython.utils.colorable as colorable
112 112
113 113 # Globals
114 114 # amount of space to put line numbers before verbose tracebacks
115 115 INDENT_SIZE = 8
116 116
117 117 # Default color scheme. This is used, for example, by the traceback
118 118 # formatter. When running in an actual IPython instance, the user's rc.colors
119 119 # value is used, but having a module global makes this functionality available
120 120 # to users of ultratb who are NOT running inside ipython.
121 121 DEFAULT_SCHEME = 'NoColor'
122 122
123 123 # ---------------------------------------------------------------------------
124 124 # Code begins
125 125
126 126 # Helper function -- largely belongs to VerboseTB, but we need the same
127 127 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
128 128 # can be recognized properly by ipython.el's py-traceback-line-re
129 129 # (SyntaxErrors have to be treated specially because they have no traceback)
130 130
131 131
132 def _format_traceback_lines(lines, Colors, lvals):
132 def _format_traceback_lines(lines, Colors, has_colors, lvals):
133 133 """
134 134 Format tracebacks lines with pointing arrow, leading numbers...
135 135
136 136 Parameters
137 137 ==========
138 138
139 139 lines: list[Line]
140 140 Colors:
141 141 ColorScheme used.
142 142 lvals: str
143 143 Values of local variables, already colored, to inject just after the error line.
144 144 """
145 145 numbers_width = INDENT_SIZE - 1
146 146 res = []
147 147
148 148 for stack_line in lines:
149 149 if stack_line is stack_data.LINE_GAP:
150 150 res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal))
151 151 continue
152 152
153 line = stack_line.render(pygmented=True).rstrip('\n') + '\n'
153 line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n'
154 154 lineno = stack_line.lineno
155 155 if stack_line.is_current:
156 156 # This is the line with the error
157 157 pad = numbers_width - len(str(lineno))
158 158 num = '%s%s' % (debugger.make_arrow(pad), str(lineno))
159 159 start_color = Colors.linenoEm
160 160 else:
161 161 num = '%*s' % (numbers_width, lineno)
162 162 start_color = Colors.lineno
163 163
164 164 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
165 165
166 166 res.append(line)
167 167 if lvals and stack_line.is_current:
168 168 res.append(lvals + '\n')
169 169 return res
170 170
171 171
172 172 #---------------------------------------------------------------------------
173 173 # Module classes
174 174 class TBTools(colorable.Colorable):
175 175 """Basic tools used by all traceback printer classes."""
176 176
177 177 # Number of frames to skip when reporting tracebacks
178 178 tb_offset = 0
179 179
180 180 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
181 181 # Whether to call the interactive pdb debugger after printing
182 182 # tracebacks or not
183 183 super(TBTools, self).__init__(parent=parent, config=config)
184 184 self.call_pdb = call_pdb
185 185
186 186 # Output stream to write to. Note that we store the original value in
187 187 # a private attribute and then make the public ostream a property, so
188 188 # that we can delay accessing sys.stdout until runtime. The way
189 189 # things are written now, the sys.stdout object is dynamically managed
190 190 # so a reference to it should NEVER be stored statically. This
191 191 # property approach confines this detail to a single location, and all
192 192 # subclasses can simply access self.ostream for writing.
193 193 self._ostream = ostream
194 194
195 195 # Create color table
196 196 self.color_scheme_table = exception_colors()
197 197
198 198 self.set_colors(color_scheme)
199 199 self.old_scheme = color_scheme # save initial value for toggles
200 200
201 201 if call_pdb:
202 202 self.pdb = debugger.Pdb()
203 203 else:
204 204 self.pdb = None
205 205
206 206 def _get_ostream(self):
207 207 """Output stream that exceptions are written to.
208 208
209 209 Valid values are:
210 210
211 211 - None: the default, which means that IPython will dynamically resolve
212 212 to sys.stdout. This ensures compatibility with most tools, including
213 213 Windows (where plain stdout doesn't recognize ANSI escapes).
214 214
215 215 - Any object with 'write' and 'flush' attributes.
216 216 """
217 217 return sys.stdout if self._ostream is None else self._ostream
218 218
219 219 def _set_ostream(self, val):
220 220 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
221 221 self._ostream = val
222 222
223 223 ostream = property(_get_ostream, _set_ostream)
224 224
225 225 def get_parts_of_chained_exception(self, evalue):
226 226 def get_chained_exception(exception_value):
227 227 cause = getattr(exception_value, '__cause__', None)
228 228 if cause:
229 229 return cause
230 230 if getattr(exception_value, '__suppress_context__', False):
231 231 return None
232 232 return getattr(exception_value, '__context__', None)
233 233
234 234 chained_evalue = get_chained_exception(evalue)
235 235
236 236 if chained_evalue:
237 237 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
238 238
239 239 def prepare_chained_exception_message(self, cause):
240 240 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
241 241 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
242 242
243 243 if cause:
244 244 message = [[direct_cause]]
245 245 else:
246 246 message = [[exception_during_handling]]
247 247 return message
248 248
249 @property
250 def has_colors(self):
251 return self.color_scheme_table.active_scheme_name.lower() != "nocolor"
252
249 253 def set_colors(self, *args, **kw):
250 254 """Shorthand access to the color table scheme selector method."""
251 255
252 256 # Set own color table
253 257 self.color_scheme_table.set_active_scheme(*args, **kw)
254 258 # for convenience, set Colors to the active scheme
255 259 self.Colors = self.color_scheme_table.active_colors
256 260 # Also set colors of debugger
257 261 if hasattr(self, 'pdb') and self.pdb is not None:
258 262 self.pdb.set_colors(*args, **kw)
259 263
260 264 def color_toggle(self):
261 265 """Toggle between the currently active color scheme and NoColor."""
262 266
263 267 if self.color_scheme_table.active_scheme_name == 'NoColor':
264 268 self.color_scheme_table.set_active_scheme(self.old_scheme)
265 269 self.Colors = self.color_scheme_table.active_colors
266 270 else:
267 271 self.old_scheme = self.color_scheme_table.active_scheme_name
268 272 self.color_scheme_table.set_active_scheme('NoColor')
269 273 self.Colors = self.color_scheme_table.active_colors
270 274
271 275 def stb2text(self, stb):
272 276 """Convert a structured traceback (a list) to a string."""
273 277 return '\n'.join(stb)
274 278
275 279 def text(self, etype, value, tb, tb_offset=None, context=5):
276 280 """Return formatted traceback.
277 281
278 282 Subclasses may override this if they add extra arguments.
279 283 """
280 284 tb_list = self.structured_traceback(etype, value, tb,
281 285 tb_offset, context)
282 286 return self.stb2text(tb_list)
283 287
284 288 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
285 289 context=5, mode=None):
286 290 """Return a list of traceback frames.
287 291
288 292 Must be implemented by each class.
289 293 """
290 294 raise NotImplementedError()
291 295
292 296
293 297 #---------------------------------------------------------------------------
294 298 class ListTB(TBTools):
295 299 """Print traceback information from a traceback list, with optional color.
296 300
297 301 Calling requires 3 arguments: (etype, evalue, elist)
298 302 as would be obtained by::
299 303
300 304 etype, evalue, tb = sys.exc_info()
301 305 if tb:
302 306 elist = traceback.extract_tb(tb)
303 307 else:
304 308 elist = None
305 309
306 310 It can thus be used by programs which need to process the traceback before
307 311 printing (such as console replacements based on the code module from the
308 312 standard library).
309 313
310 314 Because they are meant to be called without a full traceback (only a
311 315 list), instances of this class can't call the interactive pdb debugger."""
312 316
313 317 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
314 318 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
315 319 ostream=ostream, parent=parent,config=config)
316 320
317 321 def __call__(self, etype, value, elist):
318 322 self.ostream.flush()
319 323 self.ostream.write(self.text(etype, value, elist))
320 324 self.ostream.write('\n')
321 325
322 326 def _extract_tb(self, tb):
323 327 if tb:
324 328 return traceback.extract_tb(tb)
325 329 else:
326 330 return None
327 331
328 332 def structured_traceback(self, etype, evalue, etb=None, tb_offset=None,
329 333 context=5):
330 334 """Return a color formatted string with the traceback info.
331 335
332 336 Parameters
333 337 ----------
334 338 etype : exception type
335 339 Type of the exception raised.
336 340
337 341 evalue : object
338 342 Data stored in the exception
339 343
340 344 etb : object
341 345 If list: List of frames, see class docstring for details.
342 346 If Traceback: Traceback of the exception.
343 347
344 348 tb_offset : int, optional
345 349 Number of frames in the traceback to skip. If not given, the
346 350 instance evalue is used (set in constructor).
347 351
348 352 context : int, optional
349 353 Number of lines of context information to print.
350 354
351 355 Returns
352 356 -------
353 357 String with formatted exception.
354 358 """
355 359 # This is a workaround to get chained_exc_ids in recursive calls
356 360 # etb should not be a tuple if structured_traceback is not recursive
357 361 if isinstance(etb, tuple):
358 362 etb, chained_exc_ids = etb
359 363 else:
360 364 chained_exc_ids = set()
361 365
362 366 if isinstance(etb, list):
363 367 elist = etb
364 368 elif etb is not None:
365 369 elist = self._extract_tb(etb)
366 370 else:
367 371 elist = []
368 372 tb_offset = self.tb_offset if tb_offset is None else tb_offset
369 373 Colors = self.Colors
370 374 out_list = []
371 375 if elist:
372 376
373 377 if tb_offset and len(elist) > tb_offset:
374 378 elist = elist[tb_offset:]
375 379
376 380 out_list.append('Traceback %s(most recent call last)%s:' %
377 381 (Colors.normalEm, Colors.Normal) + '\n')
378 382 out_list.extend(self._format_list(elist))
379 383 # The exception info should be a single entry in the list.
380 384 lines = ''.join(self._format_exception_only(etype, evalue))
381 385 out_list.append(lines)
382 386
383 387 exception = self.get_parts_of_chained_exception(evalue)
384 388
385 389 if exception and not id(exception[1]) in chained_exc_ids:
386 390 chained_exception_message = self.prepare_chained_exception_message(
387 391 evalue.__cause__)[0]
388 392 etype, evalue, etb = exception
389 393 # Trace exception to avoid infinite 'cause' loop
390 394 chained_exc_ids.add(id(exception[1]))
391 395 chained_exceptions_tb_offset = 0
392 396 out_list = (
393 397 self.structured_traceback(
394 398 etype, evalue, (etb, chained_exc_ids),
395 399 chained_exceptions_tb_offset, context)
396 400 + chained_exception_message
397 401 + out_list)
398 402
399 403 return out_list
400 404
401 405 def _format_list(self, extracted_list):
402 406 """Format a list of traceback entry tuples for printing.
403 407
404 408 Given a list of tuples as returned by extract_tb() or
405 409 extract_stack(), return a list of strings ready for printing.
406 410 Each string in the resulting list corresponds to the item with the
407 411 same index in the argument list. Each string ends in a newline;
408 412 the strings may contain internal newlines as well, for those items
409 413 whose source text line is not None.
410 414
411 415 Lifted almost verbatim from traceback.py
412 416 """
413 417
414 418 Colors = self.Colors
415 419 list = []
416 420 for filename, lineno, name, line in extracted_list[:-1]:
417 421 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
418 422 (Colors.filename, filename, Colors.Normal,
419 423 Colors.lineno, lineno, Colors.Normal,
420 424 Colors.name, name, Colors.Normal)
421 425 if line:
422 426 item += ' %s\n' % line.strip()
423 427 list.append(item)
424 428 # Emphasize the last entry
425 429 filename, lineno, name, line = extracted_list[-1]
426 430 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
427 431 (Colors.normalEm,
428 432 Colors.filenameEm, filename, Colors.normalEm,
429 433 Colors.linenoEm, lineno, Colors.normalEm,
430 434 Colors.nameEm, name, Colors.normalEm,
431 435 Colors.Normal)
432 436 if line:
433 437 item += '%s %s%s\n' % (Colors.line, line.strip(),
434 438 Colors.Normal)
435 439 list.append(item)
436 440 return list
437 441
438 442 def _format_exception_only(self, etype, value):
439 443 """Format the exception part of a traceback.
440 444
441 445 The arguments are the exception type and value such as given by
442 446 sys.exc_info()[:2]. The return value is a list of strings, each ending
443 447 in a newline. Normally, the list contains a single string; however,
444 448 for SyntaxError exceptions, it contains several lines that (when
445 449 printed) display detailed information about where the syntax error
446 450 occurred. The message indicating which exception occurred is the
447 451 always last string in the list.
448 452
449 453 Also lifted nearly verbatim from traceback.py
450 454 """
451 455 have_filedata = False
452 456 Colors = self.Colors
453 457 list = []
454 458 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
455 459 if value is None:
456 460 # Not sure if this can still happen in Python 2.6 and above
457 461 list.append(stype + '\n')
458 462 else:
459 463 if issubclass(etype, SyntaxError):
460 464 have_filedata = True
461 465 if not value.filename: value.filename = "<string>"
462 466 if value.lineno:
463 467 lineno = value.lineno
464 468 textline = linecache.getline(value.filename, value.lineno)
465 469 else:
466 470 lineno = 'unknown'
467 471 textline = ''
468 472 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
469 473 (Colors.normalEm,
470 474 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
471 475 Colors.linenoEm, lineno, Colors.Normal ))
472 476 if textline == '':
473 477 textline = py3compat.cast_unicode(value.text, "utf-8")
474 478
475 479 if textline is not None:
476 480 i = 0
477 481 while i < len(textline) and textline[i].isspace():
478 482 i += 1
479 483 list.append('%s %s%s\n' % (Colors.line,
480 484 textline.strip(),
481 485 Colors.Normal))
482 486 if value.offset is not None:
483 487 s = ' '
484 488 for c in textline[i:value.offset - 1]:
485 489 if c.isspace():
486 490 s += c
487 491 else:
488 492 s += ' '
489 493 list.append('%s%s^%s\n' % (Colors.caret, s,
490 494 Colors.Normal))
491 495
492 496 try:
493 497 s = value.msg
494 498 except Exception:
495 499 s = self._some_str(value)
496 500 if s:
497 501 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
498 502 Colors.Normal, s))
499 503 else:
500 504 list.append('%s\n' % stype)
501 505
502 506 # sync with user hooks
503 507 if have_filedata:
504 508 ipinst = get_ipython()
505 509 if ipinst is not None:
506 510 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
507 511
508 512 return list
509 513
510 514 def get_exception_only(self, etype, value):
511 515 """Only print the exception type and message, without a traceback.
512 516
513 517 Parameters
514 518 ----------
515 519 etype : exception type
516 520 value : exception value
517 521 """
518 522 return ListTB.structured_traceback(self, etype, value)
519 523
520 524 def show_exception_only(self, etype, evalue):
521 525 """Only print the exception type and message, without a traceback.
522 526
523 527 Parameters
524 528 ----------
525 529 etype : exception type
526 530 value : exception value
527 531 """
528 532 # This method needs to use __call__ from *this* class, not the one from
529 533 # a subclass whose signature or behavior may be different
530 534 ostream = self.ostream
531 535 ostream.flush()
532 536 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
533 537 ostream.flush()
534 538
535 539 def _some_str(self, value):
536 540 # Lifted from traceback.py
537 541 try:
538 542 return py3compat.cast_unicode(str(value))
539 543 except:
540 544 return u'<unprintable %s object>' % type(value).__name__
541 545
542 546
543 547 #----------------------------------------------------------------------------
544 548 class VerboseTB(TBTools):
545 549 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
546 550 of HTML. Requires inspect and pydoc. Crazy, man.
547 551
548 552 Modified version which optionally strips the topmost entries from the
549 553 traceback, to be used with alternate interpreters (because their own code
550 554 would appear in the traceback)."""
551 555
552 556 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
553 557 tb_offset=0, long_header=False, include_vars=True,
554 558 check_cache=None, debugger_cls = None,
555 559 parent=None, config=None):
556 560 """Specify traceback offset, headers and color scheme.
557 561
558 562 Define how many frames to drop from the tracebacks. Calling it with
559 563 tb_offset=1 allows use of this handler in interpreters which will have
560 564 their own code at the top of the traceback (VerboseTB will first
561 565 remove that frame before printing the traceback info)."""
562 566 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
563 567 ostream=ostream, parent=parent, config=config)
564 568 self.tb_offset = tb_offset
565 569 self.long_header = long_header
566 570 self.include_vars = include_vars
567 571 # By default we use linecache.checkcache, but the user can provide a
568 572 # different check_cache implementation. This is used by the IPython
569 573 # kernel to provide tracebacks for interactive code that is cached,
570 574 # by a compiler instance that flushes the linecache but preserves its
571 575 # own code cache.
572 576 if check_cache is None:
573 577 check_cache = linecache.checkcache
574 578 self.check_cache = check_cache
575 579
576 580 self.debugger_cls = debugger_cls or debugger.Pdb
577 581
578 582 def format_record(self, frame_info):
579 583 """Format a single stack frame"""
580 584 Colors = self.Colors # just a shorthand + quicker name lookup
581 585 ColorsNormal = Colors.Normal # used a lot
582 586
583 587 if isinstance(frame_info, stack_data.RepeatedFrames):
584 588 return ' %s[... skipping similar frames: %s]%s\n' % (
585 589 Colors.excName, frame_info.description, ColorsNormal)
586 590
587 591 indent = ' ' * INDENT_SIZE
588 592 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
589 593 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
590 594 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
591 595 ColorsNormal)
592 596 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
593 597 (Colors.vName, Colors.valEm, ColorsNormal)
594 598 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
595 599 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
596 600
597 601 file = frame_info.filename
598 602 file = py3compat.cast_unicode(file, util_path.fs_encoding)
599 603 link = tpl_link % util_path.compress_user(file)
600 604 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
601 605
602 606 func = frame_info.executing.code_qualname()
603 607 if func == '<module>':
604 608 call = tpl_call % (func, '')
605 609 else:
606 610 # Decide whether to include variable details or not
607 611 var_repr = eqrepr if self.include_vars else nullrepr
608 612 try:
609 613 call = tpl_call % (func, inspect.formatargvalues(args,
610 614 varargs, varkw,
611 615 locals_, formatvalue=var_repr))
612 616 except KeyError:
613 617 # This happens in situations like errors inside generator
614 618 # expressions, where local variables are listed in the
615 619 # line, but can't be extracted from the frame. I'm not
616 620 # 100% sure this isn't actually a bug in inspect itself,
617 621 # but since there's no info for us to compute with, the
618 622 # best we can do is report the failure and move on. Here
619 623 # we must *not* call any traceback construction again,
620 624 # because that would mess up use of %debug later on. So we
621 625 # simply report the failure and move on. The only
622 626 # limitation will be that this frame won't have locals
623 627 # listed in the call signature. Quite subtle problem...
624 628 # I can't think of a good way to validate this in a unit
625 629 # test, but running a script consisting of:
626 630 # dict( (k,v.strip()) for (k,v) in range(10) )
627 631 # will illustrate the error, if this exception catch is
628 632 # disabled.
629 633 call = tpl_call_fail % func
630 634
631 635 lvals = ''
632 636 lvals_list = []
633 637 if self.include_vars:
634 638 for var in frame_info.variables_in_executing_piece:
635 639 lvals_list.append(tpl_name_val % (var.name, repr(var.value)))
636 640 if lvals_list:
637 641 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
638 642
639 643 result = '%s %s\n' % (link, call)
640 644
641 result += ''.join(_format_traceback_lines(frame_info.lines, Colors, lvals))
645 result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals))
642 646 return result
643 647
644 648 def prepare_header(self, etype, long_version=False):
645 649 colors = self.Colors # just a shorthand + quicker name lookup
646 650 colorsnormal = colors.Normal # used a lot
647 651 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
648 652 width = min(75, get_terminal_size()[0])
649 653 if long_version:
650 654 # Header with the exception type, python version, and date
651 655 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
652 656 date = time.ctime(time.time())
653 657
654 658 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
655 659 exc, ' ' * (width - len(str(etype)) - len(pyver)),
656 660 pyver, date.rjust(width) )
657 661 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
658 662 "\ncalls leading up to the error, with the most recent (innermost) call last."
659 663 else:
660 664 # Simplified header
661 665 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
662 666 rjust(width - len(str(etype))) )
663 667
664 668 return head
665 669
666 670 def format_exception(self, etype, evalue):
667 671 colors = self.Colors # just a shorthand + quicker name lookup
668 672 colorsnormal = colors.Normal # used a lot
669 673 # Get (safely) a string form of the exception info
670 674 try:
671 675 etype_str, evalue_str = map(str, (etype, evalue))
672 676 except:
673 677 # User exception is improperly defined.
674 678 etype, evalue = str, sys.exc_info()[:2]
675 679 etype_str, evalue_str = map(str, (etype, evalue))
676 680 # ... and format it
677 681 return ['%s%s%s: %s' % (colors.excName, etype_str,
678 682 colorsnormal, py3compat.cast_unicode(evalue_str))]
679 683
680 684 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
681 685 """Formats the header, traceback and exception message for a single exception.
682 686
683 687 This may be called multiple times by Python 3 exception chaining
684 688 (PEP 3134).
685 689 """
686 690 # some locals
687 691 orig_etype = etype
688 692 try:
689 693 etype = etype.__name__
690 694 except AttributeError:
691 695 pass
692 696
693 697 tb_offset = self.tb_offset if tb_offset is None else tb_offset
694 698 head = self.prepare_header(etype, self.long_header)
695 699 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
696 700
697 701 frames = list(map(self.format_record, records))
698 702
699 703 formatted_exception = self.format_exception(etype, evalue)
700 704 if records:
701 705 frame_info = records[-1]
702 706 ipinst = get_ipython()
703 707 if ipinst is not None:
704 708 ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0)
705 709
706 710 return [[head] + frames + [''.join(formatted_exception[0])]]
707 711
708 712 def get_records(self, etb, number_of_lines_of_context, tb_offset):
709 713 context = number_of_lines_of_context - 1
710 714 after = context // 2
711 715 before = context - after
712 options = stack_data.Options(before=before, after=after, pygments_formatter=TerminalFormatter())
716 if self.has_colors:
717 formatter = Terminal256Formatter()
718 else:
719 formatter = None
720 options = stack_data.Options(
721 before=before,
722 after=after,
723 pygments_formatter=formatter,
724 )
713 725 return list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:]
714 726
715 727 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
716 728 number_of_lines_of_context=5):
717 729 """Return a nice text document describing the traceback."""
718 730
719 731 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
720 732 tb_offset)
721 733
722 734 colors = self.Colors # just a shorthand + quicker name lookup
723 735 colorsnormal = colors.Normal # used a lot
724 736 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
725 737 structured_traceback_parts = [head]
726 738 chained_exceptions_tb_offset = 0
727 739 lines_of_context = 3
728 740 formatted_exceptions = formatted_exception
729 741 exception = self.get_parts_of_chained_exception(evalue)
730 742 if exception:
731 743 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
732 744 etype, evalue, etb = exception
733 745 else:
734 746 evalue = None
735 747 chained_exc_ids = set()
736 748 while evalue:
737 749 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
738 750 chained_exceptions_tb_offset)
739 751 exception = self.get_parts_of_chained_exception(evalue)
740 752
741 753 if exception and not id(exception[1]) in chained_exc_ids:
742 754 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
743 755 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
744 756 etype, evalue, etb = exception
745 757 else:
746 758 evalue = None
747 759
748 760 # we want to see exceptions in a reversed order:
749 761 # the first exception should be on top
750 762 for formatted_exception in reversed(formatted_exceptions):
751 763 structured_traceback_parts += formatted_exception
752 764
753 765 return structured_traceback_parts
754 766
755 767 def debugger(self, force=False):
756 768 """Call up the pdb debugger if desired, always clean up the tb
757 769 reference.
758 770
759 771 Keywords:
760 772
761 773 - force(False): by default, this routine checks the instance call_pdb
762 774 flag and does not actually invoke the debugger if the flag is false.
763 775 The 'force' option forces the debugger to activate even if the flag
764 776 is false.
765 777
766 778 If the call_pdb flag is set, the pdb interactive debugger is
767 779 invoked. In all cases, the self.tb reference to the current traceback
768 780 is deleted to prevent lingering references which hamper memory
769 781 management.
770 782
771 783 Note that each call to pdb() does an 'import readline', so if your app
772 784 requires a special setup for the readline completers, you'll have to
773 785 fix that by hand after invoking the exception handler."""
774 786
775 787 if force or self.call_pdb:
776 788 if self.pdb is None:
777 789 self.pdb = self.debugger_cls()
778 790 # the system displayhook may have changed, restore the original
779 791 # for pdb
780 792 display_trap = DisplayTrap(hook=sys.__displayhook__)
781 793 with display_trap:
782 794 self.pdb.reset()
783 795 # Find the right frame so we don't pop up inside ipython itself
784 796 if hasattr(self, 'tb') and self.tb is not None:
785 797 etb = self.tb
786 798 else:
787 799 etb = self.tb = sys.last_traceback
788 800 while self.tb is not None and self.tb.tb_next is not None:
789 801 self.tb = self.tb.tb_next
790 802 if etb and etb.tb_next:
791 803 etb = etb.tb_next
792 804 self.pdb.botframe = etb.tb_frame
793 805 self.pdb.interaction(None, etb)
794 806
795 807 if hasattr(self, 'tb'):
796 808 del self.tb
797 809
798 810 def handler(self, info=None):
799 811 (etype, evalue, etb) = info or sys.exc_info()
800 812 self.tb = etb
801 813 ostream = self.ostream
802 814 ostream.flush()
803 815 ostream.write(self.text(etype, evalue, etb))
804 816 ostream.write('\n')
805 817 ostream.flush()
806 818
807 819 # Changed so an instance can just be called as VerboseTB_inst() and print
808 820 # out the right info on its own.
809 821 def __call__(self, etype=None, evalue=None, etb=None):
810 822 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
811 823 if etb is None:
812 824 self.handler()
813 825 else:
814 826 self.handler((etype, evalue, etb))
815 827 try:
816 828 self.debugger()
817 829 except KeyboardInterrupt:
818 830 print("\nKeyboardInterrupt")
819 831
820 832
821 833 #----------------------------------------------------------------------------
822 834 class FormattedTB(VerboseTB, ListTB):
823 835 """Subclass ListTB but allow calling with a traceback.
824 836
825 837 It can thus be used as a sys.excepthook for Python > 2.1.
826 838
827 839 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
828 840
829 841 Allows a tb_offset to be specified. This is useful for situations where
830 842 one needs to remove a number of topmost frames from the traceback (such as
831 843 occurs with python programs that themselves execute other python code,
832 844 like Python shells). """
833 845
834 846 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
835 847 ostream=None,
836 848 tb_offset=0, long_header=False, include_vars=False,
837 849 check_cache=None, debugger_cls=None,
838 850 parent=None, config=None):
839 851
840 852 # NEVER change the order of this list. Put new modes at the end:
841 853 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
842 854 self.verbose_modes = self.valid_modes[1:3]
843 855
844 856 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
845 857 ostream=ostream, tb_offset=tb_offset,
846 858 long_header=long_header, include_vars=include_vars,
847 859 check_cache=check_cache, debugger_cls=debugger_cls,
848 860 parent=parent, config=config)
849 861
850 862 # Different types of tracebacks are joined with different separators to
851 863 # form a single string. They are taken from this dict
852 864 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
853 865 Minimal='')
854 866 # set_mode also sets the tb_join_char attribute
855 867 self.set_mode(mode)
856 868
857 869 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
858 870 tb_offset = self.tb_offset if tb_offset is None else tb_offset
859 871 mode = self.mode
860 872 if mode in self.verbose_modes:
861 873 # Verbose modes need a full traceback
862 874 return VerboseTB.structured_traceback(
863 875 self, etype, value, tb, tb_offset, number_of_lines_of_context
864 876 )
865 877 elif mode == 'Minimal':
866 878 return ListTB.get_exception_only(self, etype, value)
867 879 else:
868 880 # We must check the source cache because otherwise we can print
869 881 # out-of-date source code.
870 882 self.check_cache()
871 883 # Now we can extract and format the exception
872 884 return ListTB.structured_traceback(
873 885 self, etype, value, tb, tb_offset, number_of_lines_of_context
874 886 )
875 887
876 888 def stb2text(self, stb):
877 889 """Convert a structured traceback (a list) to a string."""
878 890 return self.tb_join_char.join(stb)
879 891
880 892
881 893 def set_mode(self, mode=None):
882 894 """Switch to the desired mode.
883 895
884 896 If mode is not specified, cycles through the available modes."""
885 897
886 898 if not mode:
887 899 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
888 900 len(self.valid_modes)
889 901 self.mode = self.valid_modes[new_idx]
890 902 elif mode not in self.valid_modes:
891 903 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
892 904 'Valid modes: ' + str(self.valid_modes))
893 905 else:
894 906 self.mode = mode
895 907 # include variable details only in 'Verbose' mode
896 908 self.include_vars = (self.mode == self.valid_modes[2])
897 909 # Set the join character for generating text tracebacks
898 910 self.tb_join_char = self._join_chars[self.mode]
899 911
900 912 # some convenient shortcuts
901 913 def plain(self):
902 914 self.set_mode(self.valid_modes[0])
903 915
904 916 def context(self):
905 917 self.set_mode(self.valid_modes[1])
906 918
907 919 def verbose(self):
908 920 self.set_mode(self.valid_modes[2])
909 921
910 922 def minimal(self):
911 923 self.set_mode(self.valid_modes[3])
912 924
913 925
914 926 #----------------------------------------------------------------------------
915 927 class AutoFormattedTB(FormattedTB):
916 928 """A traceback printer which can be called on the fly.
917 929
918 930 It will find out about exceptions by itself.
919 931
920 932 A brief example::
921 933
922 934 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
923 935 try:
924 936 ...
925 937 except:
926 938 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
927 939 """
928 940
929 941 def __call__(self, etype=None, evalue=None, etb=None,
930 942 out=None, tb_offset=None):
931 943 """Print out a formatted exception traceback.
932 944
933 945 Optional arguments:
934 946 - out: an open file-like object to direct output to.
935 947
936 948 - tb_offset: the number of frames to skip over in the stack, on a
937 949 per-call basis (this overrides temporarily the instance's tb_offset
938 950 given at initialization time. """
939 951
940 952 if out is None:
941 953 out = self.ostream
942 954 out.flush()
943 955 out.write(self.text(etype, evalue, etb, tb_offset))
944 956 out.write('\n')
945 957 out.flush()
946 958 # FIXME: we should remove the auto pdb behavior from here and leave
947 959 # that to the clients.
948 960 try:
949 961 self.debugger()
950 962 except KeyboardInterrupt:
951 963 print("\nKeyboardInterrupt")
952 964
953 965 def structured_traceback(self, etype=None, value=None, tb=None,
954 966 tb_offset=None, number_of_lines_of_context=5):
955 967 if etype is None:
956 968 etype, value, tb = sys.exc_info()
957 969 if isinstance(tb, tuple):
958 970 # tb is a tuple if this is a chained exception.
959 971 self.tb = tb[0]
960 972 else:
961 973 self.tb = tb
962 974 return FormattedTB.structured_traceback(
963 975 self, etype, value, tb, tb_offset, number_of_lines_of_context)
964 976
965 977
966 978 #---------------------------------------------------------------------------
967 979
968 980 # A simple class to preserve Nathan's original functionality.
969 981 class ColorTB(FormattedTB):
970 982 """Shorthand to initialize a FormattedTB in Linux colors mode."""
971 983
972 984 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
973 985 FormattedTB.__init__(self, color_scheme=color_scheme,
974 986 call_pdb=call_pdb, **kwargs)
975 987
976 988
977 989 class SyntaxTB(ListTB):
978 990 """Extension which holds some state: the last exception value"""
979 991
980 992 def __init__(self, color_scheme='NoColor', parent=None, config=None):
981 993 ListTB.__init__(self, color_scheme, parent=parent, config=config)
982 994 self.last_syntax_error = None
983 995
984 996 def __call__(self, etype, value, elist):
985 997 self.last_syntax_error = value
986 998
987 999 ListTB.__call__(self, etype, value, elist)
988 1000
989 1001 def structured_traceback(self, etype, value, elist, tb_offset=None,
990 1002 context=5):
991 1003 # If the source file has been edited, the line in the syntax error can
992 1004 # be wrong (retrieved from an outdated cache). This replaces it with
993 1005 # the current value.
994 1006 if isinstance(value, SyntaxError) \
995 1007 and isinstance(value.filename, str) \
996 1008 and isinstance(value.lineno, int):
997 1009 linecache.checkcache(value.filename)
998 1010 newtext = linecache.getline(value.filename, value.lineno)
999 1011 if newtext:
1000 1012 value.text = newtext
1001 1013 self.last_syntax_error = value
1002 1014 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1003 1015 tb_offset=tb_offset, context=context)
1004 1016
1005 1017 def clear_err_state(self):
1006 1018 """Return the current error state and clear it"""
1007 1019 e = self.last_syntax_error
1008 1020 self.last_syntax_error = None
1009 1021 return e
1010 1022
1011 1023 def stb2text(self, stb):
1012 1024 """Convert a structured traceback (a list) to a string."""
1013 1025 return ''.join(stb)
1014 1026
1015 1027
1016 1028 # some internal-use functions
1017 1029 def text_repr(value):
1018 1030 """Hopefully pretty robust repr equivalent."""
1019 1031 # this is pretty horrible but should always return *something*
1020 1032 try:
1021 1033 return pydoc.text.repr(value)
1022 1034 except KeyboardInterrupt:
1023 1035 raise
1024 1036 except:
1025 1037 try:
1026 1038 return repr(value)
1027 1039 except KeyboardInterrupt:
1028 1040 raise
1029 1041 except:
1030 1042 try:
1031 1043 # all still in an except block so we catch
1032 1044 # getattr raising
1033 1045 name = getattr(value, '__name__', None)
1034 1046 if name:
1035 1047 # ick, recursion
1036 1048 return text_repr(name)
1037 1049 klass = getattr(value, '__class__', None)
1038 1050 if klass:
1039 1051 return '%s instance' % text_repr(klass)
1040 1052 except KeyboardInterrupt:
1041 1053 raise
1042 1054 except:
1043 1055 return 'UNRECOVERABLE REPR FAILURE'
1044 1056
1045 1057
1046 1058 def eqrepr(value, repr=text_repr):
1047 1059 return '=%s' % repr(value)
1048 1060
1049 1061
1050 1062 def nullrepr(value, repr=text_repr):
1051 1063 return ''
General Comments 0
You need to be logged in to leave comments. Login now