Show More
@@ -95,6 +95,8 b' import pydoc' | |||||
95 | import sys |
|
95 | import sys | |
96 | import time |
|
96 | import time | |
97 | import traceback |
|
97 | import traceback | |
|
98 | from types import TracebackType | |||
|
99 | from typing import Tuple, List, Any, Optional | |||
98 |
|
100 | |||
99 | import stack_data |
|
101 | import stack_data | |
100 | from pygments.formatters.terminal256 import Terminal256Formatter |
|
102 | from pygments.formatters.terminal256 import Terminal256Formatter | |
@@ -130,7 +132,7 b" DEFAULT_SCHEME = 'NoColor'" | |||||
130 | # (SyntaxErrors have to be treated specially because they have no traceback) |
|
132 | # (SyntaxErrors have to be treated specially because they have no traceback) | |
131 |
|
133 | |||
132 |
|
134 | |||
133 | def _format_traceback_lines(lines, Colors, has_colors, lvals): |
|
135 | def _format_traceback_lines(lines, Colors, has_colors: bool, lvals): | |
134 | """ |
|
136 | """ | |
135 | Format tracebacks lines with pointing arrow, leading numbers... |
|
137 | Format tracebacks lines with pointing arrow, leading numbers... | |
136 |
|
138 | |||
@@ -250,21 +252,26 b' class TBTools(colorable.Colorable):' | |||||
250 |
|
252 | |||
251 | ostream = property(_get_ostream, _set_ostream) |
|
253 | ostream = property(_get_ostream, _set_ostream) | |
252 |
|
254 | |||
253 | def get_parts_of_chained_exception(self, evalue): |
|
255 | @staticmethod | |
254 |
|
|
256 | def _get_chained_exception(exception_value): | |
255 |
|
|
257 | cause = getattr(exception_value, "__cause__", None) | |
256 |
|
|
258 | if cause: | |
257 |
|
|
259 | return cause | |
258 |
|
|
260 | if getattr(exception_value, "__suppress_context__", False): | |
259 |
|
|
261 | return None | |
260 |
|
|
262 | return getattr(exception_value, "__context__", None) | |
|
263 | ||||
|
264 | def get_parts_of_chained_exception( | |||
|
265 | self, evalue | |||
|
266 | ) -> Optional[Tuple[type, BaseException, TracebackType]]: | |||
261 |
|
267 | |||
262 | chained_evalue = get_chained_exception(evalue) |
|
268 | chained_evalue = self._get_chained_exception(evalue) | |
263 |
|
269 | |||
264 | if chained_evalue: |
|
270 | if chained_evalue: | |
265 | return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__ |
|
271 | return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__ | |
|
272 | return None | |||
266 |
|
273 | |||
267 | def prepare_chained_exception_message(self, cause): |
|
274 | def prepare_chained_exception_message(self, cause) -> List[Any]: | |
268 | direct_cause = "\nThe above exception was the direct cause of the following exception:\n" |
|
275 | direct_cause = "\nThe above exception was the direct cause of the following exception:\n" | |
269 | exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n" |
|
276 | exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n" | |
270 |
|
277 | |||
@@ -275,7 +282,7 b' class TBTools(colorable.Colorable):' | |||||
275 | return message |
|
282 | return message | |
276 |
|
283 | |||
277 | @property |
|
284 | @property | |
278 | def has_colors(self): |
|
285 | def has_colors(self) -> bool: | |
279 | return self.color_scheme_table.active_scheme_name.lower() != "nocolor" |
|
286 | return self.color_scheme_table.active_scheme_name.lower() != "nocolor" | |
280 |
|
287 | |||
281 | def set_colors(self, *args, **kw): |
|
288 | def set_colors(self, *args, **kw): | |
@@ -304,7 +311,7 b' class TBTools(colorable.Colorable):' | |||||
304 | """Convert a structured traceback (a list) to a string.""" |
|
311 | """Convert a structured traceback (a list) to a string.""" | |
305 | return '\n'.join(stb) |
|
312 | return '\n'.join(stb) | |
306 |
|
313 | |||
307 | def text(self, etype, value, tb, tb_offset=None, context=5): |
|
314 | def text(self, etype, value, tb, tb_offset: Optional[int] = None, context=5): | |
308 | """Return formatted traceback. |
|
315 | """Return formatted traceback. | |
309 |
|
316 | |||
310 | Subclasses may override this if they add extra arguments. |
|
317 | Subclasses may override this if they add extra arguments. | |
@@ -313,8 +320,9 b' class TBTools(colorable.Colorable):' | |||||
313 | tb_offset, context) |
|
320 | tb_offset, context) | |
314 | return self.stb2text(tb_list) |
|
321 | return self.stb2text(tb_list) | |
315 |
|
322 | |||
316 | def structured_traceback(self, etype, evalue, tb, tb_offset=None, |
|
323 | def structured_traceback( | |
317 | context=5, mode=None): |
|
324 | self, etype, evalue, tb, tb_offset: Optional[int] = None, context=5, mode=None | |
|
325 | ): | |||
318 | """Return a list of traceback frames. |
|
326 | """Return a list of traceback frames. | |
319 |
|
327 | |||
320 | Must be implemented by each class. |
|
328 | Must be implemented by each class. | |
@@ -357,8 +365,14 b' class ListTB(TBTools):' | |||||
357 | else: |
|
365 | else: | |
358 | return None |
|
366 | return None | |
359 |
|
367 | |||
360 | def structured_traceback(self, etype, evalue, etb=None, tb_offset=None, |
|
368 | def structured_traceback( | |
361 | context=5): |
|
369 | self, | |
|
370 | etype: type, | |||
|
371 | evalue: BaseException, | |||
|
372 | etb: Optional[TracebackType] = None, | |||
|
373 | tb_offset: Optional[int] = None, | |||
|
374 | context=5, | |||
|
375 | ): | |||
362 | """Return a color formatted string with the traceback info. |
|
376 | """Return a color formatted string with the traceback info. | |
363 |
|
377 | |||
364 | Parameters |
|
378 | Parameters | |
@@ -367,7 +381,7 b' class ListTB(TBTools):' | |||||
367 | Type of the exception raised. |
|
381 | Type of the exception raised. | |
368 | evalue : object |
|
382 | evalue : object | |
369 | Data stored in the exception |
|
383 | Data stored in the exception | |
370 | etb : object |
|
384 | etb : list | TracebackType | None | |
371 | If list: List of frames, see class docstring for details. |
|
385 | If list: List of frames, see class docstring for details. | |
372 | If Traceback: Traceback of the exception. |
|
386 | If Traceback: Traceback of the exception. | |
373 | tb_offset : int, optional |
|
387 | tb_offset : int, optional | |
@@ -394,6 +408,7 b' class ListTB(TBTools):' | |||||
394 | else: |
|
408 | else: | |
395 | elist = [] |
|
409 | elist = [] | |
396 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
410 | tb_offset = self.tb_offset if tb_offset is None else tb_offset | |
|
411 | assert isinstance(tb_offset, int) | |||
397 | Colors = self.Colors |
|
412 | Colors = self.Colors | |
398 | out_list = [] |
|
413 | out_list = [] | |
399 | if elist: |
|
414 | if elist: | |
@@ -594,10 +609,19 b' class VerboseTB(TBTools):' | |||||
594 | traceback, to be used with alternate interpreters (because their own code |
|
609 | traceback, to be used with alternate interpreters (because their own code | |
595 | would appear in the traceback).""" |
|
610 | would appear in the traceback).""" | |
596 |
|
611 | |||
597 | def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None, |
|
612 | def __init__( | |
598 | tb_offset=0, long_header=False, include_vars=True, |
|
613 | self, | |
599 | check_cache=None, debugger_cls = None, |
|
614 | color_scheme: str = "Linux", | |
600 | parent=None, config=None): |
|
615 | call_pdb: bool = False, | |
|
616 | ostream=None, | |||
|
617 | tb_offset: int = 0, | |||
|
618 | long_header: bool = False, | |||
|
619 | include_vars: bool = True, | |||
|
620 | check_cache=None, | |||
|
621 | debugger_cls=None, | |||
|
622 | parent=None, | |||
|
623 | config=None, | |||
|
624 | ): | |||
601 | """Specify traceback offset, headers and color scheme. |
|
625 | """Specify traceback offset, headers and color scheme. | |
602 |
|
626 | |||
603 | Define how many frames to drop from the tracebacks. Calling it with |
|
627 | Define how many frames to drop from the tracebacks. Calling it with | |
@@ -735,7 +759,14 b' class VerboseTB(TBTools):' | |||||
735 | return ['%s%s%s: %s' % (colors.excName, etype_str, |
|
759 | return ['%s%s%s: %s' % (colors.excName, etype_str, | |
736 | colorsnormal, py3compat.cast_unicode(evalue_str))] |
|
760 | colorsnormal, py3compat.cast_unicode(evalue_str))] | |
737 |
|
761 | |||
738 | def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset): |
|
762 | def format_exception_as_a_whole( | |
|
763 | self, | |||
|
764 | etype: type, | |||
|
765 | evalue: BaseException, | |||
|
766 | etb: TracebackType, | |||
|
767 | number_of_lines_of_context, | |||
|
768 | tb_offset: Optional[int], | |||
|
769 | ): | |||
739 | """Formats the header, traceback and exception message for a single exception. |
|
770 | """Formats the header, traceback and exception message for a single exception. | |
740 |
|
771 | |||
741 | This may be called multiple times by Python 3 exception chaining |
|
772 | This may be called multiple times by Python 3 exception chaining | |
@@ -750,6 +781,7 b' class VerboseTB(TBTools):' | |||||
750 | pass |
|
781 | pass | |
751 |
|
782 | |||
752 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
783 | tb_offset = self.tb_offset if tb_offset is None else tb_offset | |
|
784 | assert isinstance(tb_offset, int) | |||
753 | head = self.prepare_header(etype, self.long_header) |
|
785 | head = self.prepare_header(etype, self.long_header) | |
754 | records = self.get_records(etb, number_of_lines_of_context, tb_offset) |
|
786 | records = self.get_records(etb, number_of_lines_of_context, tb_offset) | |
755 |
|
787 | |||
@@ -787,7 +819,9 b' class VerboseTB(TBTools):' | |||||
787 |
|
819 | |||
788 | return [[head] + frames + [''.join(formatted_exception[0])]] |
|
820 | return [[head] + frames + [''.join(formatted_exception[0])]] | |
789 |
|
821 | |||
790 | def get_records(self, etb, number_of_lines_of_context, tb_offset): |
|
822 | def get_records( | |
|
823 | self, etb: TracebackType, number_of_lines_of_context: int, tb_offset: int | |||
|
824 | ): | |||
791 | context = number_of_lines_of_context - 1 |
|
825 | context = number_of_lines_of_context - 1 | |
792 | after = context // 2 |
|
826 | after = context // 2 | |
793 | before = context - after |
|
827 | before = context - after | |
@@ -805,8 +839,14 b' class VerboseTB(TBTools):' | |||||
805 | assert etb is not None |
|
839 | assert etb is not None | |
806 | return list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:] |
|
840 | return list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:] | |
807 |
|
841 | |||
808 | def structured_traceback(self, etype, evalue, etb, tb_offset=None, |
|
842 | def structured_traceback( | |
809 | number_of_lines_of_context=5): |
|
843 | self, | |
|
844 | etype: type, | |||
|
845 | evalue: Optional[BaseException], | |||
|
846 | etb: TracebackType, | |||
|
847 | tb_offset: Optional[int] = None, | |||
|
848 | number_of_lines_of_context: int = 5, | |||
|
849 | ): | |||
810 | """Return a nice text document describing the traceback.""" |
|
850 | """Return a nice text document describing the traceback.""" | |
811 | assert etb is not None |
|
851 | assert etb is not None | |
812 | formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context, |
|
852 | formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context, | |
@@ -821,6 +861,7 b' class VerboseTB(TBTools):' | |||||
821 | formatted_exceptions = formatted_exception |
|
861 | formatted_exceptions = formatted_exception | |
822 | exception = self.get_parts_of_chained_exception(evalue) |
|
862 | exception = self.get_parts_of_chained_exception(evalue) | |
823 | if exception: |
|
863 | if exception: | |
|
864 | assert evalue is not None | |||
824 | formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) |
|
865 | formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) | |
825 | etype, evalue, etb = exception |
|
866 | etype, evalue, etb = exception | |
826 | else: |
|
867 | else: | |
@@ -845,7 +886,7 b' class VerboseTB(TBTools):' | |||||
845 |
|
886 | |||
846 | return structured_traceback_parts |
|
887 | return structured_traceback_parts | |
847 |
|
888 | |||
848 | def debugger(self, force=False): |
|
889 | def debugger(self, force: bool = False): | |
849 | """Call up the pdb debugger if desired, always clean up the tb |
|
890 | """Call up the pdb debugger if desired, always clean up the tb | |
850 | reference. |
|
891 | reference. | |
851 |
|
892 | |||
@@ -879,6 +920,7 b' class VerboseTB(TBTools):' | |||||
879 | else: |
|
920 | else: | |
880 | etb = self.tb = sys.last_traceback |
|
921 | etb = self.tb = sys.last_traceback | |
881 | while self.tb is not None and self.tb.tb_next is not None: |
|
922 | while self.tb is not None and self.tb.tb_next is not None: | |
|
923 | assert self.tb.tb_next is not None | |||
882 | self.tb = self.tb.tb_next |
|
924 | self.tb = self.tb.tb_next | |
883 | if etb and etb.tb_next: |
|
925 | if etb and etb.tb_next: | |
884 | etb = etb.tb_next |
|
926 | etb = etb.tb_next | |
@@ -924,6 +966,8 b' class FormattedTB(VerboseTB, ListTB):' | |||||
924 | occurs with python programs that themselves execute other python code, |
|
966 | occurs with python programs that themselves execute other python code, | |
925 | like Python shells). """ |
|
967 | like Python shells). """ | |
926 |
|
968 | |||
|
969 | mode: str | |||
|
970 | ||||
927 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, |
|
971 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, | |
928 | ostream=None, |
|
972 | ostream=None, | |
929 | tb_offset=0, long_header=False, include_vars=False, |
|
973 | tb_offset=0, long_header=False, include_vars=False, | |
@@ -970,8 +1014,7 b' class FormattedTB(VerboseTB, ListTB):' | |||||
970 | """Convert a structured traceback (a list) to a string.""" |
|
1014 | """Convert a structured traceback (a list) to a string.""" | |
971 | return self.tb_join_char.join(stb) |
|
1015 | return self.tb_join_char.join(stb) | |
972 |
|
1016 | |||
973 |
|
1017 | def set_mode(self, mode: Optional[str] = None): | ||
974 | def set_mode(self, mode=None): |
|
|||
975 | """Switch to the desired mode. |
|
1018 | """Switch to the desired mode. | |
976 |
|
1019 | |||
977 | If mode is not specified, cycles through the available modes.""" |
|
1020 | If mode is not specified, cycles through the available modes.""" | |
@@ -981,9 +1024,12 b' class FormattedTB(VerboseTB, ListTB):' | |||||
981 | len(self.valid_modes) |
|
1024 | len(self.valid_modes) | |
982 | self.mode = self.valid_modes[new_idx] |
|
1025 | self.mode = self.valid_modes[new_idx] | |
983 | elif mode not in self.valid_modes: |
|
1026 | elif mode not in self.valid_modes: | |
984 | raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n' |
|
1027 | raise ValueError( | |
985 | 'Valid modes: ' + str(self.valid_modes)) |
|
1028 | "Unrecognized mode in FormattedTB: <" + mode + ">\n" | |
|
1029 | "Valid modes: " + str(self.valid_modes) | |||
|
1030 | ) | |||
986 | else: |
|
1031 | else: | |
|
1032 | assert isinstance(mode, str) | |||
987 | self.mode = mode |
|
1033 | self.mode = mode | |
988 | # include variable details only in 'Verbose' mode |
|
1034 | # include variable details only in 'Verbose' mode | |
989 | self.include_vars = (self.mode == self.valid_modes[2]) |
|
1035 | self.include_vars = (self.mode == self.valid_modes[2]) | |
@@ -1045,6 +1091,10 b' class AutoFormattedTB(FormattedTB):' | |||||
1045 |
|
1091 | |||
1046 | def structured_traceback(self, etype=None, value=None, tb=None, |
|
1092 | def structured_traceback(self, etype=None, value=None, tb=None, | |
1047 | tb_offset=None, number_of_lines_of_context=5): |
|
1093 | tb_offset=None, number_of_lines_of_context=5): | |
|
1094 | ||||
|
1095 | etype: type | |||
|
1096 | value: BaseException | |||
|
1097 | # tb: TracebackType or tupleof tb types ? | |||
1048 | if etype is None: |
|
1098 | if etype is None: | |
1049 | etype, value, tb = sys.exc_info() |
|
1099 | etype, value, tb = sys.exc_info() | |
1050 | if isinstance(tb, tuple): |
|
1100 | if isinstance(tb, tuple): |
General Comments 0
You need to be logged in to leave comments.
Login now