mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-111420: Allow type comments in parenthesized with statements (#111468)
				
					
				
			This commit is contained in:
		
							parent
							
								
									faa5f6053d
								
							
						
					
					
						commit
						453e96e302
					
				
					 5 changed files with 32 additions and 8 deletions
				
			
		| 
						 | 
					@ -391,8 +391,8 @@ for_stmt[stmt_ty]:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
with_stmt[stmt_ty]:
 | 
					with_stmt[stmt_ty]:
 | 
				
			||||||
    | invalid_with_stmt_indent
 | 
					    | invalid_with_stmt_indent
 | 
				
			||||||
    | 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block {
 | 
					    | 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' tc=[TYPE_COMMENT] b=block {
 | 
				
			||||||
        CHECK_VERSION(stmt_ty, 9, "Parenthesized context managers are", _PyAST_With(a, b, NULL, EXTRA)) }
 | 
					       CHECK_VERSION(stmt_ty, 9, "Parenthesized context managers are", _PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
 | 
				
			||||||
    | 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
 | 
					    | 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
 | 
				
			||||||
        _PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) }
 | 
					        _PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) }
 | 
				
			||||||
    | 'async' 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block {
 | 
					    | 'async' 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,6 +100,8 @@ def to_tuple(t):
 | 
				
			||||||
    # With
 | 
					    # With
 | 
				
			||||||
    "with x as y: pass",
 | 
					    "with x as y: pass",
 | 
				
			||||||
    "with x as y, z as q: pass",
 | 
					    "with x as y, z as q: pass",
 | 
				
			||||||
 | 
					    "with (x as y): pass",
 | 
				
			||||||
 | 
					    "with (x, y): pass",
 | 
				
			||||||
    # Raise
 | 
					    # Raise
 | 
				
			||||||
    "raise Exception('string')",
 | 
					    "raise Exception('string')",
 | 
				
			||||||
    # TryExcept
 | 
					    # TryExcept
 | 
				
			||||||
| 
						 | 
					@ -3015,6 +3017,8 @@ def main():
 | 
				
			||||||
('Module', [('If', (1, 0, 6, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 6, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [('Pass', (6, 2, 6, 6))])])], []),
 | 
					('Module', [('If', (1, 0, 6, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 6, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [('Pass', (6, 2, 6, 6))])])], []),
 | 
				
			||||||
('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',)))], [('Pass', (1, 13, 1, 17))], None)], []),
 | 
					('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',)))], [('Pass', (1, 13, 1, 17))], None)], []),
 | 
				
			||||||
('Module', [('With', (1, 0, 1, 25), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',))), ('withitem', ('Name', (1, 13, 1, 14), 'z', ('Load',)), ('Name', (1, 18, 1, 19), 'q', ('Store',)))], [('Pass', (1, 21, 1, 25))], None)], []),
 | 
					('Module', [('With', (1, 0, 1, 25), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',))), ('withitem', ('Name', (1, 13, 1, 14), 'z', ('Load',)), ('Name', (1, 18, 1, 19), 'q', ('Store',)))], [('Pass', (1, 21, 1, 25))], None)], []),
 | 
				
			||||||
 | 
					('Module', [('With', (1, 0, 1, 19), [('withitem', ('Name', (1, 6, 1, 7), 'x', ('Load',)), ('Name', (1, 11, 1, 12), 'y', ('Store',)))], [('Pass', (1, 15, 1, 19))], None)], []),
 | 
				
			||||||
 | 
					('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 6, 1, 7), 'x', ('Load',)), None), ('withitem', ('Name', (1, 9, 1, 10), 'y', ('Load',)), None)], [('Pass', (1, 13, 1, 17))], None)], []),
 | 
				
			||||||
('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []),
 | 
					('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []),
 | 
				
			||||||
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []),
 | 
					('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []),
 | 
				
			||||||
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []),
 | 
					('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,14 @@ def foo():
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parenthesized_withstmt = """\
 | 
				
			||||||
 | 
					with (a as b):  # type: int
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					with (a, b):  # type: int
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vardecl = """\
 | 
					vardecl = """\
 | 
				
			||||||
a = 0  # type: int
 | 
					a = 0  # type: int
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
| 
						 | 
					@ -300,6 +308,14 @@ def test_withstmt(self):
 | 
				
			||||||
        tree = self.classic_parse(withstmt)
 | 
					        tree = self.classic_parse(withstmt)
 | 
				
			||||||
        self.assertEqual(tree.body[0].type_comment, None)
 | 
					        self.assertEqual(tree.body[0].type_comment, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_parenthesized_withstmt(self):
 | 
				
			||||||
 | 
					        for tree in self.parse_all(parenthesized_withstmt, minver=9):
 | 
				
			||||||
 | 
					            self.assertEqual(tree.body[0].type_comment, "int")
 | 
				
			||||||
 | 
					            self.assertEqual(tree.body[1].type_comment, "int")
 | 
				
			||||||
 | 
					        tree = self.classic_parse(parenthesized_withstmt)
 | 
				
			||||||
 | 
					        self.assertEqual(tree.body[0].type_comment, None)
 | 
				
			||||||
 | 
					        self.assertEqual(tree.body[1].type_comment, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_vardecl(self):
 | 
					    def test_vardecl(self):
 | 
				
			||||||
        for tree in self.parse_all(vardecl):
 | 
					        for tree in self.parse_all(vardecl):
 | 
				
			||||||
            self.assertEqual(tree.body[0].type_comment, "int")
 | 
					            self.assertEqual(tree.body[0].type_comment, "int")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Allow type comments in parenthesized ``with`` statements
 | 
				
			||||||
							
								
								
									
										15
									
								
								Parser/parser.c
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								Parser/parser.c
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -6483,7 +6483,7 @@ for_stmt_rule(Parser *p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// with_stmt:
 | 
					// with_stmt:
 | 
				
			||||||
//     | invalid_with_stmt_indent
 | 
					//     | invalid_with_stmt_indent
 | 
				
			||||||
//     | 'with' '(' ','.with_item+ ','? ')' ':' block
 | 
					//     | 'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block
 | 
				
			||||||
//     | 'with' ','.with_item+ ':' TYPE_COMMENT? block
 | 
					//     | 'with' ','.with_item+ ':' TYPE_COMMENT? block
 | 
				
			||||||
//     | 'async' 'with' '(' ','.with_item+ ','? ')' ':' block
 | 
					//     | 'async' 'with' '(' ','.with_item+ ','? ')' ':' block
 | 
				
			||||||
//     | 'async' 'with' ','.with_item+ ':' TYPE_COMMENT? block
 | 
					//     | 'async' 'with' ','.with_item+ ':' TYPE_COMMENT? block
 | 
				
			||||||
| 
						 | 
					@ -6528,12 +6528,12 @@ with_stmt_rule(Parser *p)
 | 
				
			||||||
        D(fprintf(stderr, "%*c%s with_stmt[%d-%d]: %s failed!\n", p->level, ' ',
 | 
					        D(fprintf(stderr, "%*c%s with_stmt[%d-%d]: %s failed!\n", p->level, ' ',
 | 
				
			||||||
                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_with_stmt_indent"));
 | 
					                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_with_stmt_indent"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    { // 'with' '(' ','.with_item+ ','? ')' ':' block
 | 
					    { // 'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block
 | 
				
			||||||
        if (p->error_indicator) {
 | 
					        if (p->error_indicator) {
 | 
				
			||||||
            p->level--;
 | 
					            p->level--;
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block"));
 | 
					        D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block"));
 | 
				
			||||||
        Token * _keyword;
 | 
					        Token * _keyword;
 | 
				
			||||||
        Token * _literal;
 | 
					        Token * _literal;
 | 
				
			||||||
        Token * _literal_1;
 | 
					        Token * _literal_1;
 | 
				
			||||||
| 
						 | 
					@ -6542,6 +6542,7 @@ with_stmt_rule(Parser *p)
 | 
				
			||||||
        UNUSED(_opt_var); // Silence compiler warnings
 | 
					        UNUSED(_opt_var); // Silence compiler warnings
 | 
				
			||||||
        asdl_withitem_seq* a;
 | 
					        asdl_withitem_seq* a;
 | 
				
			||||||
        asdl_stmt_seq* b;
 | 
					        asdl_stmt_seq* b;
 | 
				
			||||||
 | 
					        void *tc;
 | 
				
			||||||
        if (
 | 
					        if (
 | 
				
			||||||
            (_keyword = _PyPegen_expect_token(p, 629))  // token='with'
 | 
					            (_keyword = _PyPegen_expect_token(p, 629))  // token='with'
 | 
				
			||||||
            &&
 | 
					            &&
 | 
				
			||||||
| 
						 | 
					@ -6555,10 +6556,12 @@ with_stmt_rule(Parser *p)
 | 
				
			||||||
            &&
 | 
					            &&
 | 
				
			||||||
            (_literal_2 = _PyPegen_expect_token(p, 11))  // token=':'
 | 
					            (_literal_2 = _PyPegen_expect_token(p, 11))  // token=':'
 | 
				
			||||||
            &&
 | 
					            &&
 | 
				
			||||||
 | 
					            (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator)  // TYPE_COMMENT?
 | 
				
			||||||
 | 
					            &&
 | 
				
			||||||
            (b = block_rule(p))  // block
 | 
					            (b = block_rule(p))  // block
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block"));
 | 
					            D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block"));
 | 
				
			||||||
            Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
 | 
					            Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
 | 
				
			||||||
            if (_token == NULL) {
 | 
					            if (_token == NULL) {
 | 
				
			||||||
                p->level--;
 | 
					                p->level--;
 | 
				
			||||||
| 
						 | 
					@ -6568,7 +6571,7 @@ with_stmt_rule(Parser *p)
 | 
				
			||||||
            UNUSED(_end_lineno); // Only used by EXTRA macro
 | 
					            UNUSED(_end_lineno); // Only used by EXTRA macro
 | 
				
			||||||
            int _end_col_offset = _token->end_col_offset;
 | 
					            int _end_col_offset = _token->end_col_offset;
 | 
				
			||||||
            UNUSED(_end_col_offset); // Only used by EXTRA macro
 | 
					            UNUSED(_end_col_offset); // Only used by EXTRA macro
 | 
				
			||||||
            _res = CHECK_VERSION ( stmt_ty , 9 , "Parenthesized context managers are" , _PyAST_With ( a , b , NULL , EXTRA ) );
 | 
					            _res = CHECK_VERSION ( stmt_ty , 9 , "Parenthesized context managers are" , _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) );
 | 
				
			||||||
            if (_res == NULL && PyErr_Occurred()) {
 | 
					            if (_res == NULL && PyErr_Occurred()) {
 | 
				
			||||||
                p->error_indicator = 1;
 | 
					                p->error_indicator = 1;
 | 
				
			||||||
                p->level--;
 | 
					                p->level--;
 | 
				
			||||||
| 
						 | 
					@ -6578,7 +6581,7 @@ with_stmt_rule(Parser *p)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        p->mark = _mark;
 | 
					        p->mark = _mark;
 | 
				
			||||||
        D(fprintf(stderr, "%*c%s with_stmt[%d-%d]: %s failed!\n", p->level, ' ',
 | 
					        D(fprintf(stderr, "%*c%s with_stmt[%d-%d]: %s failed!\n", p->level, ' ',
 | 
				
			||||||
                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block"));
 | 
					                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    { // 'with' ','.with_item+ ':' TYPE_COMMENT? block
 | 
					    { // 'with' ','.with_item+ ':' TYPE_COMMENT? block
 | 
				
			||||||
        if (p->error_indicator) {
 | 
					        if (p->error_indicator) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue