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

Reply via email to