bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)

To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:

>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^
SyntaxError: Generator expression must be parenthesized

becomes

>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
This commit is contained in:
Pablo Galindo 2021-04-23 14:27:05 +01:00 committed by GitHub
parent 91b69b77cf
commit a77aac4fca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 1687 additions and 1219 deletions

View file

@ -601,7 +601,7 @@ class CmdLineTest(unittest.TestCase):
exitcode, stdout, stderr = assert_python_failure(script_name)
text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read()
# Confirm that the caret is located under the '=' sign
self.assertIn("\n 1 + 1 = 2\n ^\n", text)
self.assertIn("\n ^^^^^\n", text)
def test_syntaxerror_indented_caret_position(self):
script = textwrap.dedent("""\
@ -612,8 +612,8 @@ class CmdLineTest(unittest.TestCase):
script_name = _make_test_script(script_dir, 'script', script)
exitcode, stdout, stderr = assert_python_failure(script_name)
text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read()
# Confirm that the caret is located under the first 1 character
self.assertIn("\n 1 + 1 = 2\n ^\n", text)
# Confirm that the caret starts under the first 1 character
self.assertIn("\n 1 + 1 = 2\n ^^^^^\n", text)
# Try the same with a form feed at the start of the indented line
script = (
@ -624,7 +624,7 @@ class CmdLineTest(unittest.TestCase):
exitcode, stdout, stderr = assert_python_failure(script_name)
text = io.TextIOWrapper(io.BytesIO(stderr), "ascii").read()
self.assertNotIn("\f", text)
self.assertIn("\n 1 + 1 = 2\n ^\n", text)
self.assertIn("\n 1 + 1 = 2\n ^^^^^\n", text)
def test_syntaxerror_multi_line_fstring(self):
script = 'foo = f"""{}\nfoo"""\n'
@ -650,7 +650,7 @@ class CmdLineTest(unittest.TestCase):
self.assertEqual(
stderr.splitlines()[-3:],
[ b' foo = """\\q"""',
b' ^',
b' ^^^^^^^^',
b'SyntaxError: invalid escape sequence \\q'
],
)