Skip to content

Commit 603d354

Browse files
authored
bpo-40493: fix function type comment parsing (GH-19894)
The grammar for func_type_input rejected things like `(*t1) ->t2`. This fixes that. Automerge-Triggered-By: @gvanrossum
1 parent c95e691 commit 603d354

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

Grammar/python.gram

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ type_expressions[asdl_seq*]:
4040
_PyPegen_seq_append_to_end(p, CHECK(_PyPegen_seq_append_to_end(p, a, b)), c) }
4141
| a=','.expression+ ',' '*' b=expression { _PyPegen_seq_append_to_end(p, a, b) }
4242
| a=','.expression+ ',' '**' b=expression { _PyPegen_seq_append_to_end(p, a, b) }
43+
| '*' a=expression ',' '**' b=expression {
44+
_PyPegen_seq_append_to_end(p, CHECK(_PyPegen_singleton_seq(p, a)), b) }
45+
| '*' a=expression { _PyPegen_singleton_seq(p, a) }
46+
| '**' a=expression { _PyPegen_singleton_seq(p, a) }
4347
| ','.expression+
4448

4549
statements[asdl_seq*]: a=statement+ { _PyPegen_seq_flatten(p, a) }

Lib/test/test_type_comments.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,14 @@ def parse_func_type_input(source):
399399
self.assertEqual(tree.argtypes[2].id, "Any")
400400
self.assertEqual(tree.returns.id, "float")
401401

402+
tree = parse_func_type_input("(*int) -> None")
403+
self.assertEqual(tree.argtypes[0].id, "int")
404+
tree = parse_func_type_input("(**int) -> None")
405+
self.assertEqual(tree.argtypes[0].id, "int")
406+
tree = parse_func_type_input("(*int, **str) -> None")
407+
self.assertEqual(tree.argtypes[0].id, "int")
408+
self.assertEqual(tree.argtypes[1].id, "str")
409+
402410
with self.assertRaises(SyntaxError):
403411
tree = parse_func_type_input("(int, *str, *Any) -> float")
404412

Parser/pegen/parse.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,9 @@ fstring_rule(Parser *p)
825825
// | ','.expression+ ',' '*' expression ',' '**' expression
826826
// | ','.expression+ ',' '*' expression
827827
// | ','.expression+ ',' '**' expression
828+
// | '*' expression ',' '**' expression
829+
// | '*' expression
830+
// | '**' expression
828831
// | ','.expression+
829832
static asdl_seq*
830833
type_expressions_rule(Parser *p)
@@ -915,6 +918,69 @@ type_expressions_rule(Parser *p)
915918
}
916919
p->mark = mark;
917920
}
921+
{ // '*' expression ',' '**' expression
922+
expr_ty a;
923+
expr_ty b;
924+
Token * literal;
925+
Token * literal_1;
926+
Token * literal_2;
927+
if (
928+
(literal = _PyPegen_expect_token(p, 16))
929+
&&
930+
(a = expression_rule(p))
931+
&&
932+
(literal_1 = _PyPegen_expect_token(p, 12))
933+
&&
934+
(literal_2 = _PyPegen_expect_token(p, 35))
935+
&&
936+
(b = expression_rule(p))
937+
)
938+
{
939+
res = _PyPegen_seq_append_to_end ( p , CHECK ( _PyPegen_singleton_seq ( p , a ) ) , b );
940+
if (res == NULL && PyErr_Occurred()) {
941+
p->error_indicator = 1;
942+
return NULL;
943+
}
944+
goto done;
945+
}
946+
p->mark = mark;
947+
}
948+
{ // '*' expression
949+
expr_ty a;
950+
Token * literal;
951+
if (
952+
(literal = _PyPegen_expect_token(p, 16))
953+
&&
954+
(a = expression_rule(p))
955+
)
956+
{
957+
res = _PyPegen_singleton_seq ( p , a );
958+
if (res == NULL && PyErr_Occurred()) {
959+
p->error_indicator = 1;
960+
return NULL;
961+
}
962+
goto done;
963+
}
964+
p->mark = mark;
965+
}
966+
{ // '**' expression
967+
expr_ty a;
968+
Token * literal;
969+
if (
970+
(literal = _PyPegen_expect_token(p, 35))
971+
&&
972+
(a = expression_rule(p))
973+
)
974+
{
975+
res = _PyPegen_singleton_seq ( p , a );
976+
if (res == NULL && PyErr_Occurred()) {
977+
p->error_indicator = 1;
978+
return NULL;
979+
}
980+
goto done;
981+
}
982+
p->mark = mark;
983+
}
918984
{ // ','.expression+
919985
asdl_seq * _gather_9_var;
920986
if (

0 commit comments

Comments
 (0)