[PyQt] __setitem__ Problem

Neil Birkbeck neil.birkbeck at gmail.com
Sun Apr 19 09:29:14 BST 2009


Thanks!  Problem solved.  Works fine with overloaded __setitem__'s too.

Neil Birkbeck

On Sat, Apr 18, 2009 at 9:56 AM, Phil Thompson
<phil at riverbankcomputing.com>wrote:

> On Thu, 16 Apr 2009 12:26:17 -0600 (MDT), Neil Birkbeck
> <birkbeck at 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20090419/c9bc5ae7/attachment.html


More information about the PyQt mailing list