From a675ee2de1dc78aa8ea38f74a0c692425edf1521 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 30 Aug 2021 14:47:36 +0100 Subject: [PATCH 1/3] bpo-31299: make it possible to filter out frames from tracebacks --- Doc/library/traceback.rst | 3 ++- Lib/test/test_traceback.py | 28 ++++++++++++++++++++++++++++ Lib/traceback.py | 3 +++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index 83d5c8c6fcbd320..e71af262a308657 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -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 diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 5d48e9d7ff0397d..d1967aabb29a1c9 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -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): diff --git a/Lib/traceback.py b/Lib/traceback.py index 4ad8c9a17b349c1..8d83fd9b517e6ca 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -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): From f67d98417ec17f2c0cf78c0c1e6db90a2b461f32 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 13:55:11 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-08-30-13-55-09.bpo-31299.9QzjZs.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-08-30-13-55-09.bpo-31299.9QzjZs.rst diff --git a/Misc/NEWS.d/next/Library/2021-08-30-13-55-09.bpo-31299.9QzjZs.rst b/Misc/NEWS.d/next/Library/2021-08-30-13-55-09.bpo-31299.9QzjZs.rst new file mode 100644 index 000000000000000..1ffa0b15172ee73 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-08-30-13-55-09.bpo-31299.9QzjZs.rst @@ -0,0 +1 @@ +Add option to completely drop frames from a traceback by returning ``None`` from a :meth:`~traceback.StackSummary.format_frame` override. \ No newline at end of file From 35616dde763f81ca5b81cfe47ec9e1d1fb03e23b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 30 Aug 2021 15:05:26 +0100 Subject: [PATCH 3/3] fix whitespace --- Doc/library/traceback.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index e71af262a308657..7b230495b7b564a 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -358,7 +358,7 @@ 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`. If it returns ``None``, the frame is omitted - from the output. + from the output. .. versionadded:: 3.11