Thanks! Problem solved. Works fine with overloaded __setitem__'s too.<br><br>Neil Birkbeck<br><br><div class="gmail_quote">On Sat, Apr 18, 2009 at 9:56 AM, Phil Thompson <span dir="ltr"><<a href="mailto:phil@riverbankcomputing.com">phil@riverbankcomputing.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">On Thu, 16 Apr 2009 12:26:17 -0600 (MDT), Neil Birkbeck<br>
<<a href="mailto:birkbeck@cs.ualberta.ca">birkbeck@cs.ualberta.ca</a>> wrote:<br>
> In older versions of sip (4.7.3), I have used __setitem__, __getitem__ to<br>
<br>
> access/set elements from multidimensional quantities of a wrapped c++<br>
> object that uses operator()(int,int). For example, the following sip<br>
code<br>
> used to work fine<br>
><br>
> class A {<br>
> int operator()(int x,int y) const;<br>
><br>
> int __getitem__(int x,int y) const;<br>
> %MethodCode<br>
> ...<br>
> %End<br>
><br>
> void __setitem__(int x,int y, int val) const;<br>
> %MethodCode<br>
> ...<br>
> %End<br>
> };<br>
><br>
>>From the ChangeLog this feature seemed to have been removed (in a related<br>
<br>
> mailing list post, it was reported that the above usage was a bug<br>
><br>
<a href="http://article.gmane.org/gmane.comp.python.pyqt-pykde/12342/match=sip+__setitem__" target="_blank">http://article.gmane.org/gmane.comp.python.pyqt-pykde/12342/match=sip+__setitem__</a>).<br>
><br>
> With the new checking (sip 4.7.9, possibly earlier), the above code will<br>
> now give an error (e.g., sip: A.sip:18: Incorrect number of arguments to<br>
> Python slot). The previous mailing list post<br>
> (<a href="http://thread.gmane.org/gmane.comp.python.pyqt-pykde/12342" target="_blank">http://thread.gmane.org/gmane.comp.python.pyqt-pykde/12342</a>) suggested to<br>
<br>
> either not use __setitem__/__getitem__ for this purpose or to use a<br>
tuple.<br>
><br>
> I updated my code and the tuples work fine for __getitem__, but I cannot<br>
> seem to get the tuple to work for __setitem__.<br>
><br>
> For example,<br>
><br>
> A.sip:<br>
><br>
> class A {<br>
> int __getitem(int x,int y);<br>
> %MethodCode<br>
> //This is just a dummy, actually parse the tuple and extract indices...<br>
> %End<br>
><br>
> void __setitem__(SIP_PYOBJECT, SIP_PYOBJECT);<br>
> %MethodCode<br>
> //Do something here....<br>
> %End<br>
> };<br>
><br>
> Python test:<br>
> from A import A<br>
> a = A(10,10)<br>
> # Getting works fine, no error parsing arguments<br>
> b = a[0,0]<br>
> b = a[0]<br>
><br>
> # Setting works with anything but tuple<br>
> a[0] = 1 # Works fine<br>
> a[[1,2]] = 1 # Also works, but is not really a desired syntax<br>
> a[0:5] = 1 # Works, would check for this when parsing args.<br>
> a[(0,1)] = 1 # Error: "TypeError: too many arguments to A.__setitem__(),<br>
2<br>
> at most expected"<br>
> a[0,1] = 1 # Same error<br>
> tup = (0,1)<br>
> a[tup] = 1 # Same error<br>
><br>
> The tuple always gets unpacked into more than one argument for<br>
__setitem__<br>
> and causes the TypeError, which happens before any of the sip %MethodCode<br>
<br>
> can be called.<br>
><br>
> Looking at the generated code for the __setitem__, the parsing of args<br>
> looks something like:<br>
> sipParseArgs(&sipArgsParsed,sipArgs,"P0P0",&a0,&a1)<br>
><br>
> On the other hand, the parsing of args for __getitem__ seems to work due<br>
> to the single arg format of "1P0". Manually editing the generated code<br>
to<br>
> return the args packed into a single tuple (including the set value) like<br>
<br>
> __getitem__ works but is not a satisfying solution.<br>
><br>
> Changing the function signature of __setitem__ to take a SIP_PYTUPLE as<br>
> the first argument also does not help, although it does change the<br>
> sipParseArgs format to "TP0" (e.g.,<br>
> sipParseArgs(&sipArgsParsed,sipArgs,"TP0",&PyTuple_Type,&a0,&a1)). I<br>
> suspect this call would succeed if there was a way to make sipParseArgs<br>
> put the first n-1 sipArgs into a0 and the last argument into a1.<br>
><br>
> The parsing of arguments for other methods with similar signature, e.g.,<br>
> "void afunc(SIP_PYOBJECT, SIP_PYOBJECT)", does indeed accept stuff like<br>
> afunc((1,2), 0), so the problem appears to be with __setitem__.<br>
><br>
> I could be doing something wrong as no one else appears to be having this<br>
<br>
> problem. If not, is there a some other way to force the argument parsing<br>
<br>
> to put the first args into a tuple? Or is there a way to do it by hand<br>
> (like a NoArgParser for member functions)? Currently, I modified the<br>
> sip source (in sipgen/parser.c:findFunction, line 7642, {"__setitem__",<br>
> "setitem_slot, TRUE, -1}) to not check the # of arguments to<br>
> __setitem__/__getitem__. For the time being, this gives the behaviour<br>
of<br>
> the older version, so that I can remain using my old sip files (like the<br>
> beginning of this post).<br>
<br>
Try tonight's SIP snapshot.<br>
<br>
Use __setitem__(SIP_PYTUPLE, SIP_PYOBJECT) and then unpack the tuple as you<br>
are in your __getitem__.<br>
<br>
Thanks,<br>
<font color="#888888">Phil<br>
</font></blockquote></div><br>