STINNER Victor added the comment:

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.

----------
nosy: +rhettinger

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue30534>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to