diff options
author | Crowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com> | 2023-11-20 21:27:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-20 13:27:53 +0000 |
commit | 1c8f912ebdfdb146cd7dd2d7a3a67d2c5045ddb0 (patch) | |
tree | d2553d0e973e0d59f0bc20c90aba252c5efd6c40 /Lib/test/test_syntax.py | |
parent | 56e59a49ae4d9f518c5cc918aefe7eeee11736b4 (diff) | |
download | cpython-1c8f912ebdfdb146cd7dd2d7a3a67d2c5045ddb0.tar.gz cpython-1c8f912ebdfdb146cd7dd2d7a3a67d2c5045ddb0.zip |
bpo-45759: Better error messages for non-matching 'elif'/'else' statements (#29513)
Diffstat (limited to 'Lib/test/test_syntax.py')
-rw-r--r-- | Lib/test/test_syntax.py | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 7ebf9ca1707..f6fa6495508 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -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" |