Skip to content

bpo-31299: make it possible to filter out frames from tracebacks #28067

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

Merged
merged 3 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Doc/library/traceback.rst
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ capture data for later printing in a lightweight fashion.

Returns a string for printing one of the frames involved in the stack.
This method gets called for each frame object to be printed in the
:class:`StackSummary`.
:class:`StackSummary`. If it returns ``None``, the frame is omitted
from the output.

.. versionadded:: 3.11

Expand Down
28 changes: 28 additions & 0 deletions Lib/test/test_traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,34 @@ def some_inner():
s.format(),
[f'{__file__}:{some_inner.__code__.co_firstlineno + 1}'])

def test_dropping_frames(self):
def f():
1/0

def g():
try:
f()
except:
return sys.exc_info()

exc_info = g()

class Skip_G(traceback.StackSummary):
def format_frame(self, frame):
if frame.name == 'g':
return None
return super().format_frame(frame)

stack = Skip_G.extract(
traceback.walk_tb(exc_info[2])).format()

self.assertEqual(len(stack), 1)
lno = f.__code__.co_firstlineno + 1
self.assertEqual(
stack[0],
f' File "{__file__}", line {lno}, in f\n 1/0\n'
)


class TestTracebackException(unittest.TestCase):

Expand Down
3 changes: 3 additions & 0 deletions Lib/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,9 @@ def format(self):
last_name = None
count = 0
for frame in self:
formatted_frame = self.format_frame(frame)
if formatted_frame is None:
continue
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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add option to completely drop frames from a traceback by returning ``None`` from a :meth:`~traceback.StackSummary.format_frame` override.