##// END OF EJS Templates
Annotate and check typing in ultratb
Matthias Bussonnier -
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 def get_chained_exception(exception_value):
256 def _get_chained_exception(exception_value):
255 cause = getattr(exception_value, '__cause__', None)
257 cause = getattr(exception_value, "__cause__", None)
256 if cause:
258 if cause:
257 return cause
259 return cause
258 if getattr(exception_value, '__suppress_context__', False):
260 if getattr(exception_value, "__suppress_context__", False):
259 return None
261 return None
260 return getattr(exception_value, '__context__', None)
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