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().