@@ -1667,6 +1667,55 @@ def test_set___main___attrs(self):
16671667 self .assertEqual (rc , 0 )
16681668
16691669
1670+ class CaptureExceptionTests (unittest .TestCase ):
1671+
1672+ # Prevent crashes with incompatible TracebackException.format().
1673+ # Regression test for https://github.com/python/cpython/issues/143377.
1674+
1675+ def capture_with_formatter (self , exc , formatter ):
1676+ with support .swap_attr (traceback .TracebackException , "format" , formatter ):
1677+ return _interpreters .capture_exception (exc )
1678+
1679+ def test_capture_exception (self ):
1680+ captured = _interpreters .capture_exception (ValueError ("hello" ))
1681+
1682+ self .assertEqual (captured .type .__name__ , "ValueError" )
1683+ self .assertEqual (captured .type .__qualname__ , "ValueError" )
1684+ self .assertEqual (captured .type .__module__ , "builtins" )
1685+
1686+ self .assertEqual (captured .msg , "hello" )
1687+ self .assertEqual (captured .formatted , "ValueError: hello" )
1688+
1689+ def test_capture_exception_custom_format (self ):
1690+ exc = ValueError ("good bye!" )
1691+ formatter = lambda self : ["hello\n " , "world\n " ]
1692+ captured = self .capture_with_formatter (exc , formatter )
1693+ self .assertEqual (captured .msg , "good bye!" )
1694+ self .assertEqual (captured .formatted , "ValueError: good bye!" )
1695+ self .assertEqual (captured .errdisplay , "hello\n world" )
1696+
1697+ @support .subTests ("exc_lines" , ([], ["x-no-nl" ], ["x-no-nl" , "y-no-nl" ]))
1698+ def test_capture_exception_invalid_format (self , exc_lines ):
1699+ formatter = lambda self : exc_lines
1700+ captured = self .capture_with_formatter (ValueError (), formatter )
1701+ self .assertEqual (captured .msg , "" )
1702+ self .assertEqual (captured .formatted , "ValueError: " )
1703+ self .assertEqual (captured .errdisplay , "" .join (exc_lines ))
1704+
1705+ @unittest .skipUnless (
1706+ support .Py_DEBUG ,
1707+ "printing subinterpreter unraisable exceptions requires DEBUG build" ,
1708+ )
1709+ def test_capture_exception_unraisable_exception (self ):
1710+ formatter = lambda self : 1
1711+ with support .catch_unraisable_exception () as cm :
1712+ captured = self .capture_with_formatter (ValueError (), formatter )
1713+ self .assertNotHasAttr (captured , "errdisplay" )
1714+ self .assertEqual (cm .unraisable .exc_type , TypeError )
1715+ self .assertEqual (str (cm .unraisable .exc_value ),
1716+ "can only join an iterable" )
1717+
1718+
16701719if __name__ == '__main__' :
16711720 # Test needs to be a package, so we can do relative imports.
16721721 unittest .main ()
0 commit comments