Issue 985713: bug skipping optional keyword arguments of type "w#" (original) (raw)
When using PyArg_ParseTupleAndKeywords(), if you use "w#" as an optional keyword argument, you cannot skip it and still specify an optional argument that follows it. For example, take the following function:
static PyObject * dummy_func(PyObject *self, PyObject *args, PyObject *kwds) { char *string; char *buf = NULL; int bufsize = 0; unsigned short ushort = 5; static char *kwlist[] = { "string", "buffer", "ushort", NULL };
if (! PyArg_ParseTupleAndKeywords(args, kwds,
"s|w#H", kwlist, &string, &buf, &bufsize, &ushort)) return NULL;
printf("buf=%p, bufsize=%d, ushort=%hu\n", buf,
bufsize, ushort); snprintf(buf, bufsize, "you said "%s"\n", hostname);
return Py_BuildValue("s", hostname);
}
You can call this function successfully as follows:
don't specify buffer or ushort
dummy_func("text")
Or like this:
specify buffer
buf = array.array('c', [' ' for x in range(0, 1023)]) dummy_func("text", buffer=buf)
Or like this:
specify buffer and ushort
buf = array.array('c', [' ' for x in range(0, 1023)]) dummy_func("text", buffer=buf, ushort=10)
However, the following does NOT work:
specify ushort without first specifying buffer
dummy_func("text", ushort=10)
It fails with the following error:
Traceback (most recent call last): File "", line 1, in ? TypeError: argument 2 impossible
This is because the skipitem() function in Python/getargs.c does not know how to skip arguments for the "w#" format unit. I've attached a patch that fixes this.
Note that skipitem() is also missing code for many other legal format units, in addition to "w" and "w#". In particular:
u, u# (see patch #853890) es, es# et, et# I (capital i) k K D S U t# (tuple)
It might be a good idea to refactor the code so that if/when new format units are added, the same code will handle them for both skipitem() and convertsimple().