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.com>wrote: > 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 list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt