##// END OF EJS Templates
Backport PR #14010: try to fix tbcode
Matthias Bussonnier -
Show More
@@ -89,20 +89,22 b' Inheritance diagram:'
89 89 #*****************************************************************************
90 90
91 91
92 import functools
92 93 import inspect
93 94 import linecache
94 95 import pydoc
95 96 import sys
96 97 import time
97 98 import traceback
99 import types
98 100 from types import TracebackType
99 from typing import Tuple, List, Any, Optional
101 from typing import Any, List, Optional, Tuple
100 102
101 103 import stack_data
102 from stack_data import FrameInfo as SDFrameInfo
103 104 from pygments.formatters.terminal256 import Terminal256Formatter
104 105 from pygments.styles import get_style_by_name
105 106
107 import IPython.utils.colorable as colorable
106 108 # IPython's own modules
107 109 from IPython import get_ipython
108 110 from IPython.core import debugger
@@ -113,8 +115,6 b' from IPython.utils import path as util_path'
113 115 from IPython.utils import py3compat
114 116 from IPython.utils.terminal import get_terminal_size
115 117
116 import IPython.utils.colorable as colorable
117
118 118 # Globals
119 119 # amount of space to put line numbers before verbose tracebacks
120 120 INDENT_SIZE = 8
@@ -135,6 +135,54 b' FAST_THRESHOLD = 10_000'
135 135 # (SyntaxErrors have to be treated specially because they have no traceback)
136 136
137 137
138 @functools.lru_cache()
139 def count_lines_in_py_file(filename: str) -> int:
140 """
141 Given a filename, returns the number of lines in the file
142 if it ends with the extension ".py". Otherwise, returns 0.
143 """
144 if not filename.endswith(".py"):
145 return 0
146 else:
147 try:
148 with open(filename, "r") as file:
149 s = sum(1 for line in file)
150 except UnicodeError:
151 return 0
152 return s
153
154 """
155 Given a frame object, returns the total number of lines in the file
156 if the filename ends with the extension ".py". Otherwise, returns 0.
157 """
158
159
160 def get_line_number_of_frame(frame: types.FrameType) -> int:
161 """
162 Given a frame object, returns the total number of lines in the file
163 containing the frame's code object, or the number of lines in the
164 frame's source code if the file is not available.
165
166 Parameters
167 ----------
168 frame : FrameType
169 The frame object whose line number is to be determined.
170
171 Returns
172 -------
173 int
174 The total number of lines in the file containing the frame's
175 code object, or the number of lines in the frame's source code
176 if the file is not available.
177 """
178 filename = frame.f_code.co_filename
179 if filename is None:
180 print("No file....")
181 lines, first = inspect.getsourcelines(frame)
182 return first + len(lines)
183 return count_lines_in_py_file(filename)
184
185
138 186 def _format_traceback_lines(lines, Colors, has_colors: bool, lvals):
139 187 """
140 188 Format tracebacks lines with pointing arrow, leading numbers...
@@ -194,8 +242,8 b' def _simple_format_traceback_lines(lnum, index, lines, Colors, lvals, _line_form'
194 242 """
195 243 numbers_width = INDENT_SIZE - 1
196 244 res = []
197
198 245 for i, line in enumerate(lines, lnum - index):
246 # assert isinstance(line, str)
199 247 line = py3compat.cast_unicode(line)
200 248
201 249 new_line, err = _line_format(line, "str")
@@ -396,7 +444,7 b' class TBTools(colorable.Colorable):'
396 444 evalue: Optional[BaseException],
397 445 etb: Optional[TracebackType] = None,
398 446 tb_offset: Optional[int] = None,
399 context=5,
447 number_of_lines_of_context: int = 5,
400 448 ):
401 449 """Return a list of traceback frames.
402 450
@@ -497,7 +545,7 b' class ListTB(TBTools):'
497 545
498 546 exception = self.get_parts_of_chained_exception(evalue)
499 547
500 if exception and not id(exception[1]) in chained_exc_ids:
548 if exception and (id(exception[1]) not in chained_exc_ids):
501 549 chained_exception_message = (
502 550 self.prepare_chained_exception_message(evalue.__cause__)[0]
503 551 if evalue is not None
@@ -509,8 +557,12 b' class ListTB(TBTools):'
509 557 chained_exceptions_tb_offset = 0
510 558 out_list = (
511 559 self.structured_traceback(
512 etype, evalue, (etb, chained_exc_ids),
513 chained_exceptions_tb_offset, context)
560 etype,
561 evalue,
562 (etb, chained_exc_ids), # type: ignore
563 chained_exceptions_tb_offset,
564 context,
565 )
514 566 + chained_exception_message
515 567 + out_list)
516 568
@@ -673,27 +725,41 b' class FrameInfo:'
673 725 """
674 726
675 727 description: Optional[str]
676 filename: str
677 lineno: int
728 filename: Optional[str]
729 lineno: Tuple[int]
730 # number of context lines to use
731 context: Optional[int]
678 732
679 733 @classmethod
680 734 def _from_stack_data_FrameInfo(cls, frame_info):
681 735 return cls(
682 736 getattr(frame_info, "description", None),
683 getattr(frame_info, "filename", None),
684 getattr(frame_info, "lineno", None),
737 getattr(frame_info, "filename", None), # type: ignore[arg-type]
738 getattr(frame_info, "lineno", None), # type: ignore[arg-type]
685 739 getattr(frame_info, "frame", None),
686 740 getattr(frame_info, "code", None),
687 741 sd=frame_info,
742 context=None,
688 743 )
689 744
690 def __init__(self, description, filename, lineno, frame, code, sd=None):
745 def __init__(
746 self,
747 description: Optional[str],
748 filename: str,
749 lineno: Tuple[int],
750 frame,
751 code,
752 *,
753 sd=None,
754 context=None,
755 ):
691 756 self.description = description
692 757 self.filename = filename
693 758 self.lineno = lineno
694 759 self.frame = frame
695 760 self.code = code
696 761 self._sd = sd
762 self.context = context
697 763
698 764 # self.lines = []
699 765 if sd is None:
@@ -848,7 +914,6 b' class VerboseTB(TBTools):'
848 914
849 915 result = f'{link}{", " if call else ""}{call}\n'
850 916 if frame_info._sd is None:
851 assert False
852 917 # fast fallback if file is too long
853 918 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
854 919 link = tpl_link % util_path.compress_user(frame_info.filename)
@@ -858,13 +923,25 b' class VerboseTB(TBTools):'
858 923 ).format2
859 924 first_line = frame_info.code.co_firstlineno
860 925 current_line = frame_info.lineno[0]
926 raw_lines = frame_info.raw_lines
927 index = current_line - first_line
928
929 if index >= frame_info.context:
930 start = max(index - frame_info.context, 0)
931 stop = index + frame_info.context
932 index = frame_info.context
933 else:
934 start = 0
935 stop = index + frame_info.context
936 raw_lines = raw_lines[start:stop]
937
861 938 return "%s%s" % (
862 939 level,
863 940 "".join(
864 941 _simple_format_traceback_lines(
865 942 current_line,
866 current_line - first_line,
867 frame_info.raw_lines,
943 index,
944 raw_lines,
868 945 Colors,
869 946 lvals,
870 947 _line_format,
@@ -942,13 +1019,13 b' class VerboseTB(TBTools):'
942 1019 # some locals
943 1020 orig_etype = etype
944 1021 try:
945 etype = etype.__name__
1022 etype = etype.__name__ # type: ignore
946 1023 except AttributeError:
947 1024 pass
948 1025
949 1026 tb_offset = self.tb_offset if tb_offset is None else tb_offset
950 1027 assert isinstance(tb_offset, int)
951 head = self.prepare_header(etype, self.long_header)
1028 head = self.prepare_header(str(etype), self.long_header)
952 1029 records = (
953 1030 self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []
954 1031 )
@@ -1018,23 +1095,34 b' class VerboseTB(TBTools):'
1018 1095 tbs = []
1019 1096 while cf is not None:
1020 1097 try:
1021 source_file = inspect.getsourcefile(etb.tb_frame)
1022 lines, first = inspect.getsourcelines(etb.tb_frame)
1098 mod = inspect.getmodule(cf.tb_frame)
1099 if mod is not None:
1100 mod_name = mod.__name__
1101 root_name, *_ = mod_name.split(".")
1102 if root_name == "IPython":
1103 cf = cf.tb_next
1104 continue
1105 max_len = get_line_number_of_frame(cf.tb_frame)
1106
1023 1107 except OSError:
1024 max_len = float("-inf")
1025 break
1026 max_len = max(max_len, first + len(lines))
1108 max_len = 0
1109 max_len = max(max_len, max_len)
1027 1110 tbs.append(cf)
1028 cf = cf.tb_next
1111 cf = getattr(cf, "tb_next", None)
1029 1112
1030 1113 if max_len > FAST_THRESHOLD:
1031 1114 FIs = []
1032 1115 for tb in tbs:
1033 frame = tb.tb_frame
1116 frame = tb.tb_frame # type: ignore
1034 1117 lineno = (frame.f_lineno,)
1035 1118 code = frame.f_code
1036 1119 filename = code.co_filename
1037 FIs.append(FrameInfo("Raw frame", filename, lineno, frame, code))
1120 # TODO: Here we need to use before/after/
1121 FIs.append(
1122 FrameInfo(
1123 "Raw frame", filename, lineno, frame, code, context=context
1124 )
1125 )
1038 1126 return FIs
1039 1127 res = list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:]
1040 1128 res = [FrameInfo._from_stack_data_FrameInfo(r) for r in res]
@@ -1044,7 +1132,7 b' class VerboseTB(TBTools):'
1044 1132 self,
1045 1133 etype: type,
1046 1134 evalue: Optional[BaseException],
1047 etb: Optional[TracebackType],
1135 etb: Optional[TracebackType] = None,
1048 1136 tb_offset: Optional[int] = None,
1049 1137 number_of_lines_of_context: int = 5,
1050 1138 ):
@@ -1115,8 +1203,8 b' class VerboseTB(TBTools):'
1115 1203 with display_trap:
1116 1204 self.pdb.reset()
1117 1205 # Find the right frame so we don't pop up inside ipython itself
1118 if hasattr(self, 'tb') and self.tb is not None:
1119 etb = self.tb
1206 if hasattr(self, "tb") and self.tb is not None: # type: ignore[has-type]
1207 etb = self.tb # type: ignore[has-type]
1120 1208 else:
1121 1209 etb = self.tb = sys.last_traceback
1122 1210 while self.tb is not None and self.tb.tb_next is not None:
@@ -1291,24 +1379,23 b' class AutoFormattedTB(FormattedTB):'
1291 1379
1292 1380 def structured_traceback(
1293 1381 self,
1294 etype=None,
1295 value=None,
1296 tb=None,
1297 tb_offset=None,
1298 number_of_lines_of_context=5,
1382 etype: type,
1383 evalue: Optional[BaseException],
1384 etb: Optional[TracebackType] = None,
1385 tb_offset: Optional[int] = None,
1386 number_of_lines_of_context: int = 5,
1299 1387 ):
1300 etype: type
1301 value: BaseException
1302 1388 # tb: TracebackType or tupleof tb types ?
1303 1389 if etype is None:
1304 etype, value, tb = sys.exc_info()
1305 if isinstance(tb, tuple):
1390 etype, evalue, etb = sys.exc_info()
1391 if isinstance(etb, tuple):
1306 1392 # tb is a tuple if this is a chained exception.
1307 self.tb = tb[0]
1393 self.tb = etb[0]
1308 1394 else:
1309 self.tb = tb
1395 self.tb = etb
1310 1396 return FormattedTB.structured_traceback(
1311 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1397 self, etype, evalue, etb, tb_offset, number_of_lines_of_context
1398 )
1312 1399
1313 1400
1314 1401 #---------------------------------------------------------------------------
@@ -1366,7 +1453,7 b' def text_repr(value):'
1366 1453 """Hopefully pretty robust repr equivalent."""
1367 1454 # this is pretty horrible but should always return *something*
1368 1455 try:
1369 return pydoc.text.repr(value)
1456 return pydoc.text.repr(value) # type: ignore[call-arg]
1370 1457 except KeyboardInterrupt:
1371 1458 raise
1372 1459 except:
@@ -19,7 +19,7 b' exclude = ['
19 19 #'IPython/core/interactiveshell.py',
20 20 'IPython/core/magic.py',
21 21 'IPython/core/profileapp.py',
22 'IPython/core/ultratb.py',
22 # 'IPython/core/ultratb.py',
23 23 'IPython/lib/deepreload.py',
24 24 'IPython/lib/pretty.py',
25 25 'IPython/sphinxext/ipython_directive.py',
General Comments 0
You need to be logged in to leave comments. Login now