]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46098: Add test for multiline syntax error traceback (GH-30695)
authorRussel Webber <24542073+RusselWebber@users.noreply.github.com>
Thu, 27 Jan 2022 14:13:12 +0000 (14:13 +0000)
committerGitHub <noreply@github.com>
Thu, 27 Jan 2022 14:13:12 +0000 (14:13 +0000)
Lib/test/test_traceback.py

index e0884fb9b78141c8a077a1e363dbf9478790d154..0aa76aeb4ce093b9a98780b9370ea64a7f9fc54a 100644 (file)
@@ -460,6 +460,42 @@ class TracebackErrorLocationCaretTests(unittest.TestCase):
         result_lines = self.get_exception(f_with_multiline)
         self.assertEqual(result_lines, expected_f.splitlines())
 
+    def test_caret_multiline_expression_syntax_error(self):
+        # Make sure an expression spanning multiple lines that has
+        # a syntax error is correctly marked with carets.
+        code = textwrap.dedent("""
+        def foo(*args, **kwargs):
+            pass
+
+        a, b, c = 1, 2, 3
+
+        foo(a, z
+                for z in
+                    range(10), b, c)
+        """)
+
+        def f_with_multiline():
+            # Need to defer the compilation until in self.get_exception(..)
+            return compile(code, "?", "exec")
+
+        lineno_f = f_with_multiline.__code__.co_firstlineno
+
+        expected_f = (
+            'Traceback (most recent call last):\n'
+            f'  File "{__file__}", line {self.callable_line}, in get_exception\n'
+            '    callable()\n'
+            '    ^^^^^^^^^^\n'
+            f'  File "{__file__}", line {lineno_f+2}, in f_with_multiline\n'
+            '    return compile(code, "?", "exec")\n'
+            '           ^^^^^^^^^^^^^^^^^^^^^^^^^^\n'
+            '  File "?", line 7\n'
+            '    foo(a, z\n'
+            '           ^'
+            )
+
+        result_lines = self.get_exception(f_with_multiline)
+        self.assertEqual(result_lines, expected_f.splitlines())
+
     def test_caret_multiline_expression_bin_op(self):
         # Make sure no carets are printed for expressions spanning multiple
         # lines.
@@ -672,16 +708,14 @@ class CPythonTracebackErrorCaretTests(TracebackErrorLocationCaretTests):
     Same set of tests as above but with Python's internal traceback printing.
     """
     def get_exception(self, callable):
-        from _testcapi import traceback_print
+        from _testcapi import exception_print
         try:
             callable()
             self.fail("No exception thrown.")
-        except:
-            type_, value, tb = sys.exc_info()
-
-            file_ = StringIO()
-            traceback_print(tb, file_)
-            return file_.getvalue().splitlines()
+        except Exception as e:
+            with captured_output("stderr") as tbstderr:
+                exception_print(e)
+            return tbstderr.getvalue().splitlines()[:-1]
 
     callable_line = get_exception.__code__.co_firstlineno + 3