PyArg_ParseTupleAndKeywords

M

Mr.M

Hi,

i can't understand what i'm doing wrong. I have a c/api that implements
a new class.
In (initproc) function i have somethink like this:

Code:
(some declarations omitted here)
static char* keywordlist[] = {"service",
                               "event_type",
                               "free_text",
                               "group_uid",
                               "remote_name",
                               "remote_abook_uid",
                               "start_time",
                               "end_time",
                               "storage_time",
                               "flags",
                               "bytes_sent",
                               "bytes_received",
                                NULL};

if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ssssssiiiiii", 
keywordlist,
                                &service,
                                &event_type,
                                &free_text,
                                &group_uid,
                                &remote_name,
                                &remote_abook_uid,
                                &start_time,
                                &end_time,
                                &storage_time,
                                &flags,
                                &bytes_sent,
                                &bytes_received)) return -1;

Ok, what i want is something like this:

Code:
import mymodule
a = mymodule.myclass() # ok, this works
a = mymodule.myclass(flags = 1) # bad, this won't work[QUOTE]
> TypeError: expected string or Unicode object, tuple found[/QUOTE]

I found that if i write this everything works fine:

Code:
import mymodule
a = mymodule.myclass(service = "blabla", event_type = "event", free_text 
  = "free", group_uid = "group", remote_name = "remote name", 
remote_abook_uid = "abook", start_time = 1, end_time = 61, storage_time 
= 61, flags = 2)

in other words, the code only works if *EVERY* argument is specified in
exactly the same position it appears in keyword-null-terminated array.

Could you please help me?

Thank you,

Luca.
 
C

Carl Banks

Hi,

i can't understand what i'm doing wrong. I have a c/api that implements
a new class.
In (initproc) function i have somethink like this:

Code:
(some declarations omitted here)[/QUOTE]

You probably shouldn't have, that could be where the error is....  I'd
include the whole function up to the call that raises the exception.

[QUOTE]
static char* keywordlist[] = {"service",
                               "event_type",
                               "free_text",
                               "group_uid",
                               "remote_name",
                               "remote_abook_uid",
                               "start_time",
                               "end_time",
                               "storage_time",
                               "flags",
                               "bytes_sent",
                               "bytes_received",
                                NULL};

if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ssssssiiiiii",
keywordlist,
                                &service,
                                &event_type,
                                &free_text,
                                &group_uid,
                                &remote_name,
                                &remote_abook_uid,
                                &start_time,
                                &end_time,
                                &storage_time,
                                &flags,
                                &bytes_sent,
                                &bytes_received)) return -1;[/QUOTE]


This should be return NULL in most cases, but not all (such as if it's
an object's tp_init--and it does look like that's the case here, so
probably not the issue).

[QUOTE]

Ok, what i want is something like this:

Code:
import mymodule
a = mymodule.myclass() # ok, this works
a = mymodule.myclass(flags = 1) # bad, this won't work
 > TypeError: expected string or Unicode object, tuple found

Are you sure that PyArg_ParseTupleAndKeywords is what's raising the
error?

Are you subclassing this type in Python, and passing one of the string
parameters a tuple by mistake? For instance, did you do something
like this:

class myclass(_mycmodule._myctype):
def __init__(self,*args,**kwargs):
log_something_here()
super(myclass,self).__init__(args,**kwargs)

Note the missing * on args.

I found that if i write this everything works fine:

Code:
import mymodule
a = mymodule.myclass(service = "blabla", event_type = "event", free_text
  = "free", group_uid = "group", remote_name = "remote name",
remote_abook_uid = "abook", start_time = 1, end_time = 61, storage_time
= 61, flags = 2)

in other words, the code only works if *EVERY* argument is specified in
exactly the same position it appears in keyword-null-terminated array.

That it would have to be in a certain order is strange. Are you sure
it's just not merely that they all have to be present?

Could you please help me?

Tricky, but I think it'd help if you provided more information. My
gut feeling is that there exception is being raised somewhere other
than you think it is (i.e., not by PyArg_ParseTuple), so I'd recommend
adding some debugging statements to track down the exact point wher
the error occurs.


Carl Banks
 
M

Mr.M

Carl Banks ha scritto:
You probably shouldn't have, that could be where the error is.... I'd
include the whole function up to the call that raises the exception.

Thank you so much Carl for your help, i'll provide more info so that you
can try to fix my errors!
Thank you again!

First of all i'll try to explain what i've discovered over a night i
spent awake trying to find where the bug is.

My init behaves differently in this situations:

Code:
# this works
dummy = mymodule.myclass()

# this works
dummy = mymodule.myclass("string for service")

# this also works
dummy = mymodule.myclass("string for service", "string for event_type")
# and it works if i provide arguments in the right sequence, of course

# this won't work
dummy = mymodule.myclass("string for service", "string for event_type",
free_text = "string for free_text")

# but this works
dummy = mymodule.myclass(service = "string for service")

# the worst thing: this doesn't work but it did and i can't
# understand what is changed

dummy = mymodule.myclass(free_text = "text for free_text")

ok, every time the code fails i get this exception:

TypeError: expected string or Unicode object, tuple found

so, i think for some reason PyArg_ParseTupleAndKeywords receives "args"
as a touple instead of something else.

This is everything i managed to discover.

This is the code:

[code]
         /* DEBUG INFO */
         printf("event INIT\n");
         if (args)
         {
                 int i;
                 printf("args        = \"%s\"\n", PyString_AsString(args));
                 printf("type        = %s\n",
PyString_AsString(PyObject_Repr(PyObject_Type(args))));
                 printf("tuple size  = %d\n", PyTuple_Size(args));
                 for (i = 0; i < PyTuple_Size(args); i++)
                 {
                         printf("%d) %s\n", i,
PyString_AsString(PyTuple_GetItem(args, i)));
                 }
         }
         else
         {
                 printf("args = NULL\n");
         }
         printf("dict:\n");
         if (keywords)
         {
                 printf("     = %s\n",
PyString_AsString(PyObject_Repr(keywords)));
                 printf("type = %s\n",
PyString_AsString(PyObject_Repr(PyObject_Type(keywords))));
         }
         else
         {
                 printf("keywords = NULL\n");
         }

     char* service          = NULL;
     char* event_type       = NULL;
     char* free_text        = NULL;
     char* group_uid        = NULL;
     char* remote_name      = NULL;
     char* remote_abook_uid = NULL;

     time_t start_time   = -1L;
     time_t end_time     = -1L;
     time_t storage_time = -1L;

     int flags = 0;

     int bytes_sent     = -1;
     int bytes_received = -1;

     PyObject* temp;

     static char* keywordlist[] = {"service",
                                   "event_type",
                                   "free_text",
                                   "group_uid",
                                   "remote_name",
                                   "remote_abook_uid",
                                   "start_time",
                                   "end_time",
                                   "storage_time",
                                   "flags",
                                   "bytes_sent",
                                   "bytes_received",
                                   NULL};

     if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ssssssiiiiii",
keywordlist,
                                      &service,
                                      &event_type,
                                      &free_text,
                                      &group_uid,
                                      &remote_name,
                                      &remote_abook_uid,
                                      &start_time,
                                      &end_time,
                                      &storage_time,
                                      &flags,
                                      &bytes_sent,
                                      &bytes_received))
     {
         return -1;
     }

     printf("PyArg_ParseTupleAndKeywords worked fine\n");

(sorry if my code is a little messy and my english rather bad!)
Are you sure that PyArg_ParseTupleAndKeywords is what's raising the
error?

Yes, i think so. I have a lot of printf in my code!
Are you subclassing this type in Python, and passing one of the string
parameters a tuple by mistake? For instance, did you do something
like this:

class myclass(_mycmodule._myctype):
def __init__(self,*args,**kwargs):
log_something_here()
super(myclass,self).__init__(args,**kwargs)

Note the missing * on args.

no, i'm not subclassing.
I have to admit that i had some testcase and a few weeks ago they worked
like a charm... i can't understand what i changed, of course.
I found that if i write this everything works fine:

Code:
import mymodule
a = mymodule.myclass(service = "blabla", event_type = "event", free_text
= "free", group_uid = "group", remote_name = "remote name",
remote_abook_uid = "abook", start_time = 1, end_time = 61, storage_time
= 61, flags = 2)

in other words, the code only works if *EVERY* argument is specified in
exactly the same position it appears in keyword-null-terminated array.

That it would have to be in a certain order is strange. Are you sure
it's just not merely that they all have to be present?

No, i tryied to remove the "|" and Python complains that 12 argument
must be present. So they are, in a sense, optional, but (and this is
strange), they must be present in the right order even i provide them
with keyword arguments.
Tricky, but I think it'd help if you provided more information. My
gut feeling is that there exception is being raised somewhere other
than you think it is (i.e., not by PyArg_ParseTuple), so I'd recommend
adding some debugging statements to track down the exact point wher
the error occurs.

Ok, thank you!
The code i posted is exactly the same i run (and it fails).
I've no problem sending you the whole module or adding any other debug
info you think could be helpfull to find the source of the bug.

Ciao,

Luca.
 
M

MRAB

Mr.M said:
Carl Banks ha scritto:
You probably shouldn't have, that could be where the error is.... I'd
include the whole function up to the call that raises the exception.

Thank you so much Carl for your help, i'll provide more info so that you
can try to fix my errors!
Thank you again!

First of all i'll try to explain what i've discovered over a night i
spent awake trying to find where the bug is.

My init behaves differently in this situations:

Code:
# this works
dummy = mymodule.myclass()

# this works
dummy = mymodule.myclass("string for service")

# this also works
dummy = mymodule.myclass("string for service", "string for event_type")
# and it works if i provide arguments in the right sequence, of course

# this won't work
dummy = mymodule.myclass("string for service", "string for event_type",
free_text = "string for free_text")

# but this works
dummy = mymodule.myclass(service = "string for service")

# the worst thing: this doesn't work but it did and i can't
# understand what is changed

dummy = mymodule.myclass(free_text = "text for free_text")

ok, every time the code fails i get this exception:

TypeError: expected string or Unicode object, tuple found

so, i think for some reason PyArg_ParseTupleAndKeywords receives "args"
as a touple instead of something else.

This is everything i managed to discover.

This is the code:

[code]
/* DEBUG INFO */
printf("event INIT\n");
if (args)
{
int i;
printf("args        = \"%s\"\n", PyString_AsString(args));
printf("type        = %s\n",
PyString_AsString(PyObject_Repr(PyObject_Type(args))));
printf("tuple size  = %d\n", PyTuple_Size(args));
for (i = 0; i < PyTuple_Size(args); i++)
{
printf("%d) %s\n", i,
PyString_AsString(PyTuple_GetItem(args, i)));
}
}
else
{
printf("args = NULL\n");
}
printf("dict:\n");
if (keywords)
{
printf("     = %s\n",
PyString_AsString(PyObject_Repr(keywords)));
printf("type = %s\n",
PyString_AsString(PyObject_Repr(PyObject_Type(keywords))));
}
else
{
printf("keywords = NULL\n");
}

char* service          = NULL;
char* event_type       = NULL;
char* free_text        = NULL;
char* group_uid        = NULL;
char* remote_name      = NULL;
char* remote_abook_uid = NULL;

time_t start_time   = -1L;
time_t end_time     = -1L;
time_t storage_time = -1L;

int flags = 0;

int bytes_sent     = -1;
int bytes_received = -1;

PyObject* temp;

static char* keywordlist[] = {"service",
"event_type",
"free_text",
"group_uid",
"remote_name",
"remote_abook_uid",
"start_time",
"end_time",
"storage_time",
"flags",
"bytes_sent",
"bytes_received",
NULL};

if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ssssssiiiiii",
keywordlist,
&service,
&event_type,
&free_text,
&group_uid,
&remote_name,
&remote_abook_uid,
&start_time,
&end_time,
&storage_time,
&flags,
&bytes_sent,
&bytes_received))
{
return -1;
}

printf("PyArg_ParseTupleAndKeywords worked fine\n");

(sorry if my code is a little messy and my english rather bad!)
Are you sure that PyArg_ParseTupleAndKeywords is what's raising the
error?

Yes, i think so. I have a lot of printf in my code!
Are you subclassing this type in Python, and passing one of the string
parameters a tuple by mistake? For instance, did you do something
like this:

class myclass(_mycmodule._myctype):
def __init__(self,*args,**kwargs):
log_something_here()
super(myclass,self).__init__(args,**kwargs)

Note the missing * on args.

no, i'm not subclassing.
I have to admit that i had some testcase and a few weeks ago they worked
like a charm... i can't understand what i changed, of course.
I found that if i write this everything works fine:

Code:
import mymodule
a = mymodule.myclass(service = "blabla", event_type = "event", free_text
= "free", group_uid = "group", remote_name = "remote name",
remote_abook_uid = "abook", start_time = 1, end_time = 61, storage_time
= 61, flags = 2)

in other words, the code only works if *EVERY* argument is specified in
exactly the same position it appears in keyword-null-terminated array.

That it would have to be in a certain order is strange. Are you sure
it's just not merely that they all have to be present?

No, i tryied to remove the "|" and Python complains that 12 argument
must be present. So they are, in a sense, optional, but (and this is
strange), they must be present in the right order even i provide them
with keyword arguments.
Tricky, but I think it'd help if you provided more information. My
gut feeling is that there exception is being raised somewhere other
than you think it is (i.e., not by PyArg_ParseTuple), so I'd recommend
adding some debugging statements to track down the exact point wher
the error occurs.

Ok, thank you!
The code i posted is exactly the same i run (and it fails).
I've no problem sending you the whole module or adding any other debug
info you think could be helpfull to find the source of the bug.
Did you specify that the method accepts keywords arguments with
METH_KEYWORDS? The function would take parameters for the instance
(self), the positional arguments (args) and the keyword arguments
(kwargs).

http://docs.python.org/c-api/structures.html

If you don't use METH_KEYWORDS then it'll think that all the arguments
are positional, which is what seems to be happening:
 
M

Mr.M

MRAB ha scritto:
Did you specify that the method accepts keywords arguments with
METH_KEYWORDS? The function would take parameters for the instance
(self), the positional arguments (args) and the keyword arguments
(kwargs).

http://docs.python.org/c-api/structures.html

If you don't use METH_KEYWORDS then it'll think that all the arguments
are positional, which is what seems to be happening:

Thank you MRAB for your reply.
No, i didn't specify METH_KEYWORDS flag, but i think init method (the
one that you put in tp_init slot, it is "initproc" type) doesn't have to
appear in the PyMethodDef structure.

Maybe i'm wrong?

Luca.
 
M

MRAB

Mr.M said:
MRAB ha scritto:


Thank you MRAB for your reply.
No, i didn't specify METH_KEYWORDS flag, but i think init method (the
one that you put in tp_init slot, it is "initproc" type) doesn't have to
appear in the PyMethodDef structure.

Maybe i'm wrong?
I think you're right.
 
M

Mr.M

MRAB ha scritto:
I think you're right.

I have rewritten my code, a piece at a time, and (and this is very
annoying) now it works fine.

I really can't understand what went wrong with my old code.

Luca.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,999
Messages
2,570,243
Members
46,836
Latest member
login dogas

Latest Threads

Top