]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-87822: Make traceback module robust to exceptions from repr() of local values...
authorSimon-Martin Schröder <martin.schroeder@nerdluecht.de>
Mon, 11 Jul 2022 09:14:15 +0000 (11:14 +0200)
committerGitHub <noreply@github.com>
Mon, 11 Jul 2022 09:14:15 +0000 (10:14 +0100)
Doc/library/traceback.rst
Lib/test/test_traceback.py
Lib/traceback.py
Misc/ACKS
Misc/NEWS.d/next/Library/2022-07-08-17-49-12.gh-issue-87822.F9dzkf.rst [new file with mode: 0644]

index a8412cc93d16f95a356e5a63cabeac1f085b479b..8cb6af9bc840b59bb2788f88b395369184070a75 100644 (file)
@@ -341,6 +341,10 @@ capture data for later printing in a lightweight fashion.
       local variables in each :class:`FrameSummary` are captured as object
       representations.
 
+      .. versionchanged:: 3.12
+         Exceptions raised from :func:`repr` on a local variable (when
+         *capture_locals* is ``True``) are no longer propagated to the caller.
+
    .. classmethod:: from_list(a_list)
 
       Construct a :class:`StackSummary` object from a supplied list of
index f4161fbf0178dedecd34d593ff971ebeea2b9494..602bd2cae0a96b8bb20c1e348e85497c1cb7cbc5 100644 (file)
@@ -2279,6 +2279,9 @@ class TestStack(unittest.TestCase):
             f'  File "{__file__}", line {lno}, in f\n    1/0\n'
         )
 
+class Unrepresentable:
+    def __repr__(self) -> str:
+        raise Exception("Unrepresentable")
 
 class TestTracebackException(unittest.TestCase):
 
@@ -2546,12 +2549,13 @@ class TestTracebackException(unittest.TestCase):
         linecache.updatecache('/foo.py', globals())
         e = Exception("uh oh")
         c = test_code('/foo.py', 'method')
-        f = test_frame(c, globals(), {'something': 1, 'other': 'string'})
+        f = test_frame(c, globals(), {'something': 1, 'other': 'string', 'unrepresentable': Unrepresentable()})
         tb = test_tb(f, 6, None, 0)
         exc = traceback.TracebackException(
             Exception, e, tb, capture_locals=True)
         self.assertEqual(
-            exc.stack[0].locals, {'something': '1', 'other': "'string'"})
+            exc.stack[0].locals,
+            {'something': '1', 'other': "'string'", 'unrepresentable': '<local repr() failed>'})
 
     def test_no_locals(self):
         linecache.updatecache('/foo.py', globals())
index 55f8080044053ea06260c6a54cf50c5de0324d88..b1a5fd0a26d40a817d0968adc810c4e82946fa23 100644 (file)
@@ -279,7 +279,8 @@ class FrameSummary:
         self._line = line
         if lookup_line:
             self.line
-        self.locals = {k: repr(v) for k, v in locals.items()} if locals else None
+        self.locals = {k: _safe_string(v, 'local', func=repr)
+            for k, v in locals.items()} if locals else None
         self.end_lineno = end_lineno
         self.colno = colno
         self.end_colno = end_colno
index b6340414cf701237d05b3bc9596879f9ab73b60d..32475f874c36db74e19746276cf253582d5330f2 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1590,6 +1590,7 @@ Ed Schouten
 Scott Schram
 Robin Schreiber
 Chad J. Schroeder
+Simon-Martin Schroeder
 Christian Schubert
 Sam Schulenburg
 Andreas Schwab
diff --git a/Misc/NEWS.d/next/Library/2022-07-08-17-49-12.gh-issue-87822.F9dzkf.rst b/Misc/NEWS.d/next/Library/2022-07-08-17-49-12.gh-issue-87822.F9dzkf.rst
new file mode 100644 (file)
index 0000000..7b27f5d
--- /dev/null
@@ -0,0 +1 @@
+When called with ``capture_locals=True``, the :mod:`traceback` module functions swallow exceptions raised from calls to ``repr()`` on local variables of frames. This is in order to prioritize the original exception over rendering errors.  An indication of the failure is printed in place of the missing value.  (Patch by Simon-Martin Schroeder).