17521752 Traceback (most recent call last):
17531753 SyntaxError: positional patterns follow keyword patterns
17541754
1755+ Non-matching 'elif'/'else' statements:
1756+
1757+ >>> if a == b:
1758+ ... ...
1759+ ... elif a == c:
1760+ Traceback (most recent call last):
1761+ SyntaxError: 'elif' must match an if-statement here
1762+
1763+ >>> if x == y:
1764+ ... ...
1765+ ... else:
1766+ Traceback (most recent call last):
1767+ SyntaxError: 'else' must match a valid statement here
1768+
1769+ >>> elif m == n:
1770+ Traceback (most recent call last):
1771+ SyntaxError: 'elif' must match an if-statement here
1772+
1773+ >>> else:
1774+ Traceback (most recent call last):
1775+ SyntaxError: 'else' must match a valid statement here
1776+
17551777Uses of the star operator which should fail:
17561778
17571779A[:*b]
@@ -2006,8 +2028,8 @@ def _check_error(self, code, errtext,
20062028 lineno = None , offset = None , end_lineno = None , end_offset = None ):
20072029 """Check that compiling code raises SyntaxError with errtext.
20082030
2009- errtest is a regular expression that must be present in the
2010- test of the exception raised. If subclass is specified it
2031+ errtext is a regular expression that must be present in the
2032+ test of the exception raised. If subclass is specified, it
20112033 is the expected subclass of SyntaxError (e.g. IndentationError).
20122034 """
20132035 try :
@@ -2031,6 +2053,22 @@ def _check_error(self, code, errtext,
20312053 else :
20322054 self .fail ("compile() did not raise SyntaxError" )
20332055
2056+ def _check_noerror (self , code ,
2057+ errtext = "compile() raised unexpected SyntaxError" ,
2058+ filename = "<testcase>" , mode = "exec" , subclass = None ):
2059+ """Check that compiling code does not raise a SyntaxError.
2060+
2061+ errtext is the message passed to self.fail if there is
2062+ a SyntaxError. If the subclass parameter is specified,
2063+ it is the subclass of SyntaxError (e.g. IndentationError)
2064+ that the raised error is checked against.
2065+ """
2066+ try :
2067+ compile (code , filename , mode )
2068+ except SyntaxError as err :
2069+ if (not subclass ) or isinstance (err , subclass ):
2070+ self .fail (errtext )
2071+
20342072 def test_expression_with_assignment (self ):
20352073 self ._check_error (
20362074 "print(end1 + end2 = ' ')" ,
@@ -2372,6 +2410,25 @@ def test_syntax_error_on_deeply_nested_blocks(self):
23722410"""
23732411 self ._check_error (source , "too many statically nested blocks" )
23742412
2413+ def test_syntax_error_non_matching_elif_else_statements (self ):
2414+ # Check bpo-45759: 'elif' statements that doesn't match an
2415+ # if-statement or 'else' statements that doesn't match any
2416+ # valid else-able statement (e.g. 'while')
2417+ self ._check_error (
2418+ "elif m == n:\n ..." ,
2419+ "'elif' must match an if-statement here" )
2420+ self ._check_error (
2421+ "else:\n ..." ,
2422+ "'else' must match a valid statement here" )
2423+ self ._check_noerror ("if a == b:\n ...\n elif a == c:\n ..." )
2424+ self ._check_noerror ("if x == y:\n ...\n else:\n ..." )
2425+ self ._check_error (
2426+ "else = 123" ,
2427+ "invalid syntax" )
2428+ self ._check_error (
2429+ "elif 55 = 123" ,
2430+ "cannot assign to literal here" )
2431+
23752432 @support .cpython_only
23762433 def test_error_on_parser_stack_overflow (self ):
23772434 source = "-" * 100000 + "4"
0 commit comments