Revision: 402
          http://rpy.svn.sourceforge.net/rpy/?rev=402&view=rev
Author:   lgautier
Date:     2008-01-27 06:15:16 -0800 (Sun, 27 Jan 2008)

Log Message:
-----------
- Added getslice methods for Robject
- Added unit-tests for it
- Added unit-tests for getItem

Modified Paths:
--------------
    trunk/rpy/src/rpymodule.c
    trunk/rpy/tests/test_robj.py

Modified: trunk/rpy/src/rpymodule.c
===================================================================
--- trunk/rpy/src/rpymodule.c   2008-01-25 20:14:00 UTC (rev 401)
+++ trunk/rpy/src/rpymodule.c   2008-01-27 14:15:16 UTC (rev 402)
@@ -1475,16 +1475,91 @@
   return obj;
 }
 
+/* Get a slice: a[x:y] */
+/*FIXME: starting with Python 2.5, ilow and ihigh should probably
+ * be of type Py_ssize_t.
+ */
+static PyObject * 
+Robj_slice(PyObject *a, int ilow, int ihigh)
+{
+  SEXP robj, e, index;
+  PyObject *obj;
+  int robjLen, sliceLen, c;
+  
+  robjLen = Robj_len(a);
+  
+  if (robjLen < 0)
+    return NULL;
+  
+  if (ilow < 0) {
+    PyErr_SetString(PyExc_IndexError, 
+                   "R object index out of range (lowest index is negative)");
+    return NULL;
+    //ilow = 0;
+  } else if (ilow > robjLen) {
+    PyErr_SetString(PyExc_IndexError, 
+                   "R object index out of range (lowest index > object 
length)");
+    return NULL;
+    //ilow = robjLen;
+  }
+  if (ihigh < ilow) {
+    PyErr_SetString(PyExc_IndexError, 
+                   "R object index out of range (highest index < lowest 
index)");
+    return NULL;
+    //ihigh = ilow;
+  } else if (ihigh > robjLen) {
+    PyErr_SetString(PyExc_IndexError, 
+                   "R object index out of range (highest index > object 
length)");
+    //return NULL;
+    ihigh = robjLen;
+  }
+  sliceLen = ihigh - ilow;
+  
+  /*   if (ilow >= robjLen || ilow < 0) { */
+  /*     PyErr_SetString(PyExc_IndexError, "R object index out of range"); */
+  /*     return NULL; */
+  /*   } */
+  
+  PROTECT(index = allocVector(INTSXP, sliceLen));
+  int ii;
+  for (ii = 0; ii < sliceLen; ii++) {
+    INTEGER_POINTER(index)[ii] = ii + ilow + 1;
+  }
+  
+  PROTECT(e = allocVector(LANGSXP, 3));
+  SETCAR(e, get_item);
+  SETCAR(CDR(e), ((RobjObject *)a)->R_obj);
+  SETCAR(CDR(CDR(e)), index);
+
+  if (!(robj = do_eval_expr(e))) {
+    UNPROTECT(2);
+    return NULL;
+  }
+
+  UNPROTECT(2);
+
+  /* If there is a default mode, use it; otherwise, use the top mode. */
+  if (default_mode < 0)
+    c = TOP_MODE;
+  else
+    c = default_mode;
+  obj = to_Pyobj_with_mode(robj, c);
+  return obj;  
+}
+
+
 /* We should implement sq_slice, sq_contains ... */
 static PySequenceMethods Robj_as_sequence = {
   (inquiry)Robj_len,              /* sq_length */
-  0,                            /* sq_concat */
-  0,                            /* sq_repeat */
-  (intargfunc)Robj_item,           /* sq_item */
-  0,                            /* sq_slice */
-  (intobjargproc)Robj_ass_item,     /* sq_ass_item */
-  0,                            /* sq_ass_slice */
-  0,                            /* sq_contains */
+  0,                              /* sq_concat */
+  0,                              /* sq_repeat */
+  (ssizeargfunc)Robj_item,        /* sq_item */
+  (ssizessizeargfunc)Robj_slice,  /* sq_slice */
+  (intobjargproc)Robj_ass_item,   /* sq_ass_item */
+  0,                              /* sq_ass_slice */
+  0,                              /* sq_contains */
+  0,                              /* sq_inplace_concat */
+  0                               /* sq_inplace_repeat */
 };
 
 

Modified: trunk/rpy/tests/test_robj.py
===================================================================
--- trunk/rpy/tests/test_robj.py        2008-01-25 20:14:00 UTC (rev 401)
+++ trunk/rpy/tests/test_robj.py        2008-01-27 14:15:16 UTC (rev 402)
@@ -19,6 +19,33 @@
     def testCall(self):
         self.failUnless(callable(r.seq))
 
+    def testGetItem(self):
+        r.seq.autoconvert(NO_CONVERSION)
+        step = 10
+        pySeq = range(10, 50+step, step)
+        d = r.seq(10, 50, by = step)
+        for i in range(len(pySeq)):
+            self.assertTrue(pySeq[i] == d[i])
+        self.assertTrue(pySeq[-1] == d[-1])
+
+    def testGetItemSlice(self):
+        r.seq.autoconvert(NO_CONVERSION)
+        step = 10
+        pySeq = range(10, 50+step, step)
+        d = r.seq(10, 50, by=step)
+        self.assertTrue(pySeq[0:4] == d[0:4])
+        self.assertTrue(pySeq[:4] == d[:4])
+        self.assertTrue(pySeq[1:] == d[1:])
+        self.assertTrue(pySeq[2:5] == d[2:5])
+        # FIXME:
+        # The one below deserves attention: a one-element slice
+        # should return a one-element sequence.
+        # However, the conversion system in RPy is making it 
+        # somewhat problematic (or is it me ?)-- Laurent
+        # self.assertTrue(pySeq[0:1] == d[0:1])
+        self.assertRaises(IndexError, d.__getslice__, -1, 2)
+        self.assertRaises(IndexError, d.__getslice__, 5, 2)
+
     def testKeywordParameters(self):
         r.list.autoconvert(BASIC_CONVERSION)
         d = r.list(foo='foo', bar_foo='bar.foo',


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
rpy-list mailing list
rpy-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpy-list

Reply via email to