diff --git a/Lib/test/test_b1.py b/Lib/test/test_b1.py index 6d6aa6fcf18..95110790f0a 100644 --- a/Lib/test/test_b1.py +++ b/Lib/test/test_b1.py @@ -39,6 +39,17 @@ def f3(a1, a2, a3): apply(f2, (1, 2)) apply(f3, (1, 2, 3)) +# A PyCFunction that takes only positional parameters should allow an +# empty keyword dictionary to pass without a complaint, but raise a +# TypeError if the dictionary is non-empty. +apply(id, (1,), {}) +try: + apply(id, (1,), {"foo": 1}) +except TypeError: + pass +else: + raise TestFailed, 'expected TypeError; no exception raised' + print 'callable' if not callable(len):raise TestFailed, 'callable(len)' def f(): pass diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index 7dddabca65c..cc42818c9a6 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -1,4 +1,5 @@ from UserList import UserList +from test_support import TestFailed def f(*a, **k): print a, k @@ -161,4 +162,13 @@ def method(self, arg1, arg2): except TypeError, err: print err - +# A PyCFunction that takes only positional parameters should allow an +# empty keyword dictionary to pass without a complaint, but raise a +# TypeError if the dictionary is non-empty. +id(1, **{}) +try: + id(1, **{"foo": 1}) +except TypeError: + pass +else: + raise TestFailed, 'expected TypeError; no exception raised' diff --git a/Python/ceval.c b/Python/ceval.c index dd626e5f88d..1559456e6bf 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2607,36 +2607,37 @@ call_cfunction(PyObject *func, PyObject *arg, PyObject *kw) PyObject *self = PyCFunction_GET_SELF(func); int flags = PyCFunction_GET_FLAGS(func); - if (flags & METH_KEYWORDS && kw == NULL) { - static PyObject *dict = NULL; - if (dict == NULL) { - dict = PyDict_New(); - if (dict == NULL) - return NULL; - } - kw = dict; - Py_INCREF(dict); - } - if (flags & METH_VARARGS && kw == NULL) { - return (*meth)(self, arg); - } if (flags & METH_KEYWORDS) { + if (kw == NULL) { + static PyObject *dict = NULL; + if (dict == NULL) { + dict = PyDict_New(); + if (dict == NULL) + return NULL; + } + kw = dict; + Py_INCREF(dict); + } return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); } - if (!(flags & METH_VARARGS)) { - int size = PyTuple_GET_SIZE(arg); - if (size == 1) - arg = PyTuple_GET_ITEM(arg, 0); - else if (size == 0) - arg = NULL; - return (*meth)(self, arg); - } if (kw != NULL && PyDict_Size(kw) != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; } + if (flags & METH_VARARGS) { + return (*meth)(self, arg); + } + if (!(flags & METH_VARARGS)) { + /* the really old style */ + int size = PyTuple_GET_SIZE(arg); + if (size == 1) + arg = PyTuple_GET_ITEM(arg, 0); + else if (size == 0) + arg = NULL; + return (*meth)(self, arg); + } /* should never get here ??? */ PyErr_BadInternalCall(); return NULL;