##// END OF EJS Templates
Add chained exception to 'Plain' mode
Quentin Peter -
Show More
@@ -530,6 +530,30 b' class TBTools(colorable.Colorable):'
530
530
531 ostream = property(_get_ostream, _set_ostream)
531 ostream = property(_get_ostream, _set_ostream)
532
532
533 def get_parts_of_chained_exception(self, evalue):
534 def get_chained_exception(exception_value):
535 cause = getattr(exception_value, '__cause__', None)
536 if cause:
537 return cause
538 if getattr(exception_value, '__suppress_context__', False):
539 return None
540 return getattr(exception_value, '__context__', None)
541
542 chained_evalue = get_chained_exception(evalue)
543
544 if chained_evalue:
545 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
546
547 def prepare_chained_exception_message(self, cause):
548 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
549 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
550
551 if cause:
552 message = [[direct_cause]]
553 else:
554 message = [[exception_during_handling]]
555 return message
556
533 def set_colors(self, *args, **kw):
557 def set_colors(self, *args, **kw):
534 """Shorthand access to the color table scheme selector method."""
558 """Shorthand access to the color table scheme selector method."""
535
559
@@ -603,7 +627,7 b' class ListTB(TBTools):'
603 self.ostream.write(self.text(etype, value, elist))
627 self.ostream.write(self.text(etype, value, elist))
604 self.ostream.write('\n')
628 self.ostream.write('\n')
605
629
606 def structured_traceback(self, etype, value, elist, tb_offset=None,
630 def structured_traceback(self, etype, evalue, etb=None, tb_offset=None,
607 context=5):
631 context=5):
608 """Return a color formatted string with the traceback info.
632 """Return a color formatted string with the traceback info.
609
633
@@ -612,15 +636,15 b' class ListTB(TBTools):'
612 etype : exception type
636 etype : exception type
613 Type of the exception raised.
637 Type of the exception raised.
614
638
615 value : object
639 evalue : object
616 Data stored in the exception
640 Data stored in the exception
617
641
618 elist : list
642 etb : traceback
619 List of frames, see class docstring for details.
643 Traceback of the exception.
620
644
621 tb_offset : int, optional
645 tb_offset : int, optional
622 Number of frames in the traceback to skip. If not given, the
646 Number of frames in the traceback to skip. If not given, the
623 instance value is used (set in constructor).
647 instance evalue is used (set in constructor).
624
648
625 context : int, optional
649 context : int, optional
626 Number of lines of context information to print.
650 Number of lines of context information to print.
@@ -629,6 +653,14 b' class ListTB(TBTools):'
629 -------
653 -------
630 String with formatted exception.
654 String with formatted exception.
631 """
655 """
656 # if chained_exc_ids is None:
657 chained_exc_ids = set()
658 if isinstance(etb, list):
659 elist = etb
660 elif etb is not None:
661 elist = self._extract_tb(etb)
662 else:
663 elist = []
632 tb_offset = self.tb_offset if tb_offset is None else tb_offset
664 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 Colors = self.Colors
665 Colors = self.Colors
634 out_list = []
666 out_list = []
@@ -641,9 +673,21 b' class ListTB(TBTools):'
641 (Colors.normalEm, Colors.Normal) + '\n')
673 (Colors.normalEm, Colors.Normal) + '\n')
642 out_list.extend(self._format_list(elist))
674 out_list.extend(self._format_list(elist))
643 # The exception info should be a single entry in the list.
675 # The exception info should be a single entry in the list.
644 lines = ''.join(self._format_exception_only(etype, value))
676 lines = ''.join(self._format_exception_only(etype, evalue))
645 out_list.append(lines)
677 out_list.append(lines)
646
678
679 exception = self.get_parts_of_chained_exception(evalue)
680
681 if exception and not id(exception[1]) in chained_exc_ids:
682 etype, evalue, etb = exception
683 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
684 chained_exceptions_tb_offset = 0
685 out_list = (self.structured_traceback(
686 etype, evalue, etb, chained_exceptions_tb_offset, context)
687 + self.prepare_chained_exception_message(
688 evalue.__cause__)[0]
689 + out_list)
690
647 return out_list
691 return out_list
648
692
649 def _format_list(self, extracted_list):
693 def _format_list(self, extracted_list):
@@ -763,7 +807,7 b' class ListTB(TBTools):'
763 etype : exception type
807 etype : exception type
764 value : exception value
808 value : exception value
765 """
809 """
766 return ListTB.structured_traceback(self, etype, value, [])
810 return ListTB.structured_traceback(self, etype, value)
767
811
768 def show_exception_only(self, etype, evalue):
812 def show_exception_only(self, etype, evalue):
769 """Only print the exception type and message, without a traceback.
813 """Only print the exception type and message, without a traceback.
@@ -1013,16 +1057,6 b' class VerboseTB(TBTools):'
1013 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1057 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1014 _line_format)))
1058 _line_format)))
1015
1059
1016 def prepare_chained_exception_message(self, cause):
1017 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1018 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1019
1020 if cause:
1021 message = [[direct_cause]]
1022 else:
1023 message = [[exception_during_handling]]
1024 return message
1025
1026 def prepare_header(self, etype, long_version=False):
1060 def prepare_header(self, etype, long_version=False):
1027 colors = self.Colors # just a shorthand + quicker name lookup
1061 colors = self.Colors # just a shorthand + quicker name lookup
1028 colorsnormal = colors.Normal # used a lot
1062 colorsnormal = colors.Normal # used a lot
@@ -1117,20 +1151,6 b' class VerboseTB(TBTools):'
1117 info('\nUnfortunately, your original traceback can not be constructed.\n')
1151 info('\nUnfortunately, your original traceback can not be constructed.\n')
1118 return None
1152 return None
1119
1153
1120 def get_parts_of_chained_exception(self, evalue):
1121 def get_chained_exception(exception_value):
1122 cause = getattr(exception_value, '__cause__', None)
1123 if cause:
1124 return cause
1125 if getattr(exception_value, '__suppress_context__', False):
1126 return None
1127 return getattr(exception_value, '__context__', None)
1128
1129 chained_evalue = get_chained_exception(evalue)
1130
1131 if chained_evalue:
1132 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1133
1134 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1154 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1135 number_of_lines_of_context=5):
1155 number_of_lines_of_context=5):
1136 """Return a nice text document describing the traceback."""
1156 """Return a nice text document describing the traceback."""
@@ -1294,9 +1314,8 b' class FormattedTB(VerboseTB, ListTB):'
1294 # out-of-date source code.
1314 # out-of-date source code.
1295 self.check_cache()
1315 self.check_cache()
1296 # Now we can extract and format the exception
1316 # Now we can extract and format the exception
1297 elist = self._extract_tb(tb)
1298 return ListTB.structured_traceback(
1317 return ListTB.structured_traceback(
1299 self, etype, value, elist, tb_offset, number_of_lines_of_context
1318 self, etype, value, tb, tb_offset, number_of_lines_of_context
1300 )
1319 )
1301
1320
1302 def stb2text(self, stb):
1321 def stb2text(self, stb):
General Comments 0
You need to be logged in to leave comments. Login now