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