##// 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 296 tt.AssertPrints("ValueError", suppress=False):
297 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 319 class RecursionTest(unittest.TestCase):
301 320 DEFINITIONS = """
@@ -530,6 +530,30 b' class TBTools(colorable.Colorable):'
530 530
531 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 557 def set_colors(self, *args, **kw):
534 558 """Shorthand access to the color table scheme selector method."""
535 559
@@ -603,7 +627,7 b' class ListTB(TBTools):'
603 627 self.ostream.write(self.text(etype, value, elist))
604 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 631 context=5):
608 632 """Return a color formatted string with the traceback info.
609 633
@@ -612,15 +636,16 b' class ListTB(TBTools):'
612 636 etype : exception type
613 637 Type of the exception raised.
614 638
615 value : object
639 evalue : object
616 640 Data stored in the exception
617 641
618 elist : list
619 List of frames, see class docstring for details.
642 etb : object
643 If list: List of frames, see class docstring for details.
644 If Traceback: Traceback of the exception.
620 645
621 646 tb_offset : int, optional
622 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 650 context : int, optional
626 651 Number of lines of context information to print.
@@ -629,6 +654,19 b' class ListTB(TBTools):'
629 654 -------
630 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 670 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 671 Colors = self.Colors
634 672 out_list = []
@@ -641,9 +679,25 b' class ListTB(TBTools):'
641 679 (Colors.normalEm, Colors.Normal) + '\n')
642 680 out_list.extend(self._format_list(elist))
643 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 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 701 return out_list
648 702
649 703 def _format_list(self, extracted_list):
@@ -763,7 +817,7 b' class ListTB(TBTools):'
763 817 etype : exception type
764 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 822 def show_exception_only(self, etype, evalue):
769 823 """Only print the exception type and message, without a traceback.
@@ -1013,16 +1067,6 b' class VerboseTB(TBTools):'
1013 1067 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1014 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 1070 def prepare_header(self, etype, long_version=False):
1027 1071 colors = self.Colors # just a shorthand + quicker name lookup
1028 1072 colorsnormal = colors.Normal # used a lot
@@ -1117,20 +1161,6 b' class VerboseTB(TBTools):'
1117 1161 info('\nUnfortunately, your original traceback can not be constructed.\n')
1118 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 1164 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1135 1165 number_of_lines_of_context=5):
1136 1166 """Return a nice text document describing the traceback."""
@@ -1294,9 +1324,8 b' class FormattedTB(VerboseTB, ListTB):'
1294 1324 # out-of-date source code.
1295 1325 self.check_cache()
1296 1326 # Now we can extract and format the exception
1297 elist = self._extract_tb(tb)
1298 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 1331 def stb2text(self, stb):
General Comments 0
You need to be logged in to leave comments. Login now