mirror of https://github.com/python/cpython
gh-111420: Allow type comments in parenthesized `with` statements (#111468)
This commit is contained in:
parent
faa5f6053d
commit
453e96e302
|
@ -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 @@ exec_tests = [
|
||||||
# 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 @@ exec_results = [
|
||||||
('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 @@ with context() as a: # type: int
|
||||||
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 @@ class TypeCommentTests(unittest.TestCase):
|
||||||
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
|
|
@ -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…
Reference in New Issue