]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-31299: make it possible to filter out frames from tracebacks (GH-28067)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Tue, 31 Aug 2021 20:42:08 +0000 (21:42 +0100)
committerGitHub <noreply@github.com>
Tue, 31 Aug 2021 20:42:08 +0000 (21:42 +0100)
Doc/library/traceback.rst
Lib/test/test_traceback.py
Lib/traceback.py
Misc/NEWS.d/next/Library/2021-08-30-13-55-09.bpo-31299.9QzjZs.rst [new file with mode: 0644]

index 83d5c8c6fcbd3202bccad11728f08c02f046f7e5..7b230495b7b564af5dddf2f02c27065867517dfe 100644 (file)
@@ -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
 
index 5d48e9d7ff0397da8150c08950d2e5d5b12cb74a..d1967aabb29a1c9d731699049ce818e92c0df9de 100644 (file)
@@ -1514,6 +1514,34 @@ class TestStack(unittest.TestCase):
             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):
 
index 4ad8c9a17b349c1c1573c7e8ad521aa148875501..8d83fd9b517e6cad61a8ad93bde55ab6819a771a 100644 (file)
@@ -515,6 +515,9 @@ class StackSummary(list):
         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):
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 (file)
index 0000000..1ffa0b1
--- /dev/null
@@ -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