Patch #1686487: you can now pass any mapping after '**' in function calls.
This commit is contained in:
parent
70f996be24
commit
2134e754f2
|
@ -704,7 +704,7 @@ It is unusual for both keyword arguments and the
|
||||||
this confusion does not arise.
|
this confusion does not arise.
|
||||||
|
|
||||||
If the syntax \samp{**expression} appears in the function call,
|
If the syntax \samp{**expression} appears in the function call,
|
||||||
\samp{expression} must evaluate to a (subclass of) dictionary, the
|
\samp{expression} must evaluate to a mapping, the
|
||||||
contents of which are treated as additional keyword arguments. In the
|
contents of which are treated as additional keyword arguments. In the
|
||||||
case of a keyword appearing in both \samp{expression} and as an
|
case of a keyword appearing in both \samp{expression} and as an
|
||||||
explicit keyword argument, a \exception{TypeError} exception is
|
explicit keyword argument, a \exception{TypeError} exception is
|
||||||
|
|
|
@ -9,6 +9,9 @@ test_extcall
|
||||||
(1, 2, 3) {'a': 4, 'b': 5}
|
(1, 2, 3) {'a': 4, 'b': 5}
|
||||||
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
||||||
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
||||||
|
(1, 2, 3) {'a': 4, 'b': 5}
|
||||||
|
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
||||||
|
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
||||||
TypeError: g() takes at least 1 argument (0 given)
|
TypeError: g() takes at least 1 argument (0 given)
|
||||||
TypeError: g() takes at least 1 argument (0 given)
|
TypeError: g() takes at least 1 argument (0 given)
|
||||||
TypeError: g() takes at least 1 argument (0 given)
|
TypeError: g() takes at least 1 argument (0 given)
|
||||||
|
@ -25,12 +28,12 @@ g() got multiple values for keyword argument 'x'
|
||||||
g() got multiple values for keyword argument 'b'
|
g() got multiple values for keyword argument 'b'
|
||||||
f() keywords must be strings
|
f() keywords must be strings
|
||||||
h() got an unexpected keyword argument 'e'
|
h() got an unexpected keyword argument 'e'
|
||||||
h() argument after * must be a sequence
|
h() argument after * must be a sequence, not function
|
||||||
dir() argument after * must be a sequence
|
dir() argument after * must be a sequence, not function
|
||||||
NoneType object argument after * must be a sequence
|
NoneType object argument after * must be a sequence, not function
|
||||||
h() argument after ** must be a dictionary
|
h() argument after ** must be a mapping, not function
|
||||||
dir() argument after ** must be a dictionary
|
dir() argument after ** must be a mapping, not function
|
||||||
NoneType object argument after ** must be a dictionary
|
NoneType object argument after ** must be a mapping, not function
|
||||||
dir() got multiple values for keyword argument 'b'
|
dir() got multiple values for keyword argument 'b'
|
||||||
3 512 True
|
3 512 True
|
||||||
3
|
3
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from test.test_support import verify, verbose, TestFailed, sortdict
|
from test.test_support import verify, verbose, TestFailed, sortdict
|
||||||
from UserList import UserList
|
from UserList import UserList
|
||||||
|
from UserDict import UserDict
|
||||||
|
|
||||||
def e(a, b):
|
def e(a, b):
|
||||||
print a, b
|
print a, b
|
||||||
|
@ -25,6 +26,12 @@ f(1, 2, 3, **{'a':4, 'b':5})
|
||||||
f(1, 2, 3, *(4, 5), **{'a':6, 'b':7})
|
f(1, 2, 3, *(4, 5), **{'a':6, 'b':7})
|
||||||
f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b':9})
|
f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b':9})
|
||||||
|
|
||||||
|
|
||||||
|
f(1, 2, 3, **UserDict(a=4, b=5))
|
||||||
|
f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
|
||||||
|
f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
|
||||||
|
|
||||||
|
|
||||||
# Verify clearing of SF bug #733667
|
# Verify clearing of SF bug #733667
|
||||||
try:
|
try:
|
||||||
e(c=3)
|
e(c=3)
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Patch #1686487: you can now pass any mapping after '**' in function
|
||||||
|
calls.
|
||||||
|
|
||||||
- except clauses may now be spelled either "except E, target:" or
|
- except clauses may now be spelled either "except E, target:" or
|
||||||
"except E as target:". This is to provide forwards compatibility with
|
"except E as target:". This is to provide forwards compatibility with
|
||||||
Python 3.0.
|
Python 3.0.
|
||||||
|
|
|
@ -3790,13 +3790,31 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
|
||||||
|
|
||||||
if (flags & CALL_FLAG_KW) {
|
if (flags & CALL_FLAG_KW) {
|
||||||
kwdict = EXT_POP(*pp_stack);
|
kwdict = EXT_POP(*pp_stack);
|
||||||
if (!(kwdict && PyDict_Check(kwdict))) {
|
if (!PyDict_Check(kwdict)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyObject *d;
|
||||||
"%s%s argument after ** "
|
d = PyDict_New();
|
||||||
"must be a dictionary",
|
if (d == NULL)
|
||||||
PyEval_GetFuncName(func),
|
goto ext_call_fail;
|
||||||
PyEval_GetFuncDesc(func));
|
if (PyDict_Update(d, kwdict) != 0) {
|
||||||
goto ext_call_fail;
|
Py_DECREF(d);
|
||||||
|
/* PyDict_Update raises attribute
|
||||||
|
* error (percolated from an attempt
|
||||||
|
* to get 'keys' attribute) instead of
|
||||||
|
* a type error if its second argument
|
||||||
|
* is not a mapping.
|
||||||
|
*/
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%.200s%.200s argument after ** "
|
||||||
|
"must be a mapping, not %.200s",
|
||||||
|
PyEval_GetFuncName(func),
|
||||||
|
PyEval_GetFuncDesc(func),
|
||||||
|
kwdict->ob_type->tp_name);
|
||||||
|
}
|
||||||
|
goto ext_call_fail;
|
||||||
|
}
|
||||||
|
Py_DECREF(kwdict);
|
||||||
|
kwdict = d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags & CALL_FLAG_VAR) {
|
if (flags & CALL_FLAG_VAR) {
|
||||||
|
@ -3807,10 +3825,11 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%s%s argument after * "
|
"%.200s%.200s argument after * "
|
||||||
"must be a sequence",
|
"must be a sequence, not %200s",
|
||||||
PyEval_GetFuncName(func),
|
PyEval_GetFuncName(func),
|
||||||
PyEval_GetFuncDesc(func));
|
PyEval_GetFuncDesc(func),
|
||||||
|
stararg->ob_type->tp_name);
|
||||||
}
|
}
|
||||||
goto ext_call_fail;
|
goto ext_call_fail;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue