cpython: 419ceb531bab (original) (raw)
--- a/Doc/reference/compound_stmts.rst
+++ b/Doc/reference/compound_stmts.rst
@@ -471,10 +471,10 @@ A function definition defines a user-def
decorators: decorator
+
decorator: "@" dotted_name
["(" [parameter_list
[","]] ")"] NEWLINE
dotted_name: identifier
("." identifier
)*
- parameter_list: (
defparameter
",")* : | "*" [`parameter`] ("," `defparameter`)* ["," "**" `parameter`][](#l1.8)
: | "**" `parameter`[](#l1.9)
: | `defparameter` [","] )[](#l1.10)
- parameter_list:
defparameter
(","defparameter
)* ["," [parameter_list_starargs
]] : | `parameter_list_starargs`[](#l1.12)
- parameter_list_starargs: "" [
parameter
] (","defparameter
) ["," ["**"parameter
[","]]]
parameter:: | "**" `parameter` [","][](#l1.14)
identifier
[":"expression
] defparameter:parameter
["="expression
] funcname:identifier
--- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -27,13 +27,18 @@ async_funcdef: ASYNC funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' -typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [','
['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]][](#l2.8)
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)[](#l2.9)
+typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
'*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]][](#l2.11)
| '**' tfpdef [',']]][](#l2.12)
- | '' [tfpdef] (',' tfpdef ['=' test]) [',' ['**' tfpdef [',']]]
- | '**' tfpdef [',']) tfpdef: NAME [':' test] -varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [','
['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]][](#l2.17)
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef)[](#l2.18)
+varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
'*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]][](#l2.20)
| '**' vfpdef [',']]][](#l2.21)
- | '' [vfpdef] (',' vfpdef ['=' test]) [',' ['**' vfpdef [',']]]
- | '**' vfpdef [','] +) vfpdef: NAME stmt: simple_stmt | compound_stmt
--- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -295,6 +295,10 @@ class GrammarTests(unittest.TestCase): pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200) pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
self.assertRaises(SyntaxError, eval, "def f(*): pass")[](#l3.7)
self.assertRaises(SyntaxError, eval, "def f(*,): pass")[](#l3.8)
self.assertRaises(SyntaxError, eval, "def f(*, **kwds): pass")[](#l3.9)
+ # keyword arguments after *arglist def f(*args, **kwargs): return args, kwargs @@ -352,6 +356,23 @@ class GrammarTests(unittest.TestCase): check_syntax_error(self, "f(*g(1=2))") check_syntax_error(self, "f(**g(1=2))")
# Check trailing commas are permitted in funcdef argument list[](#l3.18)
def f(a,): pass[](#l3.19)
def f(*args,): pass[](#l3.20)
def f(**kwds,): pass[](#l3.21)
def f(a, *args,): pass[](#l3.22)
def f(a, **kwds,): pass[](#l3.23)
def f(*args, b,): pass[](#l3.24)
def f(*, b,): pass[](#l3.25)
def f(*args, **kwds,): pass[](#l3.26)
def f(a, *args, b,): pass[](#l3.27)
def f(a, *, b,): pass[](#l3.28)
def f(a, *args, **kwds,): pass[](#l3.29)
def f(*args, b, **kwds,): pass[](#l3.30)
def f(*, b, **kwds,): pass[](#l3.31)
def f(a, *args, b, **kwds,): pass[](#l3.32)
def f(a, *, b, **kwds,): pass[](#l3.33)
+ def test_lambdef(self): ### lambdef: 'lambda' [varargslist] ':' test l1 = lambda : 0 @@ -370,6 +391,23 @@ class GrammarTests(unittest.TestCase): self.assertEqual(l6(1,2), 1+2+20) self.assertEqual(l6(1,2,k=10), 1+2+10)
# check that trailing commas are permitted[](#l3.42)
l10 = lambda a,: 0[](#l3.43)
l11 = lambda *args,: 0[](#l3.44)
l12 = lambda **kwds,: 0[](#l3.45)
l13 = lambda a, *args,: 0[](#l3.46)
l14 = lambda a, **kwds,: 0[](#l3.47)
l15 = lambda *args, b,: 0[](#l3.48)
l16 = lambda *, b,: 0[](#l3.49)
l17 = lambda *args, **kwds,: 0[](#l3.50)
l18 = lambda a, *args, b,: 0[](#l3.51)
l19 = lambda a, *, b,: 0[](#l3.52)
l20 = lambda a, *args, **kwds,: 0[](#l3.53)
l21 = lambda *args, b, **kwds,: 0[](#l3.54)
l22 = lambda *, b, **kwds,: 0[](#l3.55)
l23 = lambda a, *args, b, **kwds,: 0[](#l3.56)
l24 = lambda a, *, b, **kwds,: 0[](#l3.57)
+ ### stmt: simple_stmt | compound_stmt # Tested below
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Release date: XXXX-XX-XX Core and Builtins ----------------- +- Issue #9232: Modify Python's grammar to allow trailing commas in the
- argument list of a function declaration. For example, "def f(*, a =
- 3,): pass" is now legal. Patch from Mark Dickinson. +
--- a/Python/ast.c +++ b/Python/ast.c @@ -1260,16 +1260,20 @@ ast_for_arguments(struct compiling *c, c and varargslist (lambda definition). parameters: '(' [typedargslist] ')'
typedargslist: ((tfpdef ['=' test] ',')*[](#l5.7)
('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef][](#l5.8)
| '**' tfpdef)[](#l5.9)
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])[](#l5.10)
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [[](#l5.11)
'*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]][](#l5.12)
| '**' tfpdef [',']]][](#l5.13)
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]][](#l5.14)
| '**' tfpdef [','])[](#l5.15) tfpdef: NAME [':' test][](#l5.16)
varargslist: ((vfpdef ['=' test] ',')*[](#l5.17)
('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef][](#l5.18)
| '**' vfpdef)[](#l5.19)
| vfpdef ['=' test] (',' vfpdef ['=' test])* [','])[](#l5.20)
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [[](#l5.21)
'*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]][](#l5.22)
| '**' vfpdef [',']]][](#l5.23)
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]][](#l5.24)
| '**' vfpdef [','][](#l5.25)
)[](#l5.26) vfpdef: NAME[](#l5.27)
+ */ int i, j, k, nposargs = 0, nkwonlyargs = 0; int nposdefaults = 0, found_default = 0; @@ -1371,7 +1375,8 @@ ast_for_arguments(struct compiling c, c i += 2; / the name and the comma */ break; case STAR:
if (i+1 >= NCH(n)) {[](#l5.36)
if (i+1 >= NCH(n) ||[](#l5.37)
(i+2 == NCH(n) && TYPE(CHILD(n, i+1)) == COMMA)) {[](#l5.38) ast_error(c, CHILD(n, i),[](#l5.39) "named arguments must follow bare *");[](#l5.40) return NULL;[](#l5.41)
--- a/Python/graminit.c +++ b/Python/graminit.c @@ -204,11 +204,13 @@ static arc arcs_9_6[2] = { {32, 7}, {0, 6}, }; -static arc arcs_9_7[2] = { +static arc arcs_9_7[3] = { {30, 12}, {34, 3}, -}; -static arc arcs_9_8[1] = {
+}; +static arc arcs_9_8[2] = {
- {32, 13}, {0, 8}, }; static arc arcs_9_9[2] = { @@ -221,35 +223,39 @@ static arc arcs_9_10[3] = { {0, 10}, }; static arc arcs_9_11[3] = {
+static arc arcs_9_13[1] = { {0, 13}, }; static arc arcs_9_14[2] = {
+}; +static arc arcs_9_15[3] = {
+}; +static arc arcs_9_16[1] = { {26, 6}, }; -static arc arcs_9_16[3] = {
-}; -static arc arcs_9_17[1] = {
-}; -static state states_9[18] = { +static arc arcs_9_17[3] = {
+}; +static arc arcs_9_18[1] = {
+}; +static state states_9[19] = { {3, arcs_9_0}, {3, arcs_9_1}, {3, arcs_9_2}, @@ -257,17 +263,18 @@ static state states_9[18] = { {1, arcs_9_4}, {4, arcs_9_5}, {2, arcs_9_6},
}; static arc arcs_10_0[1] = { {23, 1}, @@ -319,11 +326,13 @@ static arc arcs_11_6[2] = { {32, 7}, {0, 6}, }; -static arc arcs_11_7[2] = { +static arc arcs_11_7[3] = { {36, 12}, {34, 3}, -}; -static arc arcs_11_8[1] = {
+}; +static arc arcs_11_8[2] = {
- {32, 13}, {0, 8}, }; static arc arcs_11_9[2] = { @@ -336,35 +345,39 @@ static arc arcs_11_10[3] = { {0, 10}, }; static arc arcs_11_11[3] = {
+static arc arcs_11_13[1] = { {0, 13}, }; static arc arcs_11_14[2] = {
+}; +static arc arcs_11_15[3] = {
+}; +static arc arcs_11_16[1] = { {26, 6}, }; -static arc arcs_11_16[3] = {
-}; -static arc arcs_11_17[1] = {
-}; -static state states_11[18] = { +static arc arcs_11_17[3] = {
+}; +static arc arcs_11_18[1] = {
+}; +static state states_11[19] = { {3, arcs_11_0}, {3, arcs_11_1}, {3, arcs_11_2}, @@ -372,17 +385,18 @@ static state states_11[18] = { {1, arcs_11_4}, {4, arcs_11_5}, {2, arcs_11_6},
}; static arc arcs_12_0[1] = { {23, 1}, @@ -1879,11 +1893,11 @@ static dfa dfas[85] = { "\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {264, "parameters", 0, 4, states_8, "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},