diff options
-rw-r--r-- | Lib/test/test_traceback.py | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index e0884fb..0aa76ae 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -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 |