gh-128894: Fix `TracebackException._format_syntax_error` on custom `SyntaxError` metadata (#128946)
https://github.com/python/cpython/commit/a16ded10ad3952406280be5ab9ff86a4768... commit: a16ded10ad3952406280be5ab9ff86a476867b08 branch: main author: sobolevn <mail@sobolevn.me> committer: pablogsal <Pablogsal@gmail.com> date: 2025-01-22T12:47:03Z summary: gh-128894: Fix `TracebackException._format_syntax_error` on custom `SyntaxError` metadata (#128946) files: A Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst M Lib/test/test_traceback.py M Lib/traceback.py diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index a27a71c32ea521..867088a4c56bd7 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -376,6 +376,30 @@ def f(): ' ValueError: 0\n', ]) + def test_format_exception_group_syntax_error_with_custom_values(self): + # See https://github.com/python/cpython/issues/128894 + for exc in [ + SyntaxError('error', 'abcd'), + SyntaxError('error', [None] * 4), + SyntaxError('error', (1, 2, 3, 4)), + SyntaxError('error', (1, 2, 3, 4)), + SyntaxError('error', (1, 'a', 'b', 2)), + # with end_lineno and end_offset: + SyntaxError('error', 'abcdef'), + SyntaxError('error', [None] * 6), + SyntaxError('error', (1, 2, 3, 4, 5, 6)), + SyntaxError('error', (1, 'a', 'b', 2, 'c', 'd')), + ]: + with self.subTest(exc=exc): + err = traceback.format_exception_only(exc, show_group=True) + # Should not raise an exception: + if exc.lineno is not None: + self.assertEqual(len(err), 2) + self.assertTrue(err[0].startswith(' File')) + else: + self.assertEqual(len(err), 1) + self.assertEqual(err[-1], 'SyntaxError: error\n') + @requires_subprocess() @force_not_colorized def test_encoded_file(self): diff --git a/Lib/traceback.py b/Lib/traceback.py index 3ed06af15a0a89..31c73efcef5a52 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1283,7 +1283,7 @@ def _format_syntax_error(self, stype, **kwargs): filename_suffix = ' ({})'.format(self.filename) text = self.text - if text is not None: + if isinstance(text, str): # text = " foo\n" # rtext = " foo" # ltext = "foo" @@ -1292,10 +1292,17 @@ def _format_syntax_error(self, stype, **kwargs): spaces = len(rtext) - len(ltext) if self.offset is None: yield ' {}\n'.format(ltext) - else: + elif isinstance(self.offset, int): offset = self.offset if self.lineno == self.end_lineno: - end_offset = self.end_offset if self.end_offset not in {None, 0} else offset + end_offset = ( + self.end_offset + if ( + isinstance(self.end_offset, int) + and self.end_offset != 0 + ) + else offset + ) else: end_offset = len(rtext) + 1 diff --git a/Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst b/Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst new file mode 100644 index 00000000000000..7e015103a95713 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst @@ -0,0 +1,2 @@ +Fix ``traceback.TracebackException._format_syntax_error`` not to fail on +exceptions with custom metadata.
participants (1)
-
pablogsal