Message294912
Example with a builtin function, abs(), which uses METH_O.
Before:
haypo@selma$ python3
Python 3.5.3 (default, Apr 24 2017, 13:32:13)
>>> abs(x=5)
TypeError: abs() takes no keyword arguments
After:
haypo@selma$ ./python
Python 3.7.0a0 (heads/master:85aba23, May 31 2017, 10:29:03)
>>> abs(x=5)
TypeError: abs() takes exactly one argument (0 given)
In Python 3.5, PyCFunction_Call() starts by checking keyword arguments:
if (flags == (METH_VARARGS | METH_KEYWORDS)) {
...
}
else {
if (kwds != NULL && PyDict_Size(kwds) != 0) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
f->m_ml->ml_name);
return NULL;
}
switch (flags) {
case METH_NOARGS:
size = PyTuple_GET_SIZE(args);
if (size != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
f->m_ml->ml_name, size);
return NULL;
}
...
In Python 3.7, _PyMethodDef_RawFastCallKeywords() first check positional arguments:
switch (flags)
{
case METH_NOARGS:
if (nargs != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
goto exit;
}
if (nkwargs) {
goto no_keyword_error;
}
...
We can easily exchange the two checks, but IMHO we need an unit test (at least decorated by @cpython_only) to avoid regressions in the future. |
|
Date |
User |
Action |
Args |
2017-06-01 07:35:24 | vstinner | set | recipients:
+ vstinner, rhettinger, scoder, serhiy.storchaka |
2017-06-01 07:35:24 | vstinner | set | messageid: <1496302524.73.0.0444857123108.issue30534@psf.upfronthosting.co.za> |
2017-06-01 07:35:24 | vstinner | link | issue30534 messages |
2017-06-01 07:35:23 | vstinner | create | |
|