allow keyword args after *args in a function call
This commit is contained in:
parent
de0de885f7
commit
2d735bc098
|
@ -612,11 +612,11 @@ of arguments:
|
||||||
call: `primary` "(" [`argument_list` [","]
|
call: `primary` "(" [`argument_list` [","]
|
||||||
: | `expression` `genexpr_for`] ")"
|
: | `expression` `genexpr_for`] ")"
|
||||||
argument_list: `positional_arguments` ["," `keyword_arguments`]
|
argument_list: `positional_arguments` ["," `keyword_arguments`]
|
||||||
: ["," "*" `expression`]
|
: ["," "*" `expression`] ["," `keyword_arguments`]
|
||||||
: ["," "**" `expression`]
|
: ["," "**" `expression`]
|
||||||
: | `keyword_arguments` ["," "*" `expression`]
|
: | `keyword_arguments` ["," "*" `expression`]
|
||||||
: ["," "**" `expression`]
|
: ["," `keyword_arguments`] ["," "**" `expression`]
|
||||||
: | "*" `expression` ["," "**" `expression`]
|
: | "*" `expression` ["," `keyword_arguments`] ["," "**" `expression`]
|
||||||
: | "**" `expression`
|
: | "**" `expression`
|
||||||
positional_arguments: `expression` ("," `expression`)*
|
positional_arguments: `expression` ("," `expression`)*
|
||||||
keyword_arguments: `keyword_item` ("," `keyword_item`)*
|
keyword_arguments: `keyword_item` ("," `keyword_item`)*
|
||||||
|
@ -674,12 +674,13 @@ there were no excess keyword arguments.
|
||||||
|
|
||||||
If the syntax ``*expression`` appears in the function call, ``expression`` must
|
If the syntax ``*expression`` appears in the function call, ``expression`` must
|
||||||
evaluate to a sequence. Elements from this sequence are treated as if they were
|
evaluate to a sequence. Elements from this sequence are treated as if they were
|
||||||
additional positional arguments; if there are positional arguments *x1*,...,*xN*
|
additional positional arguments; if there are positional arguments *x1*,...,
|
||||||
, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent
|
*xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, this is
|
||||||
to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*.
|
equivalent to a call with M+N positional arguments *x1*, ..., *xN*, *y1*, ...,
|
||||||
|
*yM*.
|
||||||
|
|
||||||
A consequence of this is that although the ``*expression`` syntax appears
|
A consequence of this is that although the ``*expression`` syntax may appear
|
||||||
*after* any keyword arguments, it is processed *before* the keyword arguments
|
*after* some keyword arguments, it is processed *before* the keyword arguments
|
||||||
(and the ``**expression`` argument, if any -- see below). So::
|
(and the ``**expression`` argument, if any -- see below). So::
|
||||||
|
|
||||||
>>> def f(a, b):
|
>>> def f(a, b):
|
||||||
|
|
|
@ -113,7 +113,9 @@ dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
|
||||||
|
|
||||||
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
||||||
|
|
||||||
arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
|
arglist: (argument ',')* (argument [',']
|
||||||
|
|'*' test (',' argument)* [',' '**' test]
|
||||||
|
|'**' test)
|
||||||
argument: test [comp_for] | test '=' test # Really [keyword '='] test
|
argument: test [comp_for] | test '=' test # Really [keyword '='] test
|
||||||
|
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: comp_for | comp_if
|
||||||
|
|
|
@ -284,6 +284,14 @@ class GrammarTests(unittest.TestCase):
|
||||||
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
|
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
|
||||||
pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
|
pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
|
||||||
|
|
||||||
|
# keyword arguments after *arglist
|
||||||
|
def f(*args, **kwargs):
|
||||||
|
return args, kwargs
|
||||||
|
self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4),
|
||||||
|
{'x':2, 'y':5}))
|
||||||
|
self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)")
|
||||||
|
self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)")
|
||||||
|
|
||||||
# argument annotation tests
|
# argument annotation tests
|
||||||
def f(x) -> list: pass
|
def f(x) -> list: pass
|
||||||
self.assertEquals(f.__annotations__, {'return': list})
|
self.assertEquals(f.__annotations__, {'return': list})
|
||||||
|
|
|
@ -75,7 +75,7 @@ class KeywordOnlyArgTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def testSyntaxErrorForFunctionCall(self):
|
def testSyntaxErrorForFunctionCall(self):
|
||||||
self.assertRaisesSyntaxError("f(p, k=1, p2)")
|
self.assertRaisesSyntaxError("f(p, k=1, p2)")
|
||||||
self.assertRaisesSyntaxError("f(p, *(1,2), k1=100)")
|
self.assertRaisesSyntaxError("f(p, k1=50, *(1,2), k1=100)")
|
||||||
|
|
||||||
def testRaiseErrorFuncallWithUnexpectedKeywordArgument(self):
|
def testRaiseErrorFuncallWithUnexpectedKeywordArgument(self):
|
||||||
self.assertRaises(TypeError, keywordonly_sum, ())
|
self.assertRaises(TypeError, keywordonly_sum, ())
|
||||||
|
|
|
@ -1961,6 +1961,11 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
|
||||||
"non-keyword arg after keyword arg");
|
"non-keyword arg after keyword arg");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (vararg) {
|
||||||
|
ast_error(CHILD(ch, 0),
|
||||||
|
"only named arguments may follow *expression");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
e = ast_for_expr(c, CHILD(ch, 0));
|
e = ast_for_expr(c, CHILD(ch, 0));
|
||||||
if (!e)
|
if (!e)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -1598,7 +1598,8 @@ static arc arcs_73_5[2] = {
|
||||||
static arc arcs_73_6[1] = {
|
static arc arcs_73_6[1] = {
|
||||||
{0, 6},
|
{0, 6},
|
||||||
};
|
};
|
||||||
static arc arcs_73_7[1] = {
|
static arc arcs_73_7[2] = {
|
||||||
|
{161, 5},
|
||||||
{32, 3},
|
{32, 3},
|
||||||
};
|
};
|
||||||
static state states_73[8] = {
|
static state states_73[8] = {
|
||||||
|
@ -1609,7 +1610,7 @@ static state states_73[8] = {
|
||||||
{4, arcs_73_4},
|
{4, arcs_73_4},
|
||||||
{2, arcs_73_5},
|
{2, arcs_73_5},
|
||||||
{1, arcs_73_6},
|
{1, arcs_73_6},
|
||||||
{1, arcs_73_7},
|
{2, arcs_73_7},
|
||||||
};
|
};
|
||||||
static arc arcs_74_0[1] = {
|
static arc arcs_74_0[1] = {
|
||||||
{24, 1},
|
{24, 1},
|
||||||
|
|
Loading…
Reference in New Issue