-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-31299: Make it possible to filter out frames from tracebacks #26772
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3830400
4debb1d
caef03f
50fcdcc
ac09f43
68afed9
b025ee0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -453,7 +453,8 @@ def format_frame(self, frame): | |
"""Format the lines for a single frame. | ||
|
||
Returns a string representing one frame involved in the stack. This | ||
gets called for every frame to be printed in the stack summary. | ||
gets called for every frame to be printed in the stack summary. If | ||
it returns ``None``, the frame is omitted from the output. | ||
""" | ||
row = [] | ||
row.append(' File "{}", line {}, in {}\n'.format( | ||
|
@@ -509,23 +510,25 @@ def format(self): | |
last_name = None | ||
count = 0 | ||
for frame in self: | ||
if (last_file is None or last_file != frame.filename or | ||
last_line is None or last_line != frame.lineno or | ||
last_name is None or last_name != frame.name): | ||
formatted_frame = self.format_frame(frame) | ||
if formatted_frame is not None: | ||
if (last_file is None or last_file != frame.filename or | ||
last_line is None or last_line != frame.lineno or | ||
last_name is None or last_name != frame.name): | ||
if count > _RECURSIVE_CUTOFF: | ||
count -= _RECURSIVE_CUTOFF | ||
result.append( | ||
f' [Previous line repeated {count} more ' | ||
f'time{"s" if count > 1 else ""}]\n' | ||
) | ||
last_file = frame.filename | ||
last_line = frame.lineno | ||
last_name = frame.name | ||
count = 0 | ||
count += 1 | ||
if count > _RECURSIVE_CUTOFF: | ||
count -= _RECURSIVE_CUTOFF | ||
result.append( | ||
f' [Previous line repeated {count} more ' | ||
f'time{"s" if count > 1 else ""}]\n' | ||
) | ||
last_file = frame.filename | ||
last_line = frame.lineno | ||
last_name = frame.name | ||
count = 0 | ||
count += 1 | ||
if count > _RECURSIVE_CUTOFF: | ||
continue | ||
result.append(self.format_frame(frame)) | ||
continue | ||
result.append(formatted_frame) | ||
|
||
if count > _RECURSIVE_CUTOFF: | ||
count -= _RECURSIVE_CUTOFF | ||
|
@@ -618,7 +621,7 @@ class TracebackException: | |
|
||
def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, | ||
lookup_lines=True, capture_locals=False, compact=False, | ||
_seen=None): | ||
stack_summary_cls=None, _seen=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a good approach to customizing the behavior while reusing most of the exception printing code. There's precedent for this style of expansion with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See general review comment. |
||
# NB: we need to accept exc_traceback, exc_value, exc_traceback to | ||
# permit backwards compat with the existing API, otherwise we | ||
# need stub thunk objects just to glue it together. | ||
|
@@ -628,8 +631,9 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, | |
_seen = set() | ||
_seen.add(id(exc_value)) | ||
|
||
# TODO: locals. | ||
self.stack = StackSummary._extract_from_extended_frame_gen( | ||
if stack_summary_cls is None: | ||
stack_summary_cls = StackSummary | ||
self.stack = stack_summary_cls._extract_from_extended_frame_gen( | ||
_walk_tb_with_full_positions(exc_traceback), | ||
limit=limit, lookup_lines=lookup_lines, | ||
capture_locals=capture_locals) | ||
|
@@ -665,6 +669,7 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, | |
limit=limit, | ||
lookup_lines=lookup_lines, | ||
capture_locals=capture_locals, | ||
stack_summary_cls=stack_summary_cls, | ||
_seen=_seen) | ||
else: | ||
cause = None | ||
|
@@ -684,6 +689,7 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, | |
limit=limit, | ||
lookup_lines=lookup_lines, | ||
capture_locals=capture_locals, | ||
stack_summary_cls=stack_summary_cls, | ||
_seen=_seen) | ||
else: | ||
context = None | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Added the ``stack_summary_cls`` parameter to :class:`TracebackException`, to allow fine-grained control over the content of a formatted traceback. Added option to completely drop frames from the output by returning ``None`` from a :meth:`~StackSummary.format_frame` override. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a code example, in particular, class SkipG from the test, which skips frames for a function named 'g'.