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
f' File "{__file__}", line {lno}, in f\n 1/0\n'
)
+class Unrepresentable:
+ def __repr__(self) -> str:
+ raise Exception("Unrepresentable")
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())
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