On 5/9/19 10:08 AM, Jeroen Demeyer wrote:
Dear C API lovers,
I have a question about the usual args/kwargs call protocol (as used by PyObject_Call and tp_call): is the "args" tuple supposed to be of type exactly tuple or are tuple subclasses allowed? Same question for "kwargs" and dict.
The documentation is not clear about this.
I do know that calls from Python are done with an exact tuple and exact dict, but in C this is not so clear. For example, the implementation of _PyErr_CreateException uses PyTuple_Check(), not PyTuple_CheckExact():
static PyObject* _PyErr_CreateException(PyObject *exception, PyObject *value) { if (value == NULL || value == Py_None) { return _PyObject_CallNoArg(exception); } else if (PyTuple_Check(value)) { return PyObject_Call(exception, value, NULL); } else { return PyObject_CallFunctionObjArgs(exception, value, NULL); } }
Also, the implementation of the call protocol has assertions of both forms: you see both assert(PyTuple_Check(args)) and assert(PyTuple_CheckExact(args)) and similar for dict. It seems pretty random whether or not an exact type check is done.
I'm pretty sure that there are code paths that would result in an assertion failure because of this.
So basically my question is: what is the right behavior? Given the implementation of the Python bytecode interpreter, I would be inclined to say that type checks should be exact.
I don't see the reason for them to be exact. The reason we need tuples/dicts (and not any sequence/mapping) is we access the structs directly, but that will work with subtypes.
If we one day decide clean this up, converting from *_CheckExact() to *_Check() will not break previously working code.