Issue #9232: Support trailing commas in function declarations.
For example, "def f(*, a = 3,): pass" is now legal. Patch from Mark Dickinson.
This commit is contained in:
parent
5b9cd7fa2e
commit
df395991f6
|
@ -471,10 +471,10 @@ A function definition defines a user-defined function object (see section
|
|||
decorators: `decorator`+
|
||||
decorator: "@" `dotted_name` ["(" [`parameter_list` [","]] ")"] NEWLINE
|
||||
dotted_name: `identifier` ("." `identifier`)*
|
||||
parameter_list: (`defparameter` ",")*
|
||||
: | "*" [`parameter`] ("," `defparameter`)* ["," "**" `parameter`]
|
||||
: | "**" `parameter`
|
||||
: | `defparameter` [","] )
|
||||
parameter_list: `defparameter` ("," `defparameter`)* ["," [`parameter_list_starargs`]]
|
||||
: | `parameter_list_starargs`
|
||||
parameter_list_starargs: "*" [`parameter`] ("," `defparameter`)* ["," ["**" `parameter` [","]]]
|
||||
: | "**" `parameter` [","]
|
||||
parameter: `identifier` [":" `expression`]
|
||||
defparameter: `parameter` ["=" `expression`]
|
||||
funcname: `identifier`
|
||||
|
|
|
@ -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]]
|
||||
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
|
||||
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
|
||||
'*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
|
||||
| '**' tfpdef [',']]]
|
||||
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
|
||||
| '**' tfpdef [','])
|
||||
tfpdef: NAME [':' test]
|
||||
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [','
|
||||
['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]]
|
||||
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef)
|
||||
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
|
||||
'*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']]]
|
||||
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']
|
||||
)
|
||||
vfpdef: NAME
|
||||
|
||||
stmt: simple_stmt | compound_stmt
|
||||
|
|
|
@ -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")
|
||||
self.assertRaises(SyntaxError, eval, "def f(*,): pass")
|
||||
self.assertRaises(SyntaxError, eval, "def f(*, **kwds): pass")
|
||||
|
||||
# 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
|
||||
def f(a,): pass
|
||||
def f(*args,): pass
|
||||
def f(**kwds,): pass
|
||||
def f(a, *args,): pass
|
||||
def f(a, **kwds,): pass
|
||||
def f(*args, b,): pass
|
||||
def f(*, b,): pass
|
||||
def f(*args, **kwds,): pass
|
||||
def f(a, *args, b,): pass
|
||||
def f(a, *, b,): pass
|
||||
def f(a, *args, **kwds,): pass
|
||||
def f(*args, b, **kwds,): pass
|
||||
def f(*, b, **kwds,): pass
|
||||
def f(a, *args, b, **kwds,): pass
|
||||
def f(a, *, b, **kwds,): pass
|
||||
|
||||
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
|
||||
l10 = lambda a,: 0
|
||||
l11 = lambda *args,: 0
|
||||
l12 = lambda **kwds,: 0
|
||||
l13 = lambda a, *args,: 0
|
||||
l14 = lambda a, **kwds,: 0
|
||||
l15 = lambda *args, b,: 0
|
||||
l16 = lambda *, b,: 0
|
||||
l17 = lambda *args, **kwds,: 0
|
||||
l18 = lambda a, *args, b,: 0
|
||||
l19 = lambda a, *, b,: 0
|
||||
l20 = lambda a, *args, **kwds,: 0
|
||||
l21 = lambda *args, b, **kwds,: 0
|
||||
l22 = lambda *, b, **kwds,: 0
|
||||
l23 = lambda a, *args, b, **kwds,: 0
|
||||
l24 = lambda a, *, b, **kwds,: 0
|
||||
|
||||
|
||||
### stmt: simple_stmt | compound_stmt
|
||||
# Tested below
|
||||
|
|
|
@ -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.
|
||||
|
||||
- Issue #24667: Resize odict in all cases that the underlying dict resizes.
|
||||
|
||||
Library
|
||||
|
|
23
Python/ast.c
23
Python/ast.c
|
@ -1260,16 +1260,20 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
and varargslist (lambda definition).
|
||||
|
||||
parameters: '(' [typedargslist] ')'
|
||||
typedargslist: ((tfpdef ['=' test] ',')*
|
||||
('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
|
||||
| '**' tfpdef)
|
||||
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
|
||||
'*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
|
||||
| '**' tfpdef [',']]]
|
||||
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
|
||||
| '**' tfpdef [','])
|
||||
tfpdef: NAME [':' test]
|
||||
varargslist: ((vfpdef ['=' test] ',')*
|
||||
('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
|
||||
| '**' vfpdef)
|
||||
| vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
|
||||
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
|
||||
'*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']]]
|
||||
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']
|
||||
)
|
||||
vfpdef: NAME
|
||||
|
||||
*/
|
||||
int i, j, k, nposargs = 0, nkwonlyargs = 0;
|
||||
int nposdefaults = 0, found_default = 0;
|
||||
|
@ -1371,7 +1375,8 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
i += 2; /* the name and the comma */
|
||||
break;
|
||||
case STAR:
|
||||
if (i+1 >= NCH(n)) {
|
||||
if (i+1 >= NCH(n) ||
|
||||
(i+2 == NCH(n) && TYPE(CHILD(n, i+1)) == COMMA)) {
|
||||
ast_error(c, CHILD(n, i),
|
||||
"named arguments must follow bare *");
|
||||
return NULL;
|
||||
|
|
|
@ -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},
|
||||
{0, 7},
|
||||
};
|
||||
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] = {
|
||||
{30, 13},
|
||||
{32, 14},
|
||||
{30, 14},
|
||||
{32, 15},
|
||||
{0, 11},
|
||||
};
|
||||
static arc arcs_9_12[3] = {
|
||||
{32, 7},
|
||||
{31, 15},
|
||||
{31, 16},
|
||||
{0, 12},
|
||||
};
|
||||
static arc arcs_9_13[2] = {
|
||||
{32, 14},
|
||||
static arc arcs_9_13[1] = {
|
||||
{0, 13},
|
||||
};
|
||||
static arc arcs_9_14[2] = {
|
||||
{30, 16},
|
||||
{34, 3},
|
||||
{32, 15},
|
||||
{0, 14},
|
||||
};
|
||||
static arc arcs_9_15[1] = {
|
||||
static arc arcs_9_15[3] = {
|
||||
{30, 17},
|
||||
{34, 3},
|
||||
{0, 15},
|
||||
};
|
||||
static arc arcs_9_16[1] = {
|
||||
{26, 6},
|
||||
};
|
||||
static arc arcs_9_16[3] = {
|
||||
{32, 14},
|
||||
{31, 17},
|
||||
{0, 16},
|
||||
static arc arcs_9_17[3] = {
|
||||
{32, 15},
|
||||
{31, 18},
|
||||
{0, 17},
|
||||
};
|
||||
static arc arcs_9_17[1] = {
|
||||
{26, 13},
|
||||
static arc arcs_9_18[1] = {
|
||||
{26, 14},
|
||||
};
|
||||
static state states_9[18] = {
|
||||
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},
|
||||
{2, arcs_9_7},
|
||||
{1, arcs_9_8},
|
||||
{3, arcs_9_7},
|
||||
{2, arcs_9_8},
|
||||
{2, arcs_9_9},
|
||||
{3, arcs_9_10},
|
||||
{3, arcs_9_11},
|
||||
{3, arcs_9_12},
|
||||
{2, arcs_9_13},
|
||||
{1, arcs_9_13},
|
||||
{2, arcs_9_14},
|
||||
{1, arcs_9_15},
|
||||
{3, arcs_9_16},
|
||||
{1, arcs_9_17},
|
||||
{3, arcs_9_15},
|
||||
{1, arcs_9_16},
|
||||
{3, arcs_9_17},
|
||||
{1, arcs_9_18},
|
||||
};
|
||||
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},
|
||||
{0, 7},
|
||||
};
|
||||
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] = {
|
||||
{36, 13},
|
||||
{32, 14},
|
||||
{36, 14},
|
||||
{32, 15},
|
||||
{0, 11},
|
||||
};
|
||||
static arc arcs_11_12[3] = {
|
||||
{32, 7},
|
||||
{31, 15},
|
||||
{31, 16},
|
||||
{0, 12},
|
||||
};
|
||||
static arc arcs_11_13[2] = {
|
||||
{32, 14},
|
||||
static arc arcs_11_13[1] = {
|
||||
{0, 13},
|
||||
};
|
||||
static arc arcs_11_14[2] = {
|
||||
{36, 16},
|
||||
{34, 3},
|
||||
{32, 15},
|
||||
{0, 14},
|
||||
};
|
||||
static arc arcs_11_15[1] = {
|
||||
static arc arcs_11_15[3] = {
|
||||
{36, 17},
|
||||
{34, 3},
|
||||
{0, 15},
|
||||
};
|
||||
static arc arcs_11_16[1] = {
|
||||
{26, 6},
|
||||
};
|
||||
static arc arcs_11_16[3] = {
|
||||
{32, 14},
|
||||
{31, 17},
|
||||
{0, 16},
|
||||
static arc arcs_11_17[3] = {
|
||||
{32, 15},
|
||||
{31, 18},
|
||||
{0, 17},
|
||||
};
|
||||
static arc arcs_11_17[1] = {
|
||||
{26, 13},
|
||||
static arc arcs_11_18[1] = {
|
||||
{26, 14},
|
||||
};
|
||||
static state states_11[18] = {
|
||||
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},
|
||||
{2, arcs_11_7},
|
||||
{1, arcs_11_8},
|
||||
{3, arcs_11_7},
|
||||
{2, arcs_11_8},
|
||||
{2, arcs_11_9},
|
||||
{3, arcs_11_10},
|
||||
{3, arcs_11_11},
|
||||
{3, arcs_11_12},
|
||||
{2, arcs_11_13},
|
||||
{1, arcs_11_13},
|
||||
{2, arcs_11_14},
|
||||
{1, arcs_11_15},
|
||||
{3, arcs_11_16},
|
||||
{1, arcs_11_17},
|
||||
{3, arcs_11_15},
|
||||
{1, arcs_11_16},
|
||||
{3, arcs_11_17},
|
||||
{1, arcs_11_18},
|
||||
};
|
||||
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"},
|
||||
{265, "typedargslist", 0, 18, states_9,
|
||||
{265, "typedargslist", 0, 19, states_9,
|
||||
"\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||
{266, "tfpdef", 0, 4, states_10,
|
||||
"\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||
{267, "varargslist", 0, 18, states_11,
|
||||
{267, "varargslist", 0, 19, states_11,
|
||||
"\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||
{268, "vfpdef", 0, 2, states_12,
|
||||
"\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||
|
|
Loading…
Reference in New Issue