bpo-45759: Better error messages for non-matching 'elif'/'else' statements (#29513)

This commit is contained in:
Crowthebird 2023-11-20 21:27:53 +08:00 committed by GitHub
parent 56e59a49ae
commit 1c8f912ebd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 598 additions and 437 deletions

View file

@ -1752,6 +1752,28 @@ Corner-cases that used to crash:
Traceback (most recent call last):
SyntaxError: positional patterns follow keyword patterns
Non-matching 'elif'/'else' statements:
>>> if a == b:
... ...
... elif a == c:
Traceback (most recent call last):
SyntaxError: 'elif' must match an if-statement here
>>> if x == y:
... ...
... else:
Traceback (most recent call last):
SyntaxError: 'else' must match a valid statement here
>>> elif m == n:
Traceback (most recent call last):
SyntaxError: 'elif' must match an if-statement here
>>> else:
Traceback (most recent call last):
SyntaxError: 'else' must match a valid statement here
Uses of the star operator which should fail:
A[:*b]
@ -2006,8 +2028,8 @@ class SyntaxTestCase(unittest.TestCase):
lineno=None, offset=None, end_lineno=None, end_offset=None):
"""Check that compiling code raises SyntaxError with errtext.
errtest is a regular expression that must be present in the
test of the exception raised. If subclass is specified it
errtext is a regular expression that must be present in the
test of the exception raised. If subclass is specified, it
is the expected subclass of SyntaxError (e.g. IndentationError).
"""
try:
@ -2031,6 +2053,22 @@ class SyntaxTestCase(unittest.TestCase):
else:
self.fail("compile() did not raise SyntaxError")
def _check_noerror(self, code,
errtext="compile() raised unexpected SyntaxError",
filename="<testcase>", mode="exec", subclass=None):
"""Check that compiling code does not raise a SyntaxError.
errtext is the message passed to self.fail if there is
a SyntaxError. If the subclass parameter is specified,
it is the subclass of SyntaxError (e.g. IndentationError)
that the raised error is checked against.
"""
try:
compile(code, filename, mode)
except SyntaxError as err:
if (not subclass) or isinstance(err, subclass):
self.fail(errtext)
def test_expression_with_assignment(self):
self._check_error(
"print(end1 + end2 = ' ')",
@ -2372,6 +2410,25 @@ while 1:
"""
self._check_error(source, "too many statically nested blocks")
def test_syntax_error_non_matching_elif_else_statements(self):
# Check bpo-45759: 'elif' statements that doesn't match an
# if-statement or 'else' statements that doesn't match any
# valid else-able statement (e.g. 'while')
self._check_error(
"elif m == n:\n ...",
"'elif' must match an if-statement here")
self._check_error(
"else:\n ...",
"'else' must match a valid statement here")
self._check_noerror("if a == b:\n ...\nelif a == c:\n ...")
self._check_noerror("if x == y:\n ...\nelse:\n ...")
self._check_error(
"else = 123",
"invalid syntax")
self._check_error(
"elif 55 = 123",
"cannot assign to literal here")
@support.cpython_only
def test_error_on_parser_stack_overflow(self):
source = "-" * 100000 + "4"