benjamin.peterson
2008-08-19 20:57:11 UTC
Author: benjamin.peterson
Date: Tue Aug 19 22:57:10 2008
New Revision: 65877
Log:
allow keyword args after *args in a function call
Modified:
python/branches/py3k/Doc/reference/expressions.rst
python/branches/py3k/Grammar/Grammar
python/branches/py3k/Lib/test/test_grammar.py
python/branches/py3k/Lib/test/test_keywordonlyarg.py
python/branches/py3k/Python/ast.c
python/branches/py3k/Python/graminit.c
Modified: python/branches/py3k/Doc/reference/expressions.rst
==============================================================================
--- python/branches/py3k/Doc/reference/expressions.rst (original)
+++ python/branches/py3k/Doc/reference/expressions.rst Tue Aug 19 22:57:10 2008
@@ -612,11 +612,11 @@
call: `primary` "(" [`argument_list` [","]
: | `expression` `genexpr_for`] ")"
argument_list: `positional_arguments` ["," `keyword_arguments`]
- : ["," "*" `expression`]
- : ["," "**" `expression`]
+ : ["," "*" `expression`] ["," `keyword_arguments`]
+ : ["," "**" `expression`]
: | `keyword_arguments` ["," "*" `expression`]
- : ["," "**" `expression`]
- : | "*" `expression` ["," "**" `expression`]
+ : ["," `keyword_arguments`] ["," "**" `expression`]
+ : | "*" `expression` ["," `keyword_arguments`] ["," "**" `expression`]
: | "**" `expression`
positional_arguments: `expression` ("," `expression`)*
keyword_arguments: `keyword_item` ("," `keyword_item`)*
@@ -674,12 +674,13 @@
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
-additional positional arguments; if there are positional arguments *x1*,...,*xN*
-, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent
-to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*.
+additional positional arguments; if there are positional arguments *x1*,...,
+*xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, this is
+equivalent to a call with M+N positional arguments *x1*, ..., *xN*, *y1*, ...,
+*yM*.
-A consequence of this is that although the ``*expression`` syntax appears
-*after* any keyword arguments, it is processed *before* the keyword arguments
+A consequence of this is that although the ``*expression`` syntax may appear
+*after* some keyword arguments, it is processed *before* the keyword arguments
Modified: python/branches/py3k/Grammar/Grammar
==============================================================================
--- python/branches/py3k/Grammar/Grammar (original)
+++ python/branches/py3k/Grammar/Grammar Tue Aug 19 22:57:10 2008
@@ -113,7 +113,9 @@
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
comp_iter: comp_for | comp_if
Modified: python/branches/py3k/Lib/test/test_grammar.py
==============================================================================
--- python/branches/py3k/Lib/test/test_grammar.py (original)
+++ python/branches/py3k/Lib/test/test_grammar.py Tue Aug 19 22:57:10 2008
@@ -284,6 +284,14 @@
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
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
def f(x) -> list: pass
self.assertEquals(f.__annotations__, {'return': list})
Modified: python/branches/py3k/Lib/test/test_keywordonlyarg.py
==============================================================================
--- python/branches/py3k/Lib/test/test_keywordonlyarg.py (original)
+++ python/branches/py3k/Lib/test/test_keywordonlyarg.py Tue Aug 19 22:57:10 2008
@@ -75,7 +75,7 @@
def testSyntaxErrorForFunctionCall(self):
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):
self.assertRaises(TypeError, keywordonly_sum, ())
Modified: python/branches/py3k/Python/ast.c
==============================================================================
--- python/branches/py3k/Python/ast.c (original)
+++ python/branches/py3k/Python/ast.c Tue Aug 19 22:57:10 2008
@@ -1961,6 +1961,11 @@
"non-keyword arg after keyword arg");
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));
if (!e)
return NULL;
Modified: python/branches/py3k/Python/graminit.c
==============================================================================
--- python/branches/py3k/Python/graminit.c (original)
+++ python/branches/py3k/Python/graminit.c Tue Aug 19 22:57:10 2008
@@ -1598,7 +1598,8 @@
static arc arcs_73_6[1] = {
{0, 6},
};
-static arc arcs_73_7[1] = {
+static arc arcs_73_7[2] = {
+ {161, 5},
{32, 3},
};
static state states_73[8] = {
@@ -1609,7 +1610,7 @@
{4, arcs_73_4},
{2, arcs_73_5},
{1, arcs_73_6},
- {1, arcs_73_7},
+ {2, arcs_73_7},
};
static arc arcs_74_0[1] = {
{24, 1},
Date: Tue Aug 19 22:57:10 2008
New Revision: 65877
Log:
allow keyword args after *args in a function call
Modified:
python/branches/py3k/Doc/reference/expressions.rst
python/branches/py3k/Grammar/Grammar
python/branches/py3k/Lib/test/test_grammar.py
python/branches/py3k/Lib/test/test_keywordonlyarg.py
python/branches/py3k/Python/ast.c
python/branches/py3k/Python/graminit.c
Modified: python/branches/py3k/Doc/reference/expressions.rst
==============================================================================
--- python/branches/py3k/Doc/reference/expressions.rst (original)
+++ python/branches/py3k/Doc/reference/expressions.rst Tue Aug 19 22:57:10 2008
@@ -612,11 +612,11 @@
call: `primary` "(" [`argument_list` [","]
: | `expression` `genexpr_for`] ")"
argument_list: `positional_arguments` ["," `keyword_arguments`]
- : ["," "*" `expression`]
- : ["," "**" `expression`]
+ : ["," "*" `expression`] ["," `keyword_arguments`]
+ : ["," "**" `expression`]
: | `keyword_arguments` ["," "*" `expression`]
- : ["," "**" `expression`]
- : | "*" `expression` ["," "**" `expression`]
+ : ["," `keyword_arguments`] ["," "**" `expression`]
+ : | "*" `expression` ["," `keyword_arguments`] ["," "**" `expression`]
: | "**" `expression`
positional_arguments: `expression` ("," `expression`)*
keyword_arguments: `keyword_item` ("," `keyword_item`)*
@@ -674,12 +674,13 @@
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
-additional positional arguments; if there are positional arguments *x1*,...,*xN*
-, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent
-to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*.
+additional positional arguments; if there are positional arguments *x1*,...,
+*xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, this is
+equivalent to a call with M+N positional arguments *x1*, ..., *xN*, *y1*, ...,
+*yM*.
-A consequence of this is that although the ``*expression`` syntax appears
-*after* any keyword arguments, it is processed *before* the keyword arguments
+A consequence of this is that although the ``*expression`` syntax may appear
+*after* some keyword arguments, it is processed *before* the keyword arguments
Modified: python/branches/py3k/Grammar/Grammar
==============================================================================
--- python/branches/py3k/Grammar/Grammar (original)
+++ python/branches/py3k/Grammar/Grammar Tue Aug 19 22:57:10 2008
@@ -113,7 +113,9 @@
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
comp_iter: comp_for | comp_if
Modified: python/branches/py3k/Lib/test/test_grammar.py
==============================================================================
--- python/branches/py3k/Lib/test/test_grammar.py (original)
+++ python/branches/py3k/Lib/test/test_grammar.py Tue Aug 19 22:57:10 2008
@@ -284,6 +284,14 @@
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
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
def f(x) -> list: pass
self.assertEquals(f.__annotations__, {'return': list})
Modified: python/branches/py3k/Lib/test/test_keywordonlyarg.py
==============================================================================
--- python/branches/py3k/Lib/test/test_keywordonlyarg.py (original)
+++ python/branches/py3k/Lib/test/test_keywordonlyarg.py Tue Aug 19 22:57:10 2008
@@ -75,7 +75,7 @@
def testSyntaxErrorForFunctionCall(self):
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):
self.assertRaises(TypeError, keywordonly_sum, ())
Modified: python/branches/py3k/Python/ast.c
==============================================================================
--- python/branches/py3k/Python/ast.c (original)
+++ python/branches/py3k/Python/ast.c Tue Aug 19 22:57:10 2008
@@ -1961,6 +1961,11 @@
"non-keyword arg after keyword arg");
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));
if (!e)
return NULL;
Modified: python/branches/py3k/Python/graminit.c
==============================================================================
--- python/branches/py3k/Python/graminit.c (original)
+++ python/branches/py3k/Python/graminit.c Tue Aug 19 22:57:10 2008
@@ -1598,7 +1598,8 @@
static arc arcs_73_6[1] = {
{0, 6},
};
-static arc arcs_73_7[1] = {
+static arc arcs_73_7[2] = {
+ {161, 5},
{32, 3},
};
static state states_73[8] = {
@@ -1609,7 +1610,7 @@
{4, arcs_73_4},
{2, arcs_73_5},
{1, arcs_73_6},
- {1, arcs_73_7},
+ {2, arcs_73_7},
};
static arc arcs_74_0[1] = {
{24, 1},