From: Joachim Dahl on
I am updating an extension module from Python2.6 to Python3.

I used to pass character codes to the extension module, for example, I
would write:
>>> foo('X')

with the corresponding C extension routine defined as follows:
static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
{
char foo;
char *kwlist[] = {"foo", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist, &foo))
return NULL;
...


In Python3.0 this also works, but in Python3.1 I get the following
error:
TypeError: argument 1 must be a byte string of length 1, not str

and I seem to be supposed to write
>>> foo(b'X')
instead. From the Python C API, I have not been able to explain this
new behavior.
What is the correct way to pass a single character argument to
Python3.1
extension modules?
From: Joachim Dahl on
Obviously the name of the C function and the char variable cannot both
be foo,
so the C code should be:

static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
{
char foochar;
char *kwlist[] = {"foochar", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist,
&foochar))
return NULL;
...


The question remains the same: why can't I pass a single character
argument to this function under Python3.1?

Thanks.
Joachim

On Nov 30, 9:52 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
> I am updating an extension module from Python2.6 to Python3.
>
> I used to pass character codes to the extension module, for example, I
> would write:
>
> >>> foo('X')
>
> with the corresponding C extension routine defined as follows:
> static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> {
>   char foo;
>   char *kwlist[] = {"foo", NULL};
>   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist, &foo))
>     return NULL;
>   ...
>
> In Python3.0 this also works, but in Python3.1 I get the following
> error:
> TypeError: argument 1 must be a byte string of length 1, not str
>
> and I seem to be supposed to write>>> foo(b'X')
>
> instead. From the Python C API, I have not been able to explain this
> new behavior.
> What is the correct way to pass a single character argument to
> Python3.1
> extension modules?

From: casevh on
On Nov 30, 1:04 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
> Obviously the name of the C function and the char variable cannot both
> be foo,
> so the C code should be:
>
> static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> {
>   char foochar;
>   char *kwlist[] = {"foochar", NULL};
>   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist,
> &foochar))
>     return NULL;
>   ...
>
> The question remains the same: why can't I pass a single character
> argument to this function under Python3.1?
>
> Thanks.
> Joachim
>
> On Nov 30, 9:52 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
>
>
>
> > I am updating an extension module from Python2.6 to Python3.
>
> > I used to pass character codes to the extension module, for example, I
> > would write:
>
> > >>> foo('X')
>
> > with the corresponding C extension routine defined as follows:
> > static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> > {
> >   char foo;
> >   char *kwlist[] = {"foo", NULL};
> >   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist, &foo))
> >     return NULL;
> >   ...
>
> > In Python3.0 this also works, but in Python3.1 I get the following
> > error:
> > TypeError: argument 1 must be a byte string of length 1, not str
>
> > and I seem to be supposed to write>>> foo(b'X')
>
> > instead. From the Python C API, I have not been able to explain this
> > new behavior.
> > What is the correct way to pass a single character argument to
> > Python3.1
> > extension modules?- Hide quoted text -
>
> - Show quoted text -

Python 3.1 uses "c" (lowercase c) to parse a single character from a
byte-string and uses "C" (uppercase c) to parse a single character
from a Unicode string. I don't think there is an easy way to accept a
character from both.

HTH,

casevh
From: Joachim Dahl on
I think that "C" encoding is what I need, however I run into an odd
problem.
If I use the following C code

static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
{
char a, b;
char *kwlist[] = {"a", "b", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwrds, "|CC", kwlist, &a,
&b))
return NULL;
...

then the following works:
>>> foo('a')
>>> foo('a','b')
>>> foo(a='a',b='b')

but the following fails:
>>> foo(b='b')
RuntimeError: impossible<bad format char>: 'CC'

Is this error-message expected?

On Nov 30, 10:19 pm, casevh <cas...(a)gmail.com> wrote:
> On Nov 30, 1:04 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
>
>
>
>
>
> > Obviously the name of the C function and the char variable cannot both
> > be foo,
> > so the C code should be:
>
> > static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> > {
> >   char foochar;
> >   char *kwlist[] = {"foochar", NULL};
> >   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist,
> > &foochar))
> >     return NULL;
> >   ...
>
> > The question remains the same: why can't I pass a single character
> > argument to this function under Python3.1?
>
> > Thanks.
> > Joachim
>
> > On Nov 30, 9:52 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
>
> > > I am updating an extension module from Python2.6 to Python3.
>
> > > I used to pass character codes to the extension module, for example, I
> > > would write:
>
> > > >>> foo('X')
>
> > > with the corresponding C extension routine defined as follows:
> > > static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> > > {
> > >   char foo;
> > >   char *kwlist[] = {"foo", NULL};
> > >   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist, &foo))
> > >     return NULL;
> > >   ...
>
> > > In Python3.0 this also works, but in Python3.1 I get the following
> > > error:
> > > TypeError: argument 1 must be a byte string of length 1, not str
>
> > > and I seem to be supposed to write>>> foo(b'X')
>
> > > instead. From the Python C API, I have not been able to explain this
> > > new behavior.
> > > What is the correct way to pass a single character argument to
> > > Python3.1
> > > extension modules?- Hide quoted text -
>
> > - Show quoted text -
>
> Python 3.1 uses "c" (lowercase c) to parse a single character from a
> byte-string and uses "C" (uppercase c) to parse a single character
> from a Unicode string. I don't think there is an easy way to accept a
> character from both.
>
> HTH,
>
> casevh

From: casevh on
On Nov 30, 2:18 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
> I think that "C" encoding is what I need, however I run into an odd
> problem.
> If I use the following C code
>
> static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> {
>   char a, b;
>   char *kwlist[] = {"a", "b", NULL};
>   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "|CC", kwlist, &a,
> &b))
>     return NULL;
>   ...
>
> then the following works:
>
> >>> foo('a')
> >>> foo('a','b')
> >>> foo(a='a',b='b')
>
> but the following fails:>>> foo(b='b')
>
> RuntimeError: impossible<bad format char>: 'CC'
>
> Is this error-message expected?

Nope. It appears to be a bug in Python. The format code 'C' is missing
in the switch statement in skipitem() in getargs.c. I added "case
'C': /* int */" after "case 'c': /* char */" and then example worked
for me.

I'll open a bug report.

casevh
>
> On Nov 30, 10:19 pm, casevh <cas...(a)gmail.com> wrote:
>
> > On Nov 30, 1:04 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
>
> > > Obviously the name of the C function and the char variable cannot both
> > > be foo,
> > > so the C code should be:
>
> > > static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> > > {
> > >   char foochar;
> > >   char *kwlist[] = {"foochar", NULL};
> > >   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist,
> > > &foochar))
> > >     return NULL;
> > >   ...
>
> > > The question remains the same: why can't I pass a single character
> > > argument to this function under Python3.1?
>
> > > Thanks.
> > > Joachim
>
> > > On Nov 30, 9:52 pm, Joachim Dahl <dahl.joac...(a)gmail.com> wrote:
>
> > > > I am updating an extension module from Python2.6 to Python3.
>
> > > > I used to pass character codes to the extension module, for example, I
> > > > would write:
>
> > > > >>> foo('X')
>
> > > > with the corresponding C extension routine defined as follows:
> > > > static PyObject* foo(PyObject *self, PyObject *args, PyObject *kwrds)
> > > > {
> > > >   char foo;
> > > >   char *kwlist[] = {"foo", NULL};
> > > >   if (!PyArg_ParseTupleAndKeywords(args, kwrds, "c", kwlist, &foo))
> > > >     return NULL;
> > > >   ...
>
> > > > In Python3.0 this also works, but in Python3.1 I get the following
> > > > error:
> > > > TypeError: argument 1 must be a byte string of length 1, not str
>
> > > > and I seem to be supposed to write>>> foo(b'X')
>
> > > > instead. From the Python C API, I have not been able to explain this
> > > > new behavior.
> > > > What is the correct way to pass a single character argument to
> > > > Python3.1
> > > > extension modules?- Hide quoted text -
>
> > > - Show quoted text -
>
> > Python 3.1 uses "c" (lowercase c) to parse a single character from a
> > byte-string and uses "C" (uppercase c) to parse a single character
> > from a Unicode string. I don't think there is an easy way to accept a
> > character from both.
>
> > HTH,
>
> > casevh
>
>