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 "<stdin>", line 1, in ?
TypeError: argument 2 impossible<bad format char>
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().
|