##// END OF EJS Templates
Merge pull request #6065 from atteroTheGreatest/i1673...
Thomas Kluyver -
r17170:2bf35f92 merge
parent child Browse files
Show More
@@ -1735,7 +1735,7 b' class InteractiveShell(SingletonConfigurable):'
1735 1735 This hook should be used sparingly, only in places which are not likely
1736 1736 to be true IPython errors.
1737 1737 """
1738 self.showtraceback((etype,value,tb),tb_offset=0)
1738 self.showtraceback((etype, value, tb), tb_offset=0)
1739 1739
1740 1740 def _get_exc_info(self, exc_tuple=None):
1741 1741 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
@@ -1776,7 +1776,7 b' class InteractiveShell(SingletonConfigurable):'
1776 1776 """
1777 1777 self.write_err("UsageError: %s" % exc)
1778 1778
1779 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1779 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1780 1780 exception_only=False):
1781 1781 """Display the exception that just occurred.
1782 1782
@@ -2918,10 +2918,9 b' class InteractiveShell(SingletonConfigurable):'
2918 2918 False : successful execution.
2919 2919 True : an error occurred.
2920 2920 """
2921
2922 2921 # Set our own excepthook in case the user code tries to call it
2923 2922 # directly, so that the IPython crash handler doesn't get triggered
2924 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2923 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2925 2924
2926 2925 # we save the original sys.excepthook in the instance, in case config
2927 2926 # code (such as magics) needs access to it.
@@ -2939,8 +2938,8 b' class InteractiveShell(SingletonConfigurable):'
2939 2938 self.showtraceback(exception_only=True)
2940 2939 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2941 2940 except self.custom_exceptions:
2942 etype,value,tb = sys.exc_info()
2943 self.CustomTB(etype,value,tb)
2941 etype, value, tb = sys.exc_info()
2942 self.CustomTB(etype, value, tb)
2944 2943 except:
2945 2944 self.showtraceback()
2946 2945 else:
@@ -9,6 +9,7 b' from IPython.testing import tools as tt'
9 9 from IPython.testing.decorators import onlyif_unicode_paths
10 10 from IPython.utils.syspathcontext import prepended_to_syspath
11 11 from IPython.utils.tempdir import TemporaryDirectory
12 from IPython.utils.py3compat import PY3
12 13
13 14 ip = get_ipython()
14 15
@@ -147,3 +148,37 b' class SyntaxErrorTest(unittest.TestCase):'
147 148 except ValueError:
148 149 with tt.AssertPrints('QWERTY'):
149 150 ip.showsyntaxerror()
151
152
153 class Python3ChainedExceptionsTest(unittest.TestCase):
154 DIRECT_CAUSE_ERROR_CODE = """
155 try:
156 x = 1 + 2
157 print(not_defined_here)
158 except Exception as e:
159 x += 55
160 x - 1
161 y = {}
162 raise KeyError('uh') from e
163 """
164
165 EXCEPTION_DURING_HANDLING_CODE = """
166 try:
167 x = 1 + 2
168 print(not_defined_here)
169 except Exception as e:
170 x += 55
171 x - 1
172 y = {}
173 raise KeyError('uh')
174 """
175
176 def test_direct_cause_error(self):
177 if PY3:
178 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
179 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
180
181 def test_exception_during_handling_error(self):
182 if PY3:
183 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
184 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
This diff has been collapsed as it changes many lines, (529 lines changed) Show them Hide them
@@ -39,7 +39,7 b" Give it a shot--you'll love it or you'll hate it."
39 39 Verbose).
40 40
41 41
42 Installation instructions for ColorTB::
42 Installation instructions for VerboseTB::
43 43
44 44 import sys,ultratb
45 45 sys.excepthook = ultratb.VerboseTB()
@@ -73,11 +73,11 b' Inheritance diagram:'
73 73 """
74 74
75 75 #*****************************************************************************
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
78 78 #
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
81 81 #*****************************************************************************
82 82
83 83 from __future__ import unicode_literals
@@ -95,14 +95,14 b' import tokenize'
95 95 import traceback
96 96 import types
97 97
98 try: # Python 2
98 try: # Python 2
99 99 generate_tokens = tokenize.generate_tokens
100 except AttributeError: # Python 3
100 except AttributeError: # Python 3
101 101 generate_tokens = tokenize.tokenize
102 102
103 103 # For purposes of monkeypatching inspect to fix a bug in it.
104 from inspect import getsourcefile, getfile, getmodule,\
105 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
104 from inspect import getsourcefile, getfile, getmodule, \
105 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
106 106
107 107 # IPython's own modules
108 108 # Modified pdb which doesn't damage IPython's readline handling
@@ -125,11 +125,11 b' INDENT_SIZE = 8'
125 125
126 126 # Default color scheme. This is used, for example, by the traceback
127 127 # formatter. When running in an actual IPython instance, the user's rc.colors
128 # value is used, but havinga module global makes this functionality available
128 # value is used, but having a module global makes this functionality available
129 129 # to users of ultratb who are NOT running inside ipython.
130 130 DEFAULT_SCHEME = 'NoColor'
131 131
132 #---------------------------------------------------------------------------
132 # ---------------------------------------------------------------------------
133 133 # Code begins
134 134
135 135 # Utility functions
@@ -141,6 +141,7 b' def inspect_error():'
141 141 error('Internal Python error in the inspect module.\n'
142 142 'Below is the traceback from this internal error.\n')
143 143
144
144 145 # This function is a monkeypatch we apply to the Python inspect module. We have
145 146 # now found when it's needed (see discussion on issue gh-1456), and we have a
146 147 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
@@ -212,7 +213,7 b' def findsource(object):'
212 213 pmatch = pat.match
213 214 # fperez - fix: sometimes, co_firstlineno can give a number larger than
214 215 # the length of lines, which causes an error. Safeguard against that.
215 lnum = min(object.co_firstlineno,len(lines))-1
216 lnum = min(object.co_firstlineno, len(lines)) - 1
216 217 while lnum > 0:
217 218 if pmatch(lines[lnum]): break
218 219 lnum -= 1
@@ -220,9 +221,11 b' def findsource(object):'
220 221 return lines, lnum
221 222 raise IOError('could not find code object')
222 223
224
223 225 # Monkeypatch inspect to apply our bugfix.
224 226 def with_patch_inspect(f):
225 227 """decorator for monkeypatching inspect.findsource"""
228
226 229 def wrapped(*args, **kwargs):
227 230 save_findsource = inspect.findsource
228 231 inspect.findsource = findsource
@@ -230,8 +233,10 b' def with_patch_inspect(f):'
230 233 return f(*args, **kwargs)
231 234 finally:
232 235 inspect.findsource = save_findsource
236
233 237 return wrapped
234 238
239
235 240 def fix_frame_records_filenames(records):
236 241 """Try to fix the filenames in each record from inspect.getinnerframes().
237 242
@@ -253,11 +258,10 b' def fix_frame_records_filenames(records):'
253 258
254 259
255 260 @with_patch_inspect
256 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
257 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
258
259 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
261 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
262 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
260 263
264 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
261 265 # If the error is at the console, don't build any context, since it would
262 266 # otherwise produce 5 blank lines printed out (there is no file at the
263 267 # console)
@@ -272,9 +276,9 b' def _fixed_getinnerframes(etb, context=1,tb_offset=0):'
272 276 aux = traceback.extract_tb(etb)
273 277 assert len(records) == len(aux)
274 278 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
275 maybeStart = lnum-1 - context//2
276 start = max(maybeStart, 0)
277 end = start + context
279 maybeStart = lnum - 1 - context // 2
280 start = max(maybeStart, 0)
281 end = start + context
278 282 lines = ulinecache.getlines(file)[start:end]
279 283 buf = list(records[i])
280 284 buf[LNUM_POS] = lnum
@@ -290,7 +294,8 b' def _fixed_getinnerframes(etb, context=1,tb_offset=0):'
290 294
291 295 _parser = PyColorize.Parser()
292 296
293 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
297
298 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
294 299 numbers_width = INDENT_SIZE - 1
295 300 res = []
296 301 i = lnum - index
@@ -315,7 +320,7 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):'
315 320 # This is the line with the error
316 321 pad = numbers_width - len(str(i))
317 322 if pad >= 3:
318 marker = '-'*(pad-3) + '-> '
323 marker = '-' * (pad - 3) + '-> '
319 324 elif pad == 2:
320 325 marker = '> '
321 326 elif pad == 1:
@@ -323,12 +328,12 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):'
323 328 else:
324 329 marker = ''
325 330 num = marker + str(i)
326 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
327 Colors.line, line, Colors.Normal)
331 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
332 Colors.line, line, Colors.Normal)
328 333 else:
329 num = '%*s' % (numbers_width,i)
330 line = '%s%s%s %s' %(Colors.lineno, num,
331 Colors.Normal, line)
334 num = '%*s' % (numbers_width, i)
335 line = '%s%s%s %s' % (Colors.lineno, num,
336 Colors.Normal, line)
332 337
333 338 res.append(line)
334 339 if lvals and i == lnum:
@@ -389,16 +394,16 b' class TBTools(object):'
389 394
390 395 ostream = property(_get_ostream, _set_ostream)
391 396
392 def set_colors(self,*args,**kw):
397 def set_colors(self, *args, **kw):
393 398 """Shorthand access to the color table scheme selector method."""
394 399
395 400 # Set own color table
396 self.color_scheme_table.set_active_scheme(*args,**kw)
401 self.color_scheme_table.set_active_scheme(*args, **kw)
397 402 # for convenience, set Colors to the active scheme
398 403 self.Colors = self.color_scheme_table.active_colors
399 404 # Also set colors of debugger
400 if hasattr(self,'pdb') and self.pdb is not None:
401 self.pdb.set_colors(*args,**kw)
405 if hasattr(self, 'pdb') and self.pdb is not None:
406 self.pdb.set_colors(*args, **kw)
402 407
403 408 def color_toggle(self):
404 409 """Toggle between the currently active color scheme and NoColor."""
@@ -453,7 +458,7 b' class ListTB(TBTools):'
453 458 Because they are meant to be called without a full traceback (only a
454 459 list), instances of this class can't call the interactive pdb debugger."""
455 460
456 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
461 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
457 462 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
458 463 ostream=ostream)
459 464
@@ -497,7 +502,7 b' class ListTB(TBTools):'
497 502 elist = elist[tb_offset:]
498 503
499 504 out_list.append('Traceback %s(most recent call last)%s:' %
500 (Colors.normalEm, Colors.Normal) + '\n')
505 (Colors.normalEm, Colors.Normal) + '\n')
501 506 out_list.extend(self._format_list(elist))
502 507 # The exception info should be a single entry in the list.
503 508 lines = ''.join(self._format_exception_only(etype, value))
@@ -510,7 +515,7 b' class ListTB(TBTools):'
510 515 ## out_list.append(lines[-1])
511 516
512 517 # This means it was indenting everything but the last line by a little
513 # bit. I've disabled this for now, but if we see ugliness somewhre we
518 # bit. I've disabled this for now, but if we see ugliness somewhere we
514 519 # can restore it.
515 520
516 521 return out_list
@@ -532,25 +537,24 b' class ListTB(TBTools):'
532 537 list = []
533 538 for filename, lineno, name, line in extracted_list[:-1]:
534 539 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
535 (Colors.filename, filename, Colors.Normal,
536 Colors.lineno, lineno, Colors.Normal,
537 Colors.name, name, Colors.Normal)
540 (Colors.filename, filename, Colors.Normal,
541 Colors.lineno, lineno, Colors.Normal,
542 Colors.name, name, Colors.Normal)
538 543 if line:
539 544 item += ' %s\n' % line.strip()
540 545 list.append(item)
541 546 # Emphasize the last entry
542 547 filename, lineno, name, line = extracted_list[-1]
543 548 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
544 (Colors.normalEm,
545 Colors.filenameEm, filename, Colors.normalEm,
546 Colors.linenoEm, lineno, Colors.normalEm,
547 Colors.nameEm, name, Colors.normalEm,
548 Colors.Normal)
549 (Colors.normalEm,
550 Colors.filenameEm, filename, Colors.normalEm,
551 Colors.linenoEm, lineno, Colors.normalEm,
552 Colors.nameEm, name, Colors.normalEm,
553 Colors.Normal)
549 554 if line:
550 555 item += '%s %s%s\n' % (Colors.line, line.strip(),
551 Colors.Normal)
556 Colors.Normal)
552 557 list.append(item)
553 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
554 558 return list
555 559
556 560 def _format_exception_only(self, etype, value):
@@ -572,11 +576,10 b' class ListTB(TBTools):'
572 576 stype = Colors.excName + etype.__name__ + Colors.Normal
573 577 if value is None:
574 578 # Not sure if this can still happen in Python 2.6 and above
575 list.append( py3compat.cast_unicode(stype) + '\n')
579 list.append(py3compat.cast_unicode(stype) + '\n')
576 580 else:
577 581 if issubclass(etype, SyntaxError):
578 582 have_filedata = True
579 #print 'filename is',filename # dbg
580 583 if not value.filename: value.filename = "<string>"
581 584 if value.lineno:
582 585 lineno = value.lineno
@@ -585,9 +588,9 b' class ListTB(TBTools):'
585 588 lineno = 'unknown'
586 589 textline = ''
587 590 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
588 (Colors.normalEm,
589 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
590 Colors.linenoEm, lineno, Colors.Normal ))
591 (Colors.normalEm,
592 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
593 Colors.linenoEm, lineno, Colors.Normal ))
591 594 if textline == '':
592 595 textline = py3compat.cast_unicode(value.text, "utf-8")
593 596
@@ -600,13 +603,13 b' class ListTB(TBTools):'
600 603 Colors.Normal))
601 604 if value.offset is not None:
602 605 s = ' '
603 for c in textline[i:value.offset-1]:
606 for c in textline[i:value.offset - 1]:
604 607 if c.isspace():
605 608 s += c
606 609 else:
607 610 s += ' '
608 611 list.append('%s%s^%s\n' % (Colors.caret, s,
609 Colors.Normal) )
612 Colors.Normal))
610 613
611 614 try:
612 615 s = value.msg
@@ -636,7 +639,6 b' class ListTB(TBTools):'
636 639 """
637 640 return ListTB.structured_traceback(self, etype, value, [])
638 641
639
640 642 def show_exception_only(self, etype, evalue):
641 643 """Only print the exception type and message, without a traceback.
642 644
@@ -659,6 +661,7 b' class ListTB(TBTools):'
659 661 except:
660 662 return '<unprintable %s object>' % type(value).__name__
661 663
664
662 665 #----------------------------------------------------------------------------
663 666 class VerboseTB(TBTools):
664 667 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
@@ -668,7 +671,7 b' class VerboseTB(TBTools):'
668 671 traceback, to be used with alternate interpreters (because their own code
669 672 would appear in the traceback)."""
670 673
671 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
674 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
672 675 tb_offset=0, long_header=False, include_vars=True,
673 676 check_cache=None):
674 677 """Specify traceback offset, headers and color scheme.
@@ -691,126 +694,37 b' class VerboseTB(TBTools):'
691 694 check_cache = linecache.checkcache
692 695 self.check_cache = check_cache
693 696
694 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
695 context=5):
696 """Return a nice text document describing the traceback."""
697
698 tb_offset = self.tb_offset if tb_offset is None else tb_offset
699
700 # some locals
701 try:
702 etype = etype.__name__
703 except AttributeError:
704 pass
705 Colors = self.Colors # just a shorthand + quicker name lookup
706 ColorsNormal = Colors.Normal # used a lot
707 col_scheme = self.color_scheme_table.active_scheme_name
708 indent = ' '*INDENT_SIZE
709 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
710 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
711 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
712
713 # some internal-use functions
714 def text_repr(value):
715 """Hopefully pretty robust repr equivalent."""
716 # this is pretty horrible but should always return *something*
717 try:
718 return pydoc.text.repr(value)
719 except KeyboardInterrupt:
720 raise
721 except:
722 try:
723 return repr(value)
724 except KeyboardInterrupt:
725 raise
726 except:
727 try:
728 # all still in an except block so we catch
729 # getattr raising
730 name = getattr(value, '__name__', None)
731 if name:
732 # ick, recursion
733 return text_repr(name)
734 klass = getattr(value, '__class__', None)
735 if klass:
736 return '%s instance' % text_repr(klass)
737 except KeyboardInterrupt:
738 raise
739 except:
740 return 'UNRECOVERABLE REPR FAILURE'
741 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
742 def nullrepr(value, repr=text_repr): return ''
743
744 # meat of the code begins
745 try:
746 etype = etype.__name__
747 except AttributeError:
748 pass
749
750 if self.long_header:
751 # Header with the exception type, python version, and date
752 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
753 date = time.ctime(time.time())
754
755 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
756 exc, ' '*(75-len(str(etype))-len(pyver)),
757 pyver, date.rjust(75) )
758 head += "\nA problem occured executing Python code. Here is the sequence of function"\
759 "\ncalls leading up to the error, with the most recent (innermost) call last."
760 else:
761 # Simplified header
762 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
763 'Traceback (most recent call last)'.\
764 rjust(75 - len(str(etype)) ) )
697 def format_records(self, records):
698 Colors = self.Colors # just a shorthand + quicker name lookup
699 ColorsNormal = Colors.Normal # used a lot
700 col_scheme = self.color_scheme_table.active_scheme_name
701 indent = ' ' * INDENT_SIZE
702 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
703 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
765 704 frames = []
766 # Flush cache before calling inspect. This helps alleviate some of the
767 # problems with python 2.3's inspect.py.
768 ##self.check_cache()
769 # Drop topmost frames if requested
770 try:
771 # Try the default getinnerframes and Alex's: Alex's fixes some
772 # problems, but it generates empty tracebacks for console errors
773 # (5 blanks lines) where none should be returned.
774 #records = inspect.getinnerframes(etb, context)[tb_offset:]
775 #print 'python records:', records # dbg
776 records = _fixed_getinnerframes(etb, context, tb_offset)
777 #print 'alex records:', records # dbg
778 except:
779
780 # FIXME: I've been getting many crash reports from python 2.3
781 # users, traceable to inspect.py. If I can find a small test-case
782 # to reproduce this, I should either write a better workaround or
783 # file a bug report against inspect (if that's the real problem).
784 # So far, I haven't been able to find an isolated example to
785 # reproduce the problem.
786 inspect_error()
787 traceback.print_exc(file=self.ostream)
788 info('\nUnfortunately, your original traceback can not be constructed.\n')
789 return ''
790
791 705 # build some color string templates outside these nested loops
792 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
793 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
794 ColorsNormal)
795 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
796 (Colors.vName, Colors.valEm, ColorsNormal)
797 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
706 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
707 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
708 ColorsNormal)
709 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
710 (Colors.vName, Colors.valEm, ColorsNormal)
711 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
798 712 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
799 713 Colors.vName, ColorsNormal)
800 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
801 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
802 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
803 ColorsNormal)
714 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
715
716 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
717 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
718 ColorsNormal)
804 719
805 # now, loop over all records printing context and info
806 720 abspath = os.path.abspath
807 721 for frame, file, lnum, func, lines, index in records:
808 722 #print '*** record:',file,lnum,func,lines,index # dbg
809 723 if not file:
810 724 file = '?'
811 elif not(file.startswith(str("<")) and file.endswith(str(">"))):
725 elif not (file.startswith(str("<")) and file.endswith(str(">"))):
812 726 # Guess that filenames like <string> aren't real filenames, so
813 # don't call abspath on them.
727 # don't call abspath on them.
814 728 try:
815 729 file = abspath(file)
816 730 except OSError:
@@ -827,9 +741,9 b' class VerboseTB(TBTools):'
827 741 # Decide whether to include variable details or not
828 742 var_repr = self.include_vars and eqrepr or nullrepr
829 743 try:
830 call = tpl_call % (func,inspect.formatargvalues(args,
831 varargs, varkw,
832 locals,formatvalue=var_repr))
744 call = tpl_call % (func, inspect.formatargvalues(args,
745 varargs, varkw,
746 locals, formatvalue=var_repr))
833 747 except KeyError:
834 748 # This happens in situations like errors inside generator
835 749 # expressions, where local variables are listed in the
@@ -848,12 +762,12 b' class VerboseTB(TBTools):'
848 762 # will illustrate the error, if this exception catch is
849 763 # disabled.
850 764 call = tpl_call_fail % func
851
765
852 766 # Don't attempt to tokenize binary files.
853 767 if file.endswith(('.so', '.pyd', '.dll')):
854 frames.append('%s %s\n' % (link,call))
768 frames.append('%s %s\n' % (link, call))
855 769 continue
856 elif file.endswith(('.pyc','.pyo')):
770 elif file.endswith(('.pyc', '.pyo')):
857 771 # Look up the corresponding source file.
858 772 file = openpy.source_from_cache(file)
859 773
@@ -867,7 +781,7 b' class VerboseTB(TBTools):'
867 781 try:
868 782 names = []
869 783 name_cont = False
870
784
871 785 for token_type, token, start, end, line in generate_tokens(linereader):
872 786 # build composite names
873 787 if token_type == tokenize.NAME and token not in keyword.kwlist:
@@ -890,7 +804,7 b' class VerboseTB(TBTools):'
890 804 name_cont = True
891 805 elif token_type == tokenize.NEWLINE:
892 806 break
893
807
894 808 except (IndexError, UnicodeDecodeError):
895 809 # signals exit of tokenizer
896 810 pass
@@ -909,11 +823,11 b' class VerboseTB(TBTools):'
909 823 lvals = []
910 824 if self.include_vars:
911 825 for name_full in unique_names:
912 name_base = name_full.split('.',1)[0]
826 name_base = name_full.split('.', 1)[0]
913 827 if name_base in frame.f_code.co_varnames:
914 828 if name_base in locals:
915 829 try:
916 value = repr(eval(name_full,locals))
830 value = repr(eval(name_full, locals))
917 831 except:
918 832 value = undefined
919 833 else:
@@ -922,69 +836,191 b' class VerboseTB(TBTools):'
922 836 else:
923 837 if name_base in frame.f_globals:
924 838 try:
925 value = repr(eval(name_full,frame.f_globals))
839 value = repr(eval(name_full, frame.f_globals))
926 840 except:
927 841 value = undefined
928 842 else:
929 843 value = undefined
930 844 name = tpl_global_var % name_full
931 lvals.append(tpl_name_val % (name,value))
845 lvals.append(tpl_name_val % (name, value))
932 846 if lvals:
933 lvals = '%s%s' % (indent,em_normal.join(lvals))
847 lvals = '%s%s' % (indent, em_normal.join(lvals))
934 848 else:
935 849 lvals = ''
936 850
937 level = '%s %s\n' % (link,call)
851 level = '%s %s\n' % (link, call)
938 852
939 853 if index is None:
940 854 frames.append(level)
941 855 else:
942 frames.append('%s%s' % (level,''.join(
943 _format_traceback_lines(lnum,index,lines,Colors,lvals,
856 frames.append('%s%s' % (level, ''.join(
857 _format_traceback_lines(lnum, index, lines, Colors, lvals,
944 858 col_scheme))))
945 859
860 return frames
861
862 def prepare_chained_exception_message(self, cause):
863 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
864 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
865
866 if cause:
867 message = [[direct_cause]]
868 else:
869 message = [[exception_during_handling]]
870 return message
871
872 def prepare_header(self, etype, long_version=False):
873 colors = self.Colors # just a shorthand + quicker name lookup
874 colorsnormal = colors.Normal # used a lot
875 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
876 if long_version:
877 # Header with the exception type, python version, and date
878 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
879 date = time.ctime(time.time())
880
881 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
882 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
883 pyver, date.rjust(75) )
884 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
885 "\ncalls leading up to the error, with the most recent (innermost) call last."
886 else:
887 # Simplified header
888 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
889 rjust(75 - len(str(etype))) )
890
891 return head
892
893 def format_exception(self, etype, evalue):
894 colors = self.Colors # just a shorthand + quicker name lookup
895 colorsnormal = colors.Normal # used a lot
896 indent = ' ' * INDENT_SIZE
946 897 # Get (safely) a string form of the exception info
947 898 try:
948 etype_str,evalue_str = map(str,(etype,evalue))
899 etype_str, evalue_str = map(str, (etype, evalue))
949 900 except:
950 901 # User exception is improperly defined.
951 etype,evalue = str,sys.exc_info()[:2]
952 etype_str,evalue_str = map(str,(etype,evalue))
902 etype, evalue = str, sys.exc_info()[:2]
903 etype_str, evalue_str = map(str, (etype, evalue))
953 904 # ... and format it
954 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
955 ColorsNormal, py3compat.cast_unicode(evalue_str))]
905 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
906 colorsnormal, py3compat.cast_unicode(evalue_str))]
907
956 908 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
957 909 try:
958 910 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
959 911 except:
960 # Every now and then, an object with funny inernals blows up
912 # Every now and then, an object with funny internals blows up
961 913 # when dir() is called on it. We do the best we can to report
962 914 # the problem and continue
963 915 _m = '%sException reporting error (object with broken dir())%s:'
964 exception.append(_m % (Colors.excName,ColorsNormal))
965 etype_str,evalue_str = map(str,sys.exc_info()[:2])
966 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
967 ColorsNormal, py3compat.cast_unicode(evalue_str)))
916 exception.append(_m % (colors.excName, colorsnormal))
917 etype_str, evalue_str = map(str, sys.exc_info()[:2])
918 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
919 colorsnormal, py3compat.cast_unicode(evalue_str)))
968 920 names = []
969 921 for name in names:
970 922 value = text_repr(getattr(evalue, name))
971 923 exception.append('\n%s%s = %s' % (indent, name, value))
972 924
973 # vds: >>
925 return exception
926
927 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
928 # some locals
929 try:
930 etype = etype.__name__
931 except AttributeError:
932 pass
933
934 tb_offset = self.tb_offset if tb_offset is None else tb_offset
935 head = self.prepare_header(etype, self.long_header)
936 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
937
938 frames = self.format_records(records)
939 if records is None:
940 return ""
941
942 formatted_exception = self.format_exception(etype, evalue)
974 943 if records:
975 filepath, lnum = records[-1][1:3]
976 #print "file:", str(file), "linenb", str(lnum) # dbg
977 filepath = os.path.abspath(filepath)
978 ipinst = get_ipython()
979 if ipinst is not None:
980 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
981 # vds: <<
982
983 # return all our info assembled as a single string
984 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
985 return [head] + frames + [''.join(exception[0])]
986
987 def debugger(self,force=False):
944 filepath, lnum = records[-1][1:3]
945 filepath = os.path.abspath(filepath)
946 ipinst = get_ipython()
947 if ipinst is not None:
948 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
949
950 return [[head] + frames + [''.join(formatted_exception[0])]]
951
952 def get_records(self, etb, number_of_lines_of_context, tb_offset):
953 try:
954 # Try the default getinnerframes and Alex's: Alex's fixes some
955 # problems, but it generates empty tracebacks for console errors
956 # (5 blanks lines) where none should be returned.
957 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
958 except:
959 # FIXME: I've been getting many crash reports from python 2.3
960 # users, traceable to inspect.py. If I can find a small test-case
961 # to reproduce this, I should either write a better workaround or
962 # file a bug report against inspect (if that's the real problem).
963 # So far, I haven't been able to find an isolated example to
964 # reproduce the problem.
965 inspect_error()
966 traceback.print_exc(file=self.ostream)
967 info('\nUnfortunately, your original traceback can not be constructed.\n')
968 return None
969
970 def get_parts_of_chained_exception(self, evalue):
971 def get_chained_exception(exception_value):
972 cause = getattr(exception_value, '__cause__', None)
973 if cause:
974 return cause
975 return getattr(exception_value, '__context__', None)
976
977 chained_evalue = get_chained_exception(evalue)
978
979 if chained_evalue:
980 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
981
982 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
983 number_of_lines_of_context=5):
984 """Return a nice text document describing the traceback."""
985
986 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
987 tb_offset)
988
989 colors = self.Colors # just a shorthand + quicker name lookup
990 colorsnormal = colors.Normal # used a lot
991 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
992 structured_traceback_parts = [head]
993 if py3compat.PY3:
994 chained_exceptions_tb_offset = 0
995 lines_of_context = 3
996 formatted_exceptions = formatted_exception
997 exception = self.get_parts_of_chained_exception(evalue)
998 if exception:
999 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1000 etype, evalue, etb = exception
1001 else:
1002 evalue = None
1003 while evalue:
1004 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1005 chained_exceptions_tb_offset)
1006 exception = self.get_parts_of_chained_exception(evalue)
1007
1008 if exception:
1009 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1010 etype, evalue, etb = exception
1011 else:
1012 evalue = None
1013
1014 # we want to see exceptions in a reversed order:
1015 # the first exception should be on top
1016 for formatted_exception in reversed(formatted_exceptions):
1017 structured_traceback_parts += formatted_exception
1018 else:
1019 structured_traceback_parts += formatted_exception[0]
1020
1021 return structured_traceback_parts
1022
1023 def debugger(self, force=False):
988 1024 """Call up the pdb debugger if desired, always clean up the tb
989 1025 reference.
990 1026
@@ -1014,7 +1050,7 b' class VerboseTB(TBTools):'
1014 1050 with display_trap:
1015 1051 self.pdb.reset()
1016 1052 # Find the right frame so we don't pop up inside ipython itself
1017 if hasattr(self,'tb') and self.tb is not None:
1053 if hasattr(self, 'tb') and self.tb is not None:
1018 1054 etb = self.tb
1019 1055 else:
1020 1056 etb = self.tb = sys.last_traceback
@@ -1025,7 +1061,7 b' class VerboseTB(TBTools):'
1025 1061 self.pdb.botframe = etb.tb_frame
1026 1062 self.pdb.interaction(self.tb.tb_frame, self.tb)
1027 1063
1028 if hasattr(self,'tb'):
1064 if hasattr(self, 'tb'):
1029 1065 del self.tb
1030 1066
1031 1067 def handler(self, info=None):
@@ -1050,6 +1086,7 b' class VerboseTB(TBTools):'
1050 1086 except KeyboardInterrupt:
1051 1087 print("\nKeyboardInterrupt")
1052 1088
1089
1053 1090 #----------------------------------------------------------------------------
1054 1091 class FormattedTB(VerboseTB, ListTB):
1055 1092 """Subclass ListTB but allow calling with a traceback.
@@ -1069,7 +1106,7 b' class FormattedTB(VerboseTB, ListTB):'
1069 1106 check_cache=None):
1070 1107
1071 1108 # NEVER change the order of this list. Put new modes at the end:
1072 self.valid_modes = ['Plain','Context','Verbose']
1109 self.valid_modes = ['Plain', 'Context', 'Verbose']
1073 1110 self.verbose_modes = self.valid_modes[1:3]
1074 1111
1075 1112 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
@@ -1083,19 +1120,19 b' class FormattedTB(VerboseTB, ListTB):'
1083 1120 # set_mode also sets the tb_join_char attribute
1084 1121 self.set_mode(mode)
1085 1122
1086 def _extract_tb(self,tb):
1123 def _extract_tb(self, tb):
1087 1124 if tb:
1088 1125 return traceback.extract_tb(tb)
1089 1126 else:
1090 1127 return None
1091 1128
1092 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1129 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1093 1130 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1094 1131 mode = self.mode
1095 1132 if mode in self.verbose_modes:
1096 1133 # Verbose modes need a full traceback
1097 1134 return VerboseTB.structured_traceback(
1098 self, etype, value, tb, tb_offset, context
1135 self, etype, value, tb, tb_offset, number_of_lines_of_context
1099 1136 )
1100 1137 else:
1101 1138 # We must check the source cache because otherwise we can print
@@ -1104,7 +1141,7 b' class FormattedTB(VerboseTB, ListTB):'
1104 1141 # Now we can extract and format the exception
1105 1142 elist = self._extract_tb(tb)
1106 1143 return ListTB.structured_traceback(
1107 self, etype, value, elist, tb_offset, context
1144 self, etype, value, elist, tb_offset, number_of_lines_of_context
1108 1145 )
1109 1146
1110 1147 def stb2text(self, stb):
@@ -1112,18 +1149,18 b' class FormattedTB(VerboseTB, ListTB):'
1112 1149 return self.tb_join_char.join(stb)
1113 1150
1114 1151
1115 def set_mode(self,mode=None):
1152 def set_mode(self, mode=None):
1116 1153 """Switch to the desired mode.
1117 1154
1118 1155 If mode is not specified, cycles through the available modes."""
1119 1156
1120 1157 if not mode:
1121 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1158 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1122 1159 len(self.valid_modes)
1123 1160 self.mode = self.valid_modes[new_idx]
1124 1161 elif mode not in self.valid_modes:
1125 raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n'
1126 'Valid modes: '+str(self.valid_modes))
1162 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1163 'Valid modes: ' + str(self.valid_modes))
1127 1164 else:
1128 1165 self.mode = mode
1129 1166 # include variable details only in 'Verbose' mode
@@ -1131,7 +1168,7 b' class FormattedTB(VerboseTB, ListTB):'
1131 1168 # Set the join character for generating text tracebacks
1132 1169 self.tb_join_char = self._join_chars[self.mode]
1133 1170
1134 # some convenient shorcuts
1171 # some convenient shortcuts
1135 1172 def plain(self):
1136 1173 self.set_mode(self.valid_modes[0])
1137 1174
@@ -1141,6 +1178,7 b' class FormattedTB(VerboseTB, ListTB):'
1141 1178 def verbose(self):
1142 1179 self.set_mode(self.valid_modes[2])
1143 1180
1181
1144 1182 #----------------------------------------------------------------------------
1145 1183 class AutoFormattedTB(FormattedTB):
1146 1184 """A traceback printer which can be called on the fly.
@@ -1156,8 +1194,8 b' class AutoFormattedTB(FormattedTB):'
1156 1194 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1157 1195 """
1158 1196
1159 def __call__(self,etype=None,evalue=None,etb=None,
1160 out=None,tb_offset=None):
1197 def __call__(self, etype=None, evalue=None, etb=None,
1198 out=None, tb_offset=None):
1161 1199 """Print out a formatted exception traceback.
1162 1200
1163 1201 Optional arguments:
@@ -1167,7 +1205,6 b' class AutoFormattedTB(FormattedTB):'
1167 1205 per-call basis (this overrides temporarily the instance's tb_offset
1168 1206 given at initialization time. """
1169 1207
1170
1171 1208 if out is None:
1172 1209 out = self.ostream
1173 1210 out.flush()
@@ -1182,33 +1219,36 b' class AutoFormattedTB(FormattedTB):'
1182 1219 print("\nKeyboardInterrupt")
1183 1220
1184 1221 def structured_traceback(self, etype=None, value=None, tb=None,
1185 tb_offset=None, context=5):
1222 tb_offset=None, number_of_lines_of_context=5):
1186 1223 if etype is None:
1187 etype,value,tb = sys.exc_info()
1224 etype, value, tb = sys.exc_info()
1188 1225 self.tb = tb
1189 1226 return FormattedTB.structured_traceback(
1190 self, etype, value, tb, tb_offset, context)
1227 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1228
1191 1229
1192 1230 #---------------------------------------------------------------------------
1193 1231
1194 1232 # A simple class to preserve Nathan's original functionality.
1195 1233 class ColorTB(FormattedTB):
1196 1234 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1197 def __init__(self,color_scheme='Linux',call_pdb=0):
1198 FormattedTB.__init__(self,color_scheme=color_scheme,
1235
1236 def __init__(self, color_scheme='Linux', call_pdb=0):
1237 FormattedTB.__init__(self, color_scheme=color_scheme,
1199 1238 call_pdb=call_pdb)
1200 1239
1201 1240
1202 1241 class SyntaxTB(ListTB):
1203 1242 """Extension which holds some state: the last exception value"""
1204 1243
1205 def __init__(self,color_scheme = 'NoColor'):
1206 ListTB.__init__(self,color_scheme)
1244 def __init__(self, color_scheme='NoColor'):
1245 ListTB.__init__(self, color_scheme)
1207 1246 self.last_syntax_error = None
1208 1247
1209 1248 def __call__(self, etype, value, elist):
1210 1249 self.last_syntax_error = value
1211 ListTB.__call__(self,etype,value,elist)
1250
1251 ListTB.__call__(self, etype, value, elist)
1212 1252
1213 1253 def structured_traceback(self, etype, value, elist, tb_offset=None,
1214 1254 context=5):
@@ -1223,7 +1263,7 b' class SyntaxTB(ListTB):'
1223 1263 if newtext:
1224 1264 value.text = newtext
1225 1265 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1226 tb_offset=tb_offset, context=context)
1266 tb_offset=tb_offset, context=context)
1227 1267
1228 1268 def clear_err_state(self):
1229 1269 """Return the current error state and clear it"""
@@ -1236,7 +1276,46 b' class SyntaxTB(ListTB):'
1236 1276 return ''.join(stb)
1237 1277
1238 1278
1279 # some internal-use functions
1280 def text_repr(value):
1281 """Hopefully pretty robust repr equivalent."""
1282 # this is pretty horrible but should always return *something*
1283 try:
1284 return pydoc.text.repr(value)
1285 except KeyboardInterrupt:
1286 raise
1287 except:
1288 try:
1289 return repr(value)
1290 except KeyboardInterrupt:
1291 raise
1292 except:
1293 try:
1294 # all still in an except block so we catch
1295 # getattr raising
1296 name = getattr(value, '__name__', None)
1297 if name:
1298 # ick, recursion
1299 return text_repr(name)
1300 klass = getattr(value, '__class__', None)
1301 if klass:
1302 return '%s instance' % text_repr(klass)
1303 except KeyboardInterrupt:
1304 raise
1305 except:
1306 return 'UNRECOVERABLE REPR FAILURE'
1307
1308
1309 def eqrepr(value, repr=text_repr):
1310 return '=%s' % repr(value)
1311
1312
1313 def nullrepr(value, repr=text_repr):
1314 return ''
1315
1316
1239 1317 #----------------------------------------------------------------------------
1318
1240 1319 # module testing (minimal)
1241 1320 if __name__ == "__main__":
1242 1321 def spam(c, d_e):
@@ -1,6 +1,7 b''
1 1 {
2 2 "metadata": {
3 "name": ""
3 "name": "",
4 "signature": "sha256:9d47889f0678e9685429071216d0f3354db59bb66489f3225bcadfb6a1a9bbba"
4 5 },
5 6 "nbformat": 3,
6 7 "nbformat_minor": 0,
@@ -21,7 +22,8 b''
21 22 "evalue": "message",
22 23 "output_type": "pyerr",
23 24 "traceback": [
24 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mException\u001b[0m Traceback (most recent call last)",
25 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
26 "\u001b[1;31mException\u001b[0m Traceback (most recent call last)",
25 27 "\u001b[1;32m<ipython-input-1-335814d14fc1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"message\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
26 28 "\u001b[1;31mException\u001b[0m: message"
27 29 ]
General Comments 0
You need to be logged in to leave comments. Login now