Revision: 568 http://rpy.svn.sourceforge.net/rpy/?rev=568&view=rev Author: lgautier Date: 2008-07-02 08:04:22 -0700 (Wed, 02 Jul 2008)
Log Message: ----------- robjects: - new class RVectorDelegator, to delegate indexing the "R way" (on a suggestion by Michael Sorich), as well as operators such as __add__, __mult__, __and__, __or__. - getNames renamed to getnames - fix in RS4.__getattr__ (proper wrapping of the object returned) Modified Paths: -------------- branches/rpy_nextgen/rpy/robjects/__init__.py branches/rpy_nextgen/rpy/robjects/tests/testRArray.py branches/rpy_nextgen/rpy/robjects/tests/testRVector.py Modified: branches/rpy_nextgen/rpy/robjects/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/__init__.py 2008-07-02 14:57:48 UTC (rev 567) +++ branches/rpy_nextgen/rpy/robjects/__init__.py 2008-07-02 15:04:22 UTC (rev 568) @@ -123,9 +123,52 @@ "that inherits from rinterface.Sexp" +\ "(not from %s)" %type(value)) super(RObject, self).__setattr__(name, value) - +class RVectorDelegator(object): + """ + Delegate operations such as __getitem__, __add__, etc.. + to an R call of the corresponding function on its parent + attribute. + This permits a convenient coexistence between + operators on Python sequence object with their R conterparts. + """ + def __init__(self, parent): + """ The parent in expected to inherit from RVector. """ + self._parent = parent + + def __getitem__(self, *args, **kwargs): + res = self._parent.subset(*args, **kwargs) + return res + + def __add__(self, x): + res = r.get("+")(self._parent, x) + return res + + def __sub__(self, x): + res = r.get("-")(self._parent, x) + return res + + def __mul__(self, x): + res = r.get("*")(self._parent, x) + return res + + def __div__(self, x): + res = r.get("/")(self._parent, x) + return res + + def __divmod__(self, x): + res = r.get("%%")(self._parent, x) + return res + + def __or__(self, x): + res = r.get("|")(self._parent, x) + return res + + def __and__(self, x): + res = r.get("&")(self._parent, x) + return res + class RVector(RObjectMixin, rinterface.SexpVector): """ R vector-like object. Items in those instances can be accessed with the method "__getitem__" ("[" operator), @@ -135,6 +178,7 @@ if not isinstance(o, rinterface.SexpVector): o = py2ri(o) super(RVector, self).__init__(o) + self.r = RVectorDelegator(self) def subset(self, *args, **kwargs): @@ -160,11 +204,16 @@ def assign(self, *args): #FIXME: value must be the last argument, but this can be # challenging in since python kwargs do not enforce any order + #(an ordered dictionary class will therefore be implemented) args = [py2ro(x) for x in args] res = r["[<-"](*([self, ] + [x for x in args])) return res + def __add__(self, x): + res = r.get("c")(self, x) + return res + def __getitem__(self, i): res = super(RVector, self).__getitem__(i) if isinstance(res, rinterface.Sexp): @@ -175,39 +224,11 @@ value = py2ri(value) res = super(RVector, self).__setitem__(i, value) - def __add__(self, x): - res = r.get("+")(self, x) - return res - - def __sub__(self, x): - res = r.get("-")(self, x) - return res - - def __mul__(self, x): - res = r.get("*")(self, x) - return res - - def __div__(self, x): - res = r.get("/")(self, x) - return res - - def __divmod__(self, x): - res = r.get("%%")(self, x) - return res - - def __or__(self, x): - res = r.get("|")(self, x) - return res - - def __and__(self, x): - res = r.get("&")(self, x) - return res - - def getNames(self): + def getnames(self): res = r.names(self) return res - def setNames(self, value): + def setnames(self, value): """ Return a vector of names (like the R function 'names' does it).""" @@ -233,7 +254,7 @@ value = py2ro(value) res = r["dim<-"](value) - def getNames(self): + def getnames(self): """ Return a list of name vectors (like the R function 'dimnames' does it).""" @@ -301,6 +322,7 @@ def __getattr__(self, attr): res = self.do_slot(attr) + res = ri2py(res) return res Modified: branches/rpy_nextgen/rpy/robjects/tests/testRArray.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRArray.py 2008-07-02 14:57:48 UTC (rev 567) +++ branches/rpy_nextgen/rpy/robjects/tests/testRArray.py 2008-07-02 15:04:22 UTC (rev 568) @@ -26,7 +26,7 @@ m = robjects.r.matrix(1, nrow=3, ncol=2, dimnames = dimnames) a = robjects.RArray(m) - res = a.getNames() + res = a.getnames() r_identical = robjects.r.identical self.assertTrue(r_identical(dimnames[0], res[0])) self.assertTrue(r_identical(dimnames[1], res[1])) Modified: branches/rpy_nextgen/rpy/robjects/tests/testRVector.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRVector.py 2008-07-02 14:57:48 UTC (rev 567) +++ branches/rpy_nextgen/rpy/robjects/tests/testRVector.py 2008-07-02 15:04:22 UTC (rev 568) @@ -20,17 +20,33 @@ del(ri_v) self.assertEquals(ri.INTSXP, ro_v.typeof()) - - def testOperators(self): + + def testAddOperators(self): seq_R = robjects.r["seq"] + mySeqA = seq_R(0, 3) + mySeqB = seq_R(5, 7) + mySeqAdd = mySeqA + mySeqB + + self.assertEquals(len(mySeqA)+len(mySeqB), len(mySeqAdd)) + + for i, li in enumerate(mySeqA): + self.assertEquals(li, mySeqAdd[i]) + for j, li in enumerate(mySeqB): + self.assertEquals(li, mySeqAdd[i+j+1]) + + def testRAddOperators(self): + seq_R = robjects.r["seq"] mySeq = seq_R(0, 10) - mySeqAdd = mySeq + 2 + mySeqAdd = mySeq.r + 2 for i, li in enumerate(mySeq): - self.assertEquals(i + 2, mySeqAdd[i]) + self.assertEquals(li + 2, mySeqAdd[i]) - mySeqAdd = mySeq + mySeq + def testRMultOperators(self): + seq_R = robjects.r["seq"] + mySeq = seq_R(0, 10) + mySeqAdd = mySeq.r + mySeq for i, li in enumerate(mySeq): - self.assertEquals(mySeq[i] * 2, mySeqAdd[i]) + self.assertEquals(li * 2, mySeqAdd[i]) def testSubsetByIndex(self): @@ -43,6 +59,11 @@ for i, si in enumerate(myIndex): self.assertEquals(mySeq[si-1], mySubset[i]) + # same with the delegator + mySubset = mySeq.r[myIndex] + for i, si in enumerate(myIndex): + self.assertEquals(mySeq[si-1], mySubset[i]) + def testSubsetByName(self): seq_R = robjects.baseNameSpaceEnv["seq"] mySeq = seq_R(0, 25) @@ -122,17 +143,17 @@ r_names = robjects.baseNameSpaceEnv["c"](*v_names) vec = robjects.baseNameSpaceEnv["names<-"](vec, r_names) for i in xrange(len(vec)): - self.assertEquals(v_names[i], vec.getNames()[i]) + self.assertEquals(v_names[i], vec.getnames()[i]) - vec.getNames()[0] = 'x' + vec.getnames()[0] = 'x' def testSetNames(self): vec = robjects.RVector(array.array('i', [1,2,3])) names = ['x', 'y', 'z'] #FIXME: simplify this - vec = vec.setNames(names) + vec = vec.setnames(names) for i in xrange(len(vec)): - self.assertEquals(names[i], vec.getNames()[i]) + self.assertEquals(names[i], vec.getnames()[i]) def suite(): suite = unittest.TestLoader().loadTestsFromTestCase(RVectorTestCase) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ rpy-list mailing list rpy-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rpy-list