@@ -460,6 +460,42 @@ def f_with_multiline():
460
460
result_lines = self .get_exception (f_with_multiline )
461
461
self .assertEqual (result_lines , expected_f .splitlines ())
462
462
463
+ def test_caret_multiline_expression_syntax_error (self ):
464
+ # Make sure an expression spanning multiple lines that has
465
+ # a syntax error is correctly marked with carets.
466
+ code = textwrap .dedent ("""
467
+ def foo(*args, **kwargs):
468
+ pass
469
+
470
+ a, b, c = 1, 2, 3
471
+
472
+ foo(a, z
473
+ for z in
474
+ range(10), b, c)
475
+ """ )
476
+
477
+ def f_with_multiline ():
478
+ # Need to defer the compilation until in self.get_exception(..)
479
+ return compile (code , "?" , "exec" )
480
+
481
+ lineno_f = f_with_multiline .__code__ .co_firstlineno
482
+
483
+ expected_f = (
484
+ 'Traceback (most recent call last):\n '
485
+ f' File "{ __file__ } ", line { self .callable_line } , in get_exception\n '
486
+ ' callable()\n '
487
+ ' ^^^^^^^^^^\n '
488
+ f' File "{ __file__ } ", line { lineno_f + 2 } , in f_with_multiline\n '
489
+ ' return compile(code, "?", "exec")\n '
490
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^\n '
491
+ ' File "?", line 7\n '
492
+ ' foo(a, z\n '
493
+ ' ^'
494
+ )
495
+
496
+ result_lines = self .get_exception (f_with_multiline )
497
+ self .assertEqual (result_lines , expected_f .splitlines ())
498
+
463
499
def test_caret_multiline_expression_bin_op (self ):
464
500
# Make sure no carets are printed for expressions spanning multiple
465
501
# lines.
@@ -672,16 +708,14 @@ class CPythonTracebackErrorCaretTests(TracebackErrorLocationCaretTests):
672
708
Same set of tests as above but with Python's internal traceback printing.
673
709
"""
674
710
def get_exception (self , callable ):
675
- from _testcapi import traceback_print
711
+ from _testcapi import exception_print
676
712
try :
677
713
callable ()
678
714
self .fail ("No exception thrown." )
679
- except :
680
- type_ , value , tb = sys .exc_info ()
681
-
682
- file_ = StringIO ()
683
- traceback_print (tb , file_ )
684
- return file_ .getvalue ().splitlines ()
715
+ except Exception as e :
716
+ with captured_output ("stderr" ) as tbstderr :
717
+ exception_print (e )
718
+ return tbstderr .getvalue ().splitlines ()[:- 1 ]
685
719
686
720
callable_line = get_exception .__code__ .co_firstlineno + 3
687
721
0 commit comments