##// END OF EJS Templates
Merge pull request #11999 from impact27/plain_chained...
Matthias Bussonnier -
r25322:a4c0db7f merge
parent child Browse files
Show More
@@ -296,6 +296,25 b' except Exception:'
296 tt.AssertPrints("ValueError", suppress=False):
296 tt.AssertPrints("ValueError", suppress=False):
297 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
297 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
298
298
299 def test_plain_direct_cause_error(self):
300 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
301 ip.run_cell("%xmode Plain")
302 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
303 ip.run_cell("%xmode Verbose")
304
305 def test_plain_exception_during_handling_error(self):
306 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
307 ip.run_cell("%xmode Plain")
308 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
309 ip.run_cell("%xmode Verbose")
310
311 def test_plain_suppress_exception_chaining(self):
312 with tt.AssertNotPrints("ZeroDivisionError"), \
313 tt.AssertPrints("ValueError", suppress=False):
314 ip.run_cell("%xmode Plain")
315 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
316 ip.run_cell("%xmode Verbose")
317
299
318
300 class RecursionTest(unittest.TestCase):
319 class RecursionTest(unittest.TestCase):
301 DEFINITIONS = """
320 DEFINITIONS = """
@@ -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,16 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 : object
619 List of frames, see class docstring for details.
643 If list: List of frames, see class docstring for details.
644 If Traceback: Traceback of the exception.
620
645
621 tb_offset : int, optional
646 tb_offset : int, optional
622 Number of frames in the traceback to skip. If not given, the
647 Number of frames in the traceback to skip. If not given, the
623 instance value is used (set in constructor).
648 instance evalue is used (set in constructor).
624
649
625 context : int, optional
650 context : int, optional
626 Number of lines of context information to print.
651 Number of lines of context information to print.
@@ -629,6 +654,19 b' class ListTB(TBTools):'
629 -------
654 -------
630 String with formatted exception.
655 String with formatted exception.
631 """
656 """
657 # This is a workaround to get chained_exc_ids in recursive calls
658 # etb should not be a tuple if structured_traceback is not recursive
659 if isinstance(etb, tuple):
660 etb, chained_exc_ids = etb
661 else:
662 chained_exc_ids = set()
663
664 if isinstance(etb, list):
665 elist = etb
666 elif etb is not None:
667 elist = self._extract_tb(etb)
668 else:
669 elist = []
632 tb_offset = self.tb_offset if tb_offset is None else tb_offset
670 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 Colors = self.Colors
671 Colors = self.Colors
634 out_list = []
672 out_list = []
@@ -641,9 +679,25 b' class ListTB(TBTools):'
641 (Colors.normalEm, Colors.Normal) + '\n')
679 (Colors.normalEm, Colors.Normal) + '\n')
642 out_list.extend(self._format_list(elist))
680 out_list.extend(self._format_list(elist))
643 # The exception info should be a single entry in the list.
681 # The exception info should be a single entry in the list.
644 lines = ''.join(self._format_exception_only(etype, value))
682 lines = ''.join(self._format_exception_only(etype, evalue))
645 out_list.append(lines)
683 out_list.append(lines)
646
684
685 exception = self.get_parts_of_chained_exception(evalue)
686
687 if exception and not id(exception[1]) in chained_exc_ids:
688 chained_exception_message = self.prepare_chained_exception_message(
689 evalue.__cause__)[0]
690 etype, evalue, etb = exception
691 # Trace exception to avoid infinite 'cause' loop
692 chained_exc_ids.add(id(exception[1]))
693 chained_exceptions_tb_offset = 0
694 out_list = (
695 self.structured_traceback(
696 etype, evalue, (etb, chained_exc_ids),
697 chained_exceptions_tb_offset, context)
698 + chained_exception_message
699 + out_list)
700
647 return out_list
701 return out_list
648
702
649 def _format_list(self, extracted_list):
703 def _format_list(self, extracted_list):
@@ -763,7 +817,7 b' class ListTB(TBTools):'
763 etype : exception type
817 etype : exception type
764 value : exception value
818 value : exception value
765 """
819 """
766 return ListTB.structured_traceback(self, etype, value, [])
820 return ListTB.structured_traceback(self, etype, value)
767
821
768 def show_exception_only(self, etype, evalue):
822 def show_exception_only(self, etype, evalue):
769 """Only print the exception type and message, without a traceback.
823 """Only print the exception type and message, without a traceback.
@@ -1013,16 +1067,6 b' class VerboseTB(TBTools):'
1013 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1067 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1014 _line_format)))
1068 _line_format)))
1015
1069
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):
1070 def prepare_header(self, etype, long_version=False):
1027 colors = self.Colors # just a shorthand + quicker name lookup
1071 colors = self.Colors # just a shorthand + quicker name lookup
1028 colorsnormal = colors.Normal # used a lot
1072 colorsnormal = colors.Normal # used a lot
@@ -1117,20 +1161,6 b' class VerboseTB(TBTools):'
1117 info('\nUnfortunately, your original traceback can not be constructed.\n')
1161 info('\nUnfortunately, your original traceback can not be constructed.\n')
1118 return None
1162 return None
1119
1163
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,
1164 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1135 number_of_lines_of_context=5):
1165 number_of_lines_of_context=5):
1136 """Return a nice text document describing the traceback."""
1166 """Return a nice text document describing the traceback."""
@@ -1294,9 +1324,8 b' class FormattedTB(VerboseTB, ListTB):'
1294 # out-of-date source code.
1324 # out-of-date source code.
1295 self.check_cache()
1325 self.check_cache()
1296 # Now we can extract and format the exception
1326 # Now we can extract and format the exception
1297 elist = self._extract_tb(tb)
1298 return ListTB.structured_traceback(
1327 return ListTB.structured_traceback(
1299 self, etype, value, elist, tb_offset, number_of_lines_of_context
1328 self, etype, value, tb, tb_offset, number_of_lines_of_context
1300 )
1329 )
1301
1330
1302 def stb2text(self, stb):
1331 def stb2text(self, stb):
General Comments 0
You need to be logged in to leave comments. Login now