Kaydet (Commit) 1a7aab70 authored tarafından Fred Drake's avatar Fred Drake

When a PyCFunction that takes only positional parameters is called with

an empty keywords dictionary (via apply() or the extended call syntax),
the keywords dict should be ignored.  If the keywords dict is not empty,
TypeError should be raised.  (Between the restructuring of the call
machinery and this patch, an empty dict in this situation would trigger
a SystemError via PyErr_BadInternalCall().)

Added regression tests to detect errors for this.
üst be4c0f56
......@@ -39,6 +39,17 @@ apply(f1, (1,))
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
......
from UserList import UserList
from test_support import TestFailed
def f(*a, **k):
print a, k
......@@ -161,4 +162,13 @@ try:
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'
......@@ -2607,7 +2607,8 @@ 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) {
if (flags & METH_KEYWORDS) {
if (kw == NULL) {
static PyObject *dict = NULL;
if (dict == NULL) {
dict = PyDict_New();
......@@ -2617,13 +2618,19 @@ call_cfunction(PyObject *func, PyObject *arg, PyObject *kw)
kw = dict;
Py_INCREF(dict);
}
if (flags & METH_VARARGS && kw == NULL) {
return (*meth)(self, arg);
}
if (flags & METH_KEYWORDS) {
return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
}
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);
......@@ -2631,12 +2638,6 @@ call_cfunction(PyObject *func, PyObject *arg, PyObject *kw)
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;
}
/* should never get here ??? */
PyErr_BadInternalCall();
return NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment