Re: [PyQt] __setitem__ Problem

2009-04-19 Thread Neil Birkbeck
Thanks!  Problem solved.  Works fine with overloaded __setitem__'s too.

Neil Birkbeck

On Sat, Apr 18, 2009 at 9:56 AM, Phil Thompson
p...@riverbankcomputing.comwrote:

 On Thu, 16 Apr 2009 12:26:17 -0600 (MDT), Neil Birkbeck
 birkb...@cs.ualberta.ca wrote:
  In older versions of sip (4.7.3), I have used __setitem__, __getitem__ to

  access/set elements from multidimensional quantities of a wrapped c++
  object that uses operator()(int,int).  For example, the following sip
 code
  used to work fine
 
  class A {
   int operator()(int x,int y) const;
 
   int __getitem__(int x,int y) const;
  %MethodCode
  ...
  %End
 
   void __setitem__(int x,int y, int val) const;
  %MethodCode
  ...
  %End
  };
 
 From the ChangeLog this feature seemed to have been removed (in a related

  mailing list post, it was reported that the above usage was a bug
 

 http://article.gmane.org/gmane.comp.python.pyqt-pykde/12342/match=sip+__setitem__
 ).
 
  With the new checking (sip 4.7.9, possibly earlier), the above code will
  now give an error (e.g., sip: A.sip:18: Incorrect number of arguments to
  Python slot).  The previous mailing list post
  (http://thread.gmane.org/gmane.comp.python.pyqt-pykde/12342) suggested
 to

  either not use __setitem__/__getitem__ for this purpose or to use a
 tuple.
 
  I updated my code and the tuples work fine for __getitem__, but I cannot
  seem to get the tuple to work for __setitem__.
 
  For example,
 
  A.sip:
 
  class A {
   int __getitem(int x,int y);
  %MethodCode
   //This is just a dummy, actually parse the tuple and extract indices...
  %End
 
   void __setitem__(SIP_PYOBJECT, SIP_PYOBJECT);
  %MethodCode
//Do something here
  %End
  };
 
  Python test:
  from A import A
  a = A(10,10)
  # Getting works fine, no error parsing arguments
  b = a[0,0]
  b = a[0]
 
  # Setting works with anything but tuple
  a[0] = 1 # Works fine
  a[[1,2]] = 1 # Also works, but is not really a desired syntax
  a[0:5] = 1   # Works, would check for this when parsing args.
  a[(0,1)] = 1 # Error: TypeError: too many arguments to A.__setitem__(),
 2
  at most expected
  a[0,1] = 1 #  Same error
  tup = (0,1)
  a[tup] = 1 # Same error
 
  The tuple always gets unpacked into more than one argument for
 __setitem__
  and causes the TypeError, which happens before any of the sip %MethodCode

  can be called.
 
  Looking at the generated code for the __setitem__, the parsing of args
  looks something like:
  sipParseArgs(sipArgsParsed,sipArgs,P0P0,a0,a1)
 
  On the other hand, the parsing of args for __getitem__ seems to work due
  to the single arg format of 1P0.  Manually editing the generated code
 to
  return the args packed into a single tuple (including the set value) like

  __getitem__ works but is not a satisfying solution.
 
  Changing the function signature of __setitem__ to take a SIP_PYTUPLE as
  the first argument also does not help, although it does change the
  sipParseArgs format to TP0 (e.g.,
  sipParseArgs(sipArgsParsed,sipArgs,TP0,PyTuple_Type,a0,a1)).  I
  suspect this call would succeed if there was a way to make sipParseArgs
  put the first n-1 sipArgs into a0 and the last argument into a1.
 
  The parsing of arguments for other methods with similar signature, e.g.,
  void afunc(SIP_PYOBJECT, SIP_PYOBJECT), does indeed accept stuff like
  afunc((1,2), 0), so the problem appears to be with __setitem__.
 
  I could be doing something wrong as no one else appears to be having this

  problem.  If not, is there a some other way to force the argument parsing

  to put the first args into a tuple?  Or is there a way to do it by hand
  (like a NoArgParser for member functions)?Currently, I modified the
  sip source (in sipgen/parser.c:findFunction, line 7642, {__setitem__,
  setitem_slot, TRUE, -1}) to not check the # of arguments to
  __setitem__/__getitem__.   For the time being, this gives the behaviour
 of
  the older version, so that I can remain using my old sip files (like the
  beginning of this post).

 Try tonight's SIP snapshot.

 Use __setitem__(SIP_PYTUPLE, SIP_PYOBJECT) and then unpack the tuple as you
 are in your __getitem__.

 Thanks,
 Phil

___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

[PyQt] (no subject)

2009-04-16 Thread Neil Birkbeck

In older versions of sip (4.7.3), I have used __setitem__, __getitem__ to 
access/set elements from multidimensional quantities of a wrapped c++ 
object that uses operator()(int,int).  For example, the following sip code 
used to work fine

class A {
 int operator()(int x,int y) const;

 int __getitem__(int x,int y) const;
%MethodCode
...
%End

 void __setitem__(int x,int y, int val) const;
%MethodCode
...
%End
};

From the ChangeLog this feature seemed to have been removed (in a related 
mailing list post, it was reported that the above usage was a bug
http://article.gmane.org/gmane.comp.python.pyqt-pykde/12342/match=sip+__setitem__).

With the new checking (sip 4.7.9, possibly earlier), the above code will 
now give an error (e.g., sip: A.sip:18: Incorrect number of arguments to 
Python slot).  The previous mailing list post 
(http://thread.gmane.org/gmane.comp.python.pyqt-pykde/12342) suggested to 
either not use __setitem__/__getitem__ for this purpose or to use a tuple.

I updated my code and the tuples work fine for __getitem__, but I cannot 
seem to get the tuple to work for __setitem__.

For example,

A.sip:

class A {
 int __getitem(int x,int y);
%MethodCode
 //This is just a dummy, actually parse the tuple and extract indices...
%End

 void __setitem__(SIP_PYOBJECT, SIP_PYOBJECT);
%MethodCode
  //Do something here
%End
};

Python test:
from A import A
a = A(10,10)
# Getting works fine, no error parsing arguments
b = a[0,0]
b = a[0]

# Setting works with anything but tuple
a[0] = 1 # Works fine
a[[1,2]] = 1 # Also works, but is not really a desired syntax
a[0:5] = 1   # Works, would check for this when parsing args.
a[(0,1)] = 1 # Error: TypeError: too many arguments to A.__setitem__(), 2 at 
most expected
a[0,1] = 1 #  Same error
tup = (0,1)
a[tup] = 1 # Same error

The tuple always gets unpacked into more than one argument for __setitem__ 
and causes the TypeError, which happens before any of the sip %MethodCode 
can be called.

Looking at the generated code for the __setitem__, the parsing of args 
looks something like:
sipParseArgs(sipArgsParsed,sipArgs,P0P0,a0,a1)

On the other hand, the parsing of args for __getitem__ seems to work due 
to the single arg format of 1P0.  Manually editing the generated code to 
return the args packed into a single tuple (including the set value) like 
__getitem__ works but is not a satisfying solution.

Changing the function signature of __setitem__ to take a SIP_PYTUPLE as 
the first argument also does not help, although it does change the 
sipParseArgs format to TP0 (e.g., 
sipParseArgs(sipArgsParsed,sipArgs,TP0,PyTuple_Type,a0,a1)).  I 
suspect this call would succeed if there was a way to make sipParseArgs 
put the first n-1 sipArgs into a0 and the last argument into a1.  

The parsing of arguments for other methods with similar signature, e.g., 
void afunc(SIP_PYOBJECT, SIP_PYOBJECT), does indeed accept stuff like 
afunc((1,2), 0), so the problem appears to be with __setitem__. 

I could be doing something wrong as no one else appears to be having this 
problem.  If not, is there a some other way to force the argument parsing 
to put the first args into a tuple?  Or is there a way to do it by hand 
(like a NoArgParser for member functions)?Currently, I modified the 
sip source (in sipgen/parser.c:findFunction, line 7642, {__setitem__, 
setitem_slot, TRUE, -1}) to not check the # of arguments to 
__setitem__/__getitem__.   For the time being, this gives the behaviour of 
the older version, so that I can remain using my old sip files (like the 
beginning of this post).

Thanks,
Neil Birkbeck
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt