@@ -30,11 +30,15 @@ def print_list(extracted_list, file=None, *, show_lines=True):
3030 """Print the list of tuples as returned by extract_tb() or
3131 extract_stack() as a formatted stack trace to the given file.
3232
33- If show_lines is False, source code lines are not included in the output.
33+ To print in "recent call first" order, call "extracted_list.reverse()"
34+ before passing it to this function.
35+
36+ If 'show_lines' is false, source code lines are not included in the output.
3437 """
3538 if file is None :
3639 file = sys .stderr
37- for item in StackSummary .from_list (extracted_list ).format (show_lines = show_lines ):
40+ for item in StackSummary .from_list (extracted_list ).format (
41+ show_lines = show_lines ):
3842 print (item , file = file , end = "" )
3943
4044def format_list (extracted_list , * , show_lines = True ):
@@ -44,37 +48,41 @@ def format_list(extracted_list, *, show_lines=True):
4448 extract_tb() or extract_stack(), return a list of strings ready
4549 for printing.
4650
47- Each string in the resulting list corresponds to the item with the
48- same index in the argument list. Each string ends in a newline;
49- the strings may contain internal newlines as well, for those items
50- whose source text line is not None.
51+ Each string ends in a newline; the strings may contain internal newlines as
52+ well, for those items whose source text line is not None.
5153
52- If show_lines is False , source code lines are not included in the output.
54+ If ' show_lines' is false , source code lines are not included in the output.
5355 """
5456 return StackSummary .from_list (extracted_list ).format (show_lines = show_lines )
5557
5658#
5759# Printing and Extracting Tracebacks.
5860#
5961
60- def print_tb (tb , limit = None , file = None , * , show_lines = True ):
62+ def print_tb (tb , limit = None , file = None , * , show_lines = True , recent_first = False ):
6163 """Print up to 'limit' stack trace entries from the traceback 'tb'.
6264
6365 If 'limit' is omitted or None, all entries are printed. If 'file'
6466 is omitted or None, the output goes to sys.stderr; otherwise
6567 'file' should be an open file or file-like object with a write()
6668 method.
6769
68- If show_lines is False, source code lines are not included in the output.
70+ If 'show_lines' is false, source code lines are not included in the output.
71+ If 'recent_first' is true, the stack trace is printed in "most recent call
72+ first" order.
6973 """
70- print_list (extract_tb (tb , limit = limit ), file = file , show_lines = show_lines )
74+ tblist = extract_tb (tb , limit = limit )
75+ if recent_first :
76+ tblist .reverse ()
77+ print_list (tblist , file = file , show_lines = show_lines )
7178
72- def format_tb (tb , limit = None , * , show_lines = True ):
73- """A shorthand for 'format_list(extract_tb(tb, limit))'.
79+ def format_tb (tb , limit = None , * , show_lines = True , recent_first = False ):
80+ """A shorthand for 'format_list(extract_tb(tb, limit))'."""
7481
75- If show_lines is False, source code lines are not included in the output.
76- """
77- return extract_tb (tb , limit = limit ).format (show_lines = show_lines )
82+ tblist = extract_tb (tb , limit = limit )
83+ if recent_first :
84+ tblist .reverse ()
85+ return tblist .format (show_lines = show_lines )
7886
7987def extract_tb (tb , limit = None ):
8088 """
@@ -90,7 +98,7 @@ def extract_tb(tb, limit=None):
9098 whitespace stripped; if the source is not available it is None.
9199 """
92100 return StackSummary ._extract_from_extended_frame_gen (
93- _walk_tb_with_full_positions (tb ), limit = limit , lookup_lines = False )
101+ _walk_tb_with_full_positions (tb ), limit = limit )
94102
95103#
96104# Exception formatting and output.
@@ -126,8 +134,9 @@ def _parse_value_tb(exc, value, tb):
126134 return value , tb
127135
128136
129- def print_exception (exc , / , value = _sentinel , tb = _sentinel , limit = None , \
130- file = None , chain = True , show_lines = True , ** kwargs ):
137+ def print_exception (exc , / , value = _sentinel , tb = _sentinel , limit = None ,
138+ file = None , chain = True , * , show_lines = True ,
139+ recent_first = False , ** kwargs ):
131140 """Print exception up to 'limit' stack trace entries from 'tb' to 'file'.
132141
133142 This differs from print_tb() in the following ways: (1) if
@@ -138,13 +147,15 @@ def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \
138147 occurred with a caret on the next line indicating the approximate
139148 position of the error.
140149
141- If show_lines is False, source code lines are not included in the output.
150+ If 'show_lines' is false, source code lines are not included in the output.
151+ If 'recent_first' is true, exception is printed first and traceback is shown
152+ by "most recent call first" order.
142153 """
143154 colorize = kwargs .get ("colorize" , False )
144155 value , tb = _parse_value_tb (exc , value , tb )
145- te = TracebackException (type (value ), value , tb , limit = limit , compact = True ,
146- lookup_lines = show_lines )
147- te . print ( file = file , chain = chain , colorize = colorize , show_lines = show_lines )
156+ te = TracebackException (type (value ), value , tb , limit = limit , compact = True )
157+ te . print ( file = file , chain = chain , colorize = colorize ,
158+ show_lines = show_lines , recent_first = recent_first )
148159
149160
150161BUILTIN_EXCEPTION_LIMIT = object ()
@@ -156,23 +167,21 @@ def _print_exception_bltin(exc, /):
156167 return print_exception (exc , limit = BUILTIN_EXCEPTION_LIMIT , file = file , colorize = colorize )
157168
158169
159- def format_exception (exc , / , value = _sentinel , tb = _sentinel , limit = None , \
160- chain = True , show_lines = True , ** kwargs ):
170+ def format_exception (exc , / , value = _sentinel , tb = _sentinel , limit = None ,
171+ chain = True , * , show_lines = True , recent_first = False , ** kwargs ):
161172 """Format a stack trace and the exception information.
162173
163174 The arguments have the same meaning as the corresponding arguments
164175 to print_exception(). The return value is a list of strings, each
165176 ending in a newline and some containing internal newlines. When
166177 these lines are concatenated and printed, exactly the same text is
167178 printed as does print_exception().
168-
169- If show_lines is False, source code lines are not included in the output.
170179 """
171180 colorize = kwargs .get ("colorize" , False )
172181 value , tb = _parse_value_tb (exc , value , tb )
173- te = TracebackException (type (value ), value , tb , limit = limit , compact = True ,
174- lookup_lines = show_lines )
175- return list ( te . format ( chain = chain , colorize = colorize , show_lines = show_lines ))
182+ te = TracebackException (type (value ), value , tb , limit = limit , compact = True )
183+ return list ( te . format ( chain = chain , colorize = colorize ,
184+ show_lines = show_lines , recent_first = recent_first ))
176185
177186
178187def format_exception_only (exc , / , value = _sentinel , * , show_group = False , ** kwargs ):
@@ -221,61 +230,63 @@ def _safe_string(value, what, func=str):
221230
222231# --
223232
224- def print_exc (limit = None , file = None , chain = True , * , show_lines = True ):
225- """Shorthand for 'print_exception(sys.exception(), limit=limit, file=file, chain=chain)'.
226-
227- If show_lines is False, source code lines are not included in the output.
228- """
229- print_exception (sys .exception (), limit = limit , file = file , chain = chain , show_lines = show_lines )
230-
231- def format_exc (limit = None , chain = True , * , show_lines = True ):
232- """Like print_exc() but return a string.
233-
234- If show_lines is False, source code lines are not included in the output.
235- """
236- return "" .join (format_exception (sys .exception (), limit = limit , chain = chain , show_lines = show_lines ))
237-
238- def print_last (limit = None , file = None , chain = True , * , show_lines = True ):
239- """This is a shorthand for 'print_exception(sys.last_exc, limit=limit, file=file, chain=chain)'.
240-
241- If show_lines is False, source code lines are not included in the output.
242- """
233+ def print_exc (limit = None , file = None , chain = True , * , show_lines = True ,
234+ recent_first = False ):
235+ """Shorthand for 'print_exception(sys.exception(), limit=limit, file=file, chain=chain, ...)'."""
236+ print_exception (sys .exception (), limit = limit , file = file , chain = chain ,
237+ show_lines = show_lines , recent_first = recent_first )
238+
239+ def format_exc (limit = None , chain = True , * , show_lines = True , recent_first = False ):
240+ """Like print_exc() but return a string."""
241+ return "" .join (format_exception (
242+ sys .exception (), limit = limit , chain = chain ,
243+ show_lines = show_lines , recent_first = recent_first ))
244+
245+ def print_last (limit = None , file = None , chain = True , * , show_lines = True ,
246+ recent_first = False ):
247+ """This is a shorthand for 'print_exception(sys.last_exc, limit=limit, file=file, chain=chain, ...)'."""
243248 if not hasattr (sys , "last_exc" ) and not hasattr (sys , "last_type" ):
244249 raise ValueError ("no last exception" )
245250
246251 if hasattr (sys , "last_exc" ):
247- print_exception (sys .last_exc , limit = limit , file = file , chain = chain , show_lines = show_lines )
252+ print_exception (sys .last_exc , limit = limit , file = file , chain = chain ,
253+ show_lines = show_lines , recent_first = recent_first )
248254 else :
249255 print_exception (sys .last_type , sys .last_value , sys .last_traceback ,
250- limit = limit , file = file , chain = chain , show_lines = show_lines )
256+ limit = limit , file = file , chain = chain ,
257+ show_lines = show_lines , recent_first = recent_first )
251258
252259
253260#
254261# Printing and Extracting Stacks.
255262#
256263
257- def print_stack (f = None , limit = None , file = None , * , show_lines = True ):
264+ def print_stack (f = None , limit = None , file = None , * , show_lines = True , recent_first = False ):
258265 """Print a stack trace from its invocation point.
259266
260267 The optional 'f' argument can be used to specify an alternate
261268 stack frame at which to start. The optional 'limit' and 'file'
262269 arguments have the same meaning as for print_exception().
263270
264- If show_lines is False, source code lines are not included in the output.
271+ If 'show_lines' is false, source code lines are not included in the output.
272+ If 'recent_first' is true, stack is printed by "most recent call first" order.
265273 """
266274 if f is None :
267275 f = sys ._getframe ().f_back
268- print_list (extract_stack (f , limit = limit ), file = file , show_lines = show_lines )
276+ stack = extract_stack (f , limit = limit )
277+ if recent_first :
278+ stack .reverse ()
279+ print_list (stack , file = file , show_lines = show_lines )
269280
270281
271- def format_stack (f = None , limit = None , * , show_lines = True ):
272- """Shorthand for 'format_list(extract_stack(f, limit))'.
273-
274- If show_lines is False, source code lines are not included in the output.
275- """
282+ def format_stack (f = None , limit = None , * , show_lines = True , recent_first = False ):
283+ """Shorthand for 'format_list(extract_stack(f, limit), show_lines)'."""
276284 if f is None :
277285 f = sys ._getframe ().f_back
278- return format_list (extract_stack (f , limit = limit ), show_lines = show_lines )
286+ stack = extract_stack (f , limit = limit )
287+ if recent_first :
288+ stack .reverse ()
289+ return format_list (stack , show_lines = show_lines )
279290
280291
281292def extract_stack (f = None , limit = None ):
@@ -289,7 +300,8 @@ def extract_stack(f=None, limit=None):
289300 """
290301 if f is None :
291302 f = sys ._getframe ().f_back
292- stack = StackSummary .extract (walk_stack (f ), limit = limit , lookup_lines = False )
303+ stack = StackSummary .extract (walk_stack (f ), limit = limit )
304+ # Traceback should use "recent call last" order.
293305 stack .reverse ()
294306 return stack
295307
@@ -465,7 +477,7 @@ class StackSummary(list):
465477 """A list of FrameSummary objects, representing a stack of frames."""
466478
467479 @classmethod
468- def extract (klass , frame_gen , * , limit = None , lookup_lines = True ,
480+ def extract (klass , frame_gen , * , limit = None , lookup_lines = False ,
469481 capture_locals = False ):
470482 """Create a StackSummary from a traceback or stack object.
471483
@@ -488,7 +500,7 @@ def extended_frame_gen():
488500
489501 @classmethod
490502 def _extract_from_extended_frame_gen (klass , frame_gen , * , limit = None ,
491- lookup_lines = True , capture_locals = False ):
503+ lookup_lines = False , capture_locals = False ):
492504 # Same as extract but operates on a frame generator that yields
493505 # (frame, (lineno, end_lineno, colno, end_colno)) in the stack.
494506 # Only lineno is required, the remaining fields can be None if the
@@ -560,8 +572,6 @@ def format_frame_summary(self, frame_summary, *, show_lines=True, **kwargs):
560572
561573 Returns a string representing one frame involved in the stack. This
562574 gets called for every frame to be printed in the stack summary.
563-
564- If show_lines is False, source code lines are not included in the output.
565575 """
566576 colorize = kwargs .get ("colorize" , False )
567577 row = []
@@ -785,8 +795,6 @@ def format(self, *, show_lines=True, **kwargs):
785795 For long sequences of the same frame and line, the first few
786796 repetitions are shown, followed by a summary line stating the exact
787797 number of further repetitions.
788-
789- If show_lines is False, source code lines are not included in the output.
790798 """
791799 colorize = kwargs .get ("colorize" , False )
792800 result = []
@@ -1076,7 +1084,7 @@ class TracebackException:
10761084 """
10771085
10781086 def __init__ (self , exc_type , exc_value , exc_traceback , * , limit = None ,
1079- lookup_lines = True , capture_locals = False , compact = False ,
1087+ lookup_lines = False , capture_locals = False , compact = False ,
10801088 max_group_width = 15 , max_group_depth = 10 , save_exc_type = True , _seen = None ):
10811089 # NB: we need to accept exc_traceback, exc_value, exc_traceback to
10821090 # permit backwards compat with the existing API, otherwise we
@@ -1499,7 +1507,7 @@ def _format_syntax_error(self, stype, **kwargs):
14991507 filename_suffix ,
15001508 )
15011509
1502- def format (self , * , chain = True , show_lines = True , _ctx = None , ** kwargs ):
1510+ def format (self , * , chain = True , show_lines = True , _ctx = None , recent_first = False , ** kwargs ):
15031511 """Format the exception.
15041512
15051513 If chain is not *True*, *__cause__* and *__context__* will not be formatted.
@@ -1510,8 +1518,6 @@ def format(self, *, chain=True, show_lines=True, _ctx=None, **kwargs):
15101518
15111519 The message indicating which exception occurred is always the last
15121520 string in the output.
1513-
1514- If show_lines is False, source code lines are not included in the output.
15151521 """
15161522 colorize = kwargs .get ("colorize" , False )
15171523 if _ctx is None :
@@ -1541,10 +1547,16 @@ def format(self, *, chain=True, show_lines=True, _ctx=None, **kwargs):
15411547 if msg is not None :
15421548 yield from _ctx .emit (msg )
15431549 if exc .exceptions is None :
1544- if exc .stack :
1550+ if not recent_first and exc .stack :
15451551 yield from _ctx .emit ('Traceback (most recent call last):\n ' )
1546- yield from _ctx .emit (exc .stack .format (show_lines = show_lines , colorize = colorize ))
1552+ yield from _ctx .emit (exc .stack .format (
1553+ show_lines = show_lines , colorize = colorize ))
15471554 yield from _ctx .emit (exc .format_exception_only (colorize = colorize ))
1555+ if recent_first and exc .stack :
1556+ yield from _ctx .emit ('Traceback (most recent call first):\n ' )
1557+ reversed_stack = StackSummary (reversed (self .stack ))
1558+ yield from _ctx .emit (reversed_stack .format (
1559+ show_lines = show_lines , colorize = colorize ))
15481560 elif _ctx .exception_group_depth > self .max_group_depth :
15491561 # exception group, but depth exceeds limit
15501562 yield from _ctx .emit (
@@ -1555,13 +1567,22 @@ def format(self, *, chain=True, show_lines=True, _ctx=None, **kwargs):
15551567 if is_toplevel :
15561568 _ctx .exception_group_depth += 1
15571569
1558- if exc .stack :
1570+ if not recent_first and exc .stack :
15591571 yield from _ctx .emit (
15601572 'Exception Group Traceback (most recent call last):\n ' ,
15611573 margin_char = '+' if is_toplevel else None )
1562- yield from _ctx .emit (exc .stack .format (show_lines = show_lines , colorize = colorize ))
1574+ yield from _ctx .emit (exc .stack .format (
1575+ show_lines = show_lines , colorize = colorize ))
15631576
15641577 yield from _ctx .emit (exc .format_exception_only (colorize = colorize ))
1578+ if recent_first and exc .stack :
1579+ yield from _ctx .emit (
1580+ 'Exception Group Traceback (most recent call first):\n ' ,
1581+ margin_char = '+' if is_toplevel else None )
1582+ reversed_stack = StackSummary (reversed (self .stack ))
1583+ yield from _ctx .emit (reversed_stack .format (
1584+ show_lines = show_lines , colorize = colorize ))
1585+
15651586 num_excs = len (exc .exceptions )
15661587 if num_excs <= self .max_group_width :
15671588 n = num_excs
@@ -1602,15 +1623,13 @@ def format(self, *, chain=True, show_lines=True, _ctx=None, **kwargs):
16021623 _ctx .exception_group_depth = 0
16031624
16041625
1605- def print (self , * , file = None , chain = True , show_lines = True , ** kwargs ):
1606- """Print the result of self.format(chain=chain) to 'file'.
1607-
1608- If show_lines is False, source code lines are not included in the output.
1609- """
1626+ def print (self , * , file = None , chain = True , show_lines = True , recent_first = False , ** kwargs ):
1627+ """Print the result of self.format(chain=chain) to 'file'."""
16101628 colorize = kwargs .get ("colorize" , False )
16111629 if file is None :
16121630 file = sys .stderr
1613- for line in self .format (chain = chain , show_lines = show_lines , colorize = colorize ):
1631+ for line in self .format (chain = chain , show_lines = show_lines ,
1632+ recent_first = recent_first , colorize = colorize ):
16141633 print (line , file = file , end = "" )
16151634
16161635
0 commit comments