Skip to content

Commit b63fd2a

Browse files
committed
Issue #9154: Merge fix from 3.2.
2 parents 119d026 + ea7e9f9 commit b63fd2a

File tree

3 files changed

+94
-57
lines changed

3 files changed

+94
-57
lines changed

Lib/test/test_parser.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,27 @@ def test_function_defs(self):
150150
self.check_suite("@funcattrs()\n"
151151
"def f(): pass")
152152

153+
# keyword-only arguments
154+
self.check_suite("def f(*, a): pass")
155+
self.check_suite("def f(*, a = 5): pass")
156+
self.check_suite("def f(*, a = 5, b): pass")
157+
self.check_suite("def f(*, a, b = 5): pass")
158+
self.check_suite("def f(*, a, b = 5, **kwds): pass")
159+
self.check_suite("def f(*args, a): pass")
160+
self.check_suite("def f(*args, a = 5): pass")
161+
self.check_suite("def f(*args, a = 5, b): pass")
162+
self.check_suite("def f(*args, a, b = 5): pass")
163+
self.check_suite("def f(*args, a, b = 5, **kwds): pass")
164+
165+
# function annotations
166+
self.check_suite("def f(a: int): pass")
167+
self.check_suite("def f(a: int = 5): pass")
168+
self.check_suite("def f(*args: list): pass")
169+
self.check_suite("def f(**kwds: dict): pass")
170+
self.check_suite("def f(*, a: int): pass")
171+
self.check_suite("def f(*, a: int = 5): pass")
172+
self.check_suite("def f() -> int: pass")
173+
153174
def test_class_defs(self):
154175
self.check_suite("class foo():pass")
155176
self.check_suite("class foo(object):pass")

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ Core and Builtins
8484
Library
8585
-------
8686

87+
- Issue #9154: Fix parser module to understand function annotations.
88+
8789
- Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the
8890
client ip address instead client hostname. Patch by Charles-François Natali.
8991

Modules/parsermodule.c

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ static int validate_terminal(node *terminal, int type, char *string);
940940
#define validate_doublestar(ch) validate_terminal(ch, DOUBLESTAR, "**")
941941
#define validate_dot(ch) validate_terminal(ch, DOT, ".")
942942
#define validate_at(ch) validate_terminal(ch, AT, "@")
943+
#define validate_rarrow(ch) validate_terminal(ch, RARROW, "->")
943944
#define validate_name(ch, str) validate_terminal(ch, NAME, str)
944945

945946
#define VALIDATER(n) static int validate_##n(node *tree)
@@ -1229,68 +1230,68 @@ validate_vfpdef(node *tree)
12291230
return 0;
12301231
}
12311232

1232-
/* '*' vfpdef (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef
1233+
/* '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef
12331234
* ..or tfpdef in place of vfpdef. vfpdef: NAME; tfpdef: NAME [':' test]
12341235
*/
12351236
static int
12361237
validate_varargslist_trailer(node *tree, int start)
12371238
{
12381239
int nch = NCH(tree);
1239-
int res = 0, i;
1240-
int sym;
1240+
int res = 0;
12411241

12421242
if (nch <= start) {
12431243
err_string("expected variable argument trailer for varargslist");
12441244
return 0;
12451245
}
1246-
sym = TYPE(CHILD(tree, start));
1247-
if (sym == STAR) {
1246+
if (TYPE(CHILD(tree, start)) == STAR) {
12481247
/*
1249-
* '*' vfpdef (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef
1248+
* '*' [vfpdef]
12501249
*/
1251-
if (nch-start == 2)
1252-
res = validate_vfpdef(CHILD(tree, start+1));
1253-
else if (nch-start == 5 && TYPE(CHILD(tree, start+2)) == COMMA)
1254-
res = (validate_vfpdef(CHILD(tree, start+1))
1255-
&& validate_comma(CHILD(tree, start+2))
1256-
&& validate_doublestar(CHILD(tree, start+3))
1257-
&& validate_vfpdef(CHILD(tree, start+4)));
1258-
else {
1259-
/* skip over vfpdef (',' vfpdef ['=' test])* */
1260-
i = start + 1;
1261-
if (TYPE(CHILD(tree, i)) == vfpdef ||
1262-
TYPE(CHILD(tree, i)) == tfpdef) { /* skip over vfpdef or tfpdef */
1263-
i += 1;
1264-
}
1265-
while (res && i+1 < nch) { /* validate (',' vfpdef ['=' test])* */
1266-
res = validate_comma(CHILD(tree, i));
1267-
if (TYPE(CHILD(tree, i+1)) == DOUBLESTAR)
1268-
break;
1269-
res = res && validate_vfpdef(CHILD(tree, i+1));
1270-
if (res && i+2 < nch && TYPE(CHILD(tree, i+2)) == EQUAL) {
1271-
res = res && (i+3 < nch)
1272-
&& validate_test(CHILD(tree, i+3));
1273-
i += 4;
1274-
}
1275-
else {
1276-
i += 2;
1277-
}
1278-
}
1279-
/* [',' '**' vfpdef] */
1280-
if (res && i+1 < nch && TYPE(CHILD(tree, i+1)) == DOUBLESTAR) {
1281-
res = validate_vfpdef(CHILD(tree, i+2));
1282-
}
1250+
res = validate_star(CHILD(tree, start++));
1251+
if (res && start < nch && (TYPE(CHILD(tree, start)) == vfpdef ||
1252+
TYPE(CHILD(tree, start)) == tfpdef))
1253+
res = validate_vfpdef(CHILD(tree, start++));
1254+
/*
1255+
* (',' vfpdef ['=' test])*
1256+
*/
1257+
while (res && start + 1 < nch && (
1258+
TYPE(CHILD(tree, start + 1)) == vfpdef ||
1259+
TYPE(CHILD(tree, start + 1)) == tfpdef)) {
1260+
res = (validate_comma(CHILD(tree, start++))
1261+
&& validate_vfpdef(CHILD(tree, start++)));
1262+
if (res && start + 1 < nch && TYPE(CHILD(tree, start)) == EQUAL)
1263+
res = (validate_equal(CHILD(tree, start++))
1264+
&& validate_test(CHILD(tree, start++)));
12831265
}
1266+
/*
1267+
* [',' '**' vfpdef]
1268+
*/
1269+
if (res && start + 2 < nch && TYPE(CHILD(tree, start+1)) == DOUBLESTAR)
1270+
res = (validate_comma(CHILD(tree, start++))
1271+
&& validate_doublestar(CHILD(tree, start++))
1272+
&& validate_vfpdef(CHILD(tree, start++)));
12841273
}
1285-
else if (sym == DOUBLESTAR) {
1274+
else if (TYPE(CHILD(tree, start)) == DOUBLESTAR) {
12861275
/*
1287-
* '**' NAME
1276+
* '**' vfpdef
12881277
*/
1289-
if (nch-start == 2)
1290-
res = validate_vfpdef(CHILD(tree, start+1));
1278+
if (start + 1 < nch)
1279+
res = (validate_doublestar(CHILD(tree, start++))
1280+
&& validate_vfpdef(CHILD(tree, start++)));
1281+
else {
1282+
res = 0;
1283+
err_string("expected vfpdef after ** in varargslist trailer");
1284+
}
1285+
}
1286+
else {
1287+
res = 0;
1288+
err_string("expected * or ** in varargslist trailer");
1289+
}
1290+
1291+
if (res && start != nch) {
1292+
res = 0;
1293+
err_string("unexpected extra children in varargslist trailer");
12911294
}
1292-
if (!res)
1293-
err_string("illegal variable argument trailer for varargslist");
12941295
return res;
12951296
}
12961297

@@ -2525,23 +2526,36 @@ validate_with_stmt(node *tree)
25252526
return ok;
25262527
}
25272528

2528-
/* funcdef:
2529-
*
2530-
* -5 -4 -3 -2 -1
2531-
* 'def' NAME parameters ':' suite
2532-
*/
2529+
/* funcdef: 'def' NAME parameters ['->' test] ':' suite */
2530+
25332531
static int
25342532
validate_funcdef(node *tree)
25352533
{
25362534
int nch = NCH(tree);
2537-
int ok = (validate_ntype(tree, funcdef)
2538-
&& (nch == 5)
2539-
&& validate_name(RCHILD(tree, -5), "def")
2540-
&& validate_ntype(RCHILD(tree, -4), NAME)
2541-
&& validate_colon(RCHILD(tree, -2))
2542-
&& validate_parameters(RCHILD(tree, -3))
2543-
&& validate_suite(RCHILD(tree, -1)));
2544-
return ok;
2535+
int res = validate_ntype(tree, funcdef);
2536+
if (res) {
2537+
if (nch == 5) {
2538+
res = (validate_name(CHILD(tree, 0), "def")
2539+
&& validate_ntype(CHILD(tree, 1), NAME)
2540+
&& validate_parameters(CHILD(tree, 2))
2541+
&& validate_colon(CHILD(tree, 3))
2542+
&& validate_suite(CHILD(tree, 4)));
2543+
}
2544+
else if (nch == 7) {
2545+
res = (validate_name(CHILD(tree, 0), "def")
2546+
&& validate_ntype(CHILD(tree, 1), NAME)
2547+
&& validate_parameters(CHILD(tree, 2))
2548+
&& validate_rarrow(CHILD(tree, 3))
2549+
&& validate_test(CHILD(tree, 4))
2550+
&& validate_colon(CHILD(tree, 5))
2551+
&& validate_suite(CHILD(tree, 6)));
2552+
}
2553+
else {
2554+
res = 0;
2555+
err_string("illegal number of children for funcdef");
2556+
}
2557+
}
2558+
return res;
25452559
}
25462560

25472561

0 commit comments

Comments
 (0)