Revision: 548 http://rpy.svn.sourceforge.net/rpy/?rev=548&view=rev Author: lgautier Date: 2008-06-07 00:05:04 -0700 (Sat, 07 Jun 2008)
Log Message: ----------- robjects: - changed class names (now upper-case after the R prefix; e.g., RVector, RFunction, etc...) - refactored the classes: - attribute _sexp, constaining the rinterface.Sexp, is gone - classes inherit from their rinterface counterpart - a mixin class RObjectMixin provides common methods Modified Paths: -------------- branches/rpy_nextgen/rpy/robjects/__init__.py branches/rpy_nextgen/rpy/robjects/tests/testRArray.py branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py branches/rpy_nextgen/rpy/robjects/tests/testRObject.py branches/rpy_nextgen/rpy/robjects/tests/testRVector.py branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py Modified: branches/rpy_nextgen/rpy/robjects/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/__init__.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/__init__.py 2008-06-07 07:05:04 UTC (rev 548) @@ -13,26 +13,28 @@ #FIXME: close everything when leaving (check RPy for that). -def defaultRobjects2PyMapper(o): - if isinstance(o, rinterface.SexpVector): - res = Rvector(o) +def default_ri2py(o): + if isinstance(o, RObject): + res = o + elif isinstance(o, rinterface.SexpVector): + res = RVector(o) elif isinstance(o, rinterface.SexpClosure): - res = Rfunction(o) + res = RFunction(o) elif isinstance(o, rinterface.SexpEnvironment): - res = Renvironment(o) + res = REnvironment(o) elif isinstance(o, rinterface.SexpS4): res = RS4(o) else: - res = Robject(o) + res = RObject(o) return res #FIXME: clean and nice mechanism to allow user-specified mapping function #FIXME: better names for the functions -mapperR2Py = defaultRobjects2PyMapper +ri2py = default_ri2py -def defaultPy2Rinterface(o): - if isinstance(o, Robject): - return o._sexp +def default_py2ri(o): + if isinstance(o, RObject): + res = rinterface.Sexp(o) if isinstance(o, rinterface.Sexp): res = o elif isinstance(o, array.array): @@ -51,31 +53,30 @@ elif isinstance(o, str): res = rinterface.SexpVector([o, ], rinterface.STRSXP) elif isinstance(o, list): - res = r.list(*[defaultPy2RobjectsMapper(x) for x in o]) + res = r.list(*[ri2py(py2ri(x)) for x in o]) else: raise(ValueError("Nothing can be done for this type at the moment.")) return res -def defaultPy2RobjectsMapper(o): - res = defaultPy2Rinterface(o) - return mapperR2Py(res) +py2ri = default_py2ri -mapperPy2R = defaultPy2RobjectsMapper +def default_py2ro(o): + res = default_py2ri(o) + return default_ri2py(res) +py2ro = default_py2ro + + def repr_robject(o): s = r.deparse(o) s = str.join(os.linesep, s) return s -class Robject(object): +class RObjectMixin(object): name = None - _sexp = None - def __init__(self, sexp, copy=True): - self._sexp = rinterface.Sexp(sexp, copy=copy) - def __str__(self): tmp = baseNameSpaceEnv["fifo"]("") baseNameSpaceEnv["sink"](tmp) @@ -89,36 +90,36 @@ def __repr__(self): return repr_robject(self) + def typeof(self): + return super(rinterface.Sexp, self).typeof() + + def do_slot(self, name): + return super(rinterface.Sexp, self).do_slot(name) + + def rclass(self): + return baseNameSpaceEnv["class"](self) + + +class RObject(rinterface.Sexp, RObjectMixin): def __setattr__(self, name, value): if name == '_sexp': if not isinstance(value, rinterface.Sexp): raise ValueError("_attr must contain an object " +\ "that inherits from rinterface.Sexp" +\ "(not from %s)" %type(value)) - super(Robject, self).__setattr__(name, value) + super(RObject, self).__setattr__(name, value) + - def getSexp(self): - return self._sexp - def typeof(self): - return self._sexp.typeof() - - def do_slot(self, name): - return self._sexp.do_slot(name) - - def rclass(self): - return baseNameSpaceEnv["class"](self.getSexp()) - -class Rvector(Robject): +class RVector(rinterface.SexpVector, RObjectMixin): """ R vector-like object. Items in those instances can be accessed with the method "__getitem__" ("[" operator), or with the method "subset".""" def __init__(self, o): if not isinstance(o, rinterface.SexpVector): - o = mapperPy2R(o) - o = o.getSexp() - self._sexp = o + o = py2ri(o) + super(RVector, self).__init__(o) def subset(self, *args, **kwargs): @@ -134,73 +135,68 @@ #for a in args: # if not isinstance(a, Rvector): # raise(TypeError("Subset only take R vectors")) - args = [mapperPy2R(x) for x in args] + args = [py2ro(x) for x in args] for k, v in kwargs.itervalues(): - args[k] = mapperPy2R(v) + args[k] = py2ro(v) res = r["["](*([self, ] + [x for x in args]), **kwargs) return res def __getitem__(self, i): - res = self._sexp[i] + res = super(RVector, self).__getitem__(i) if isinstance(res, rinterface.Sexp): - res = mapperR2Py(res) + res = ri2py(res) return res - def __repr__(self): - return repr_robject(self) - def __add__(self, x): - res = r.get("+")(self.getSexp(), x) + res = r.get("+")(self, x) return res def __sub__(self, x): - res = r.get("-")(self.getSexp(), x) + res = r.get("-")(self, x) return res def __mul__(self, x): - res = r.get("*")(self.getSexp(), x) + res = r.get("*")(self, x) return res def __div__(self, x): - res = r.get("/")(self.getSexp(), x) + res = r.get("/")(self, x) return res def __divmod__(self, x): - res = r.get("%%")(self.getSexp(), x) + res = r.get("%%")(self, x) return res def __or__(self, x): - res = r.get("|")(self.getSexp(), x) + res = r.get("|")(self, x) return res def __and__(self, x): - res = r.get("&")(self.getSexp(), x) + res = r.get("&")(self, x) return res - def __len__(self): - return len(self.getSexp()) - def getNames(self): - res = r.names(self.getSexp()) + res = r.names(self) return res -class RArray(Rvector): +class RArray(RVector): """ An R array """ def __init__(self, o): super(RArray, self).__init__(o) - if not r["is.array"](self.getSexp())[0]: + #import pdb; pdb.set_trace() + if not r["is.array"](self)[0]: raise(TypeError("The object must be reflecting an R array")) def __getattr__(self, name): if name == 'dim': - res = r.dim(self.getSexp()) - res = mapperR2Py(res) + res = r.dim(self) + res = ri2py(res) return res def __setattr__(self, name, value): if name == 'dim': - value = mapperPy2R + value = py2ro(value) res = r["dim<-"](value) @@ -215,67 +211,53 @@ """ Number of columns """ return self.dim[1] -class DataFrame(Rvector): +class DataFrame(RVector): #FIXME: not implemented def __init__(self, o): - if not isinstance(o, rinterface.SexpVector): - o = mapperPy2R(o) - o = o.getSexp() - self._sexp = o + raise Exception("not implemented.") -class Rfunction(Robject): +class RFunction(rinterface.SexpClosure, RObjectMixin): """ An R function (aka "closure"). """ - def __init__(self, sexp): - # arbirtary python functions for v-2.1 - self._sexp = rinterface.SexpClosure(sexp) def __call__(self, *args, **kwargs): - new_args = [mapperPy2R(a).getSexp() for a in args] + new_args = [py2ri(a) for a in args] new_kwargs = {} for k, v in kwargs.iteritems(): - new_kwargs[k] = mapperPy2R(v).getSexp() - res = self.getSexp()(*new_args, **new_kwargs) - res = mapperR2Py(res) + new_kwargs[k] = py2ri(v) + res = super(RFunction, self).__call__(*new_args, **new_kwargs) + res = ri2py(res) return res #def getSexp(self): # return super(rinterface.SexpClosure, self).__init__(self) -class Renvironment(Robject): +class REnvironment(rinterface.SexpEnvironment, RObjectMixin): """ An R environement. """ def __init__(self, o=None): if o is None: o = rinterface.baseNameSpaceEnv["new.env"](hash=rinterface.SexpVector([True, ], rinterface.LGLSXP)) - self._sexp = rinterface.SexpEnvironment(o) + super(REnvironment, self).__init__(o) def __getitem__(self, item): - res = self._sexp[item] - res = mapperR2Py(res) + res = super(REnvironment, self).__getitem__(item) + res = ri2py(res) return res def __setitem__(self, item, value): - robj = mapperPy2R(value) - self._sexp[item] = robj.getSexp() + robj = py2ro(value) + super(REnvironment, self).__setitem__(item, robj) - def __iter__(self): - return iter(self._sexp) - def get(self, item): - res = self.getSexp().get(item) - res = mapperR2Py(res) + res = super(REnvironment, self).get(item) + res = ri2py(res) return res -class RS4(Robject): - def __init__(self, o): - if (isinstance(o, rinterface.SexpS4)): - self._sexp = o - else: - raise(ValueError("Cannot instantiate")) +class RS4(rinterface.SexpS4, RObjectMixin): def __getattr__(self, attr): res = r.get("@")(self, attr) @@ -297,7 +279,7 @@ def __getitem__(self, item): res = rinterface.globalEnv.get(item) - res = mapperR2Py(res) + res = ri2py(res) return res #FIXME: check that this is properly working @@ -317,6 +299,6 @@ r = R() -globalEnv = mapperR2Py(rinterface.globalEnv) -baseNameSpaceEnv = mapperR2Py(rinterface.baseNameSpaceEnv) +globalEnv = ri2py(rinterface.globalEnv) +baseNameSpaceEnv = ri2py(rinterface.baseNameSpaceEnv) Modified: branches/rpy_nextgen/rpy/robjects/tests/testRArray.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRArray.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/tests/testRArray.py 2008-06-07 07:05:04 UTC (rev 548) @@ -10,7 +10,8 @@ self.assertRaises(TypeError, robjects.RArray, letters) m = robjects.r.matrix(1, nrow=5, ncol=3) a = robjects.RArray(m) - + # only tests that it runs. + def testDim(self): m = robjects.r.matrix(1, nrow=5, ncol=3) a = robjects.RArray(m) Modified: branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py 2008-06-07 07:05:04 UTC (rev 548) @@ -5,12 +5,12 @@ class REnvironmentTestCase(unittest.TestCase): def testNew(self): - env = robjects.Renvironment() - self.assertEquals(rinterface.ENVSXP, env.getSexp().typeof()) - self.assertRaises(ValueError, robjects.Renvironment, 'a') + env = robjects.REnvironment() + self.assertEquals(rinterface.ENVSXP, env.typeof()) + self.assertRaises(ValueError, robjects.REnvironment, 'a') def testSetItem(self): - env = robjects.Renvironment() + env = robjects.REnvironment() env['a'] = 123 self.assertTrue('a' in env) Modified: branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py 2008-06-07 07:05:04 UTC (rev 548) @@ -6,19 +6,19 @@ class RFunctionTestCase(unittest.TestCase): def testNew(self): identical = rinterface.baseNameSpaceEnv["identical"] - self.assertRaises(ValueError, robjects.Rfunction, 'a') + self.assertRaises(ValueError, robjects.RFunction, 'a') ri_f = rinterface.baseNameSpaceEnv.get('help') - ro_f = robjects.Rfunction(ri_f) + ro_f = robjects.RFunction(ri_f) - self.assertTrue(identical(ri_f, ro_f.getSexp())) + self.assertTrue(identical(ri_f, ro_f)) def testCall(self): ri_f = rinterface.baseNameSpaceEnv.get('sum') - ro_f = robjects.Rfunction(ri_f) + ro_f = robjects.RFunction(ri_f) - ro_v = robjects.Rvector(array.array('i', [1,2,3])) + ro_v = robjects.RVector(array.array('i', [1,2,3])) s = ro_f(ro_v) Modified: branches/rpy_nextgen/rpy/robjects/tests/testRObject.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRObject.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/tests/testRObject.py 2008-06-07 07:05:04 UTC (rev 548) @@ -8,12 +8,12 @@ identical = rinterface.baseNameSpaceEnv["identical"] py_a = array.array('i', [1,2,3]) - self.assertRaises(ValueError, robjects.Robject, py_a) + self.assertRaises(ValueError, robjects.RObject, py_a) ri_v = rinterface.SexpVector(py_a, rinterface.INTSXP) - ro_v = robjects.Robject(ri_v) + ro_v = robjects.RObject(ri_v) - self.assertTrue(identical(ro_v._sexp, ri_v)[0]) + self.assertTrue(identical(ro_v, ri_v)[0]) #FIXME: why isn't this working ? #del(ri_v) Modified: branches/rpy_nextgen/rpy/robjects/tests/testRVector.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRVector.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/tests/testRVector.py 2008-06-07 07:05:04 UTC (rev 548) @@ -5,18 +5,18 @@ rlist = robjects.baseNameSpaceEnv["list"] -class RvectorTestCase(unittest.TestCase): +class RVectorTestCase(unittest.TestCase): def testNew(self): identical = ri.baseNameSpaceEnv["identical"] py_a = array.array('i', [1,2,3]) - ro_v = robjects.Rvector(py_a) + ro_v = robjects.RVector(py_a) self.assertEquals(ro_v.typeof(), ri.INTSXP) ri_v = ri.SexpVector(py_a, ri.INTSXP) - ro_v = robjects.Rvector(ri_v) + ro_v = robjects.RVector(ri_v) - self.assertTrue(identical(ro_v._sexp, ri_v)[0]) + self.assertTrue(identical(ro_v, ri_v)[0]) del(ri_v) self.assertEquals(ri.INTSXP, ro_v.typeof()) @@ -37,14 +37,14 @@ seq_R = robjects.baseNameSpaceEnv["seq"] mySeq = seq_R(0, 10) # R indexing starts at one - myIndex = robjects.Rvector(array.array('i', range(1, 11, 2))) + myIndex = robjects.RVector(array.array('i', range(1, 11, 2))) mySubset = mySeq.subset(myIndex) for i, si in enumerate(myIndex): self.assertEquals(mySeq[si-1], mySubset[i]) # recycling rule - v = robjects.Rvector(array.array('i', range(1, 23))) + v = robjects.RVector(array.array('i', range(1, 23))) m = robjects.r.matrix(v, ncol = 2) col = m.subset(True, 1) self.assertEquals(11, len(col)) @@ -68,7 +68,7 @@ self.assertTrue(idem("foo", mylist[1])) def testGetNames(self): - vec = robjects.Rvector(array.array('i', [1,2,3])) + vec = robjects.RVector(array.array('i', [1,2,3])) v_names = [robjects.baseNameSpaceEnv["letters"][x] for x in (0,1,2)] #FIXME: simplify this r_names = robjects.baseNameSpaceEnv["c"](*v_names) @@ -77,7 +77,7 @@ self.assertEquals(v_names[i], vec.getNames()[i]) def suite(): - suite = unittest.TestLoader().loadTestsFromTestCase(RvectorTestCase) + suite = unittest.TestLoader().loadTestsFromTestCase(RVectorTestCase) return suite if __name__ == '__main__': Modified: branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py 2008-06-07 07:01:08 UTC (rev 547) +++ branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py 2008-06-07 07:05:04 UTC (rev 548) @@ -7,7 +7,7 @@ def testGetItem(self): letters_R = robjects.r["letters"] - self.assertTrue(isinstance(letters_R, robjects.Rvector)) + self.assertTrue(isinstance(letters_R, robjects.RVector)) letters = (('a', 0), ('b', 1), ('c', 2), ('x', 23), ('y', 24), ('z', 25)) for l, i in letters: self.assertTrue(letters_R[i] == l) @@ -22,42 +22,65 @@ for i, li in enumerate(myList): self.assertEquals(i, myList[i][0]) - - def testMapperR2Python(self): + def testMapperR2Python_string(self): sexp = rinterface.globalEnv.get("letters") - ob = robjects.defaultRobjects2PyMapper(sexp) + ob = robjects.default_ri2py(sexp) self.assertTrue(isinstance(ob, - robjects.Rvector)) + robjects.RVector)) + def testMapperR2Python_boolean(self): sexp = rinterface.globalEnv.get("T") - ob = robjects.defaultRobjects2PyMapper(sexp) + ob = robjects.default_ri2py(sexp) self.assertTrue(isinstance(ob, - robjects.Rvector)) + robjects.RVector)) + def testMapperR2Python_function(self): sexp = rinterface.globalEnv.get("plot") - ob = robjects.defaultRobjects2PyMapper(sexp) + ob = robjects.default_ri2py(sexp) self.assertTrue(isinstance(ob, - robjects.Rfunction)) + robjects.RFunction)) + def testMapperR2Python_environment(self): sexp = rinterface.globalEnv.get(".GlobalEnv") - self.assertTrue(isinstance(robjects.defaultRobjects2PyMapper(sexp), robjects.Renvironment)) + self.assertTrue(isinstance(robjects.default_ri2py(sexp), + robjects.Renvironment)) #FIXME: test S4 - def testMapperPy2R(self): + def testMapperPy2R_integer(self): py = 1 - rob = robjects.defaultPy2RobjectsMapper(py) - self.assertTrue(isinstance(rob, robjects.Rvector)) - + rob = robjects.default_py2ro(py) + self.assertTrue(isinstance(rob, robjects.RVector)) + + def testMapperPy2R_boolean(self): py = True - rob = robjects.defaultPy2RobjectsMapper(py) - self.assertTrue(isinstance(rob, robjects.Rvector)) + rob = robjects.default_py2ro(py) + self.assertTrue(isinstance(rob, robjects.RVector)) self.assertEquals(rinterface.LGLSXP, rob.typeof()) #FIXME: more tests + def testOverride_ri2py(self): + class Density(object): + def __init__(self, x): + self._x = x + + def f(obj): + pyobj = robjects.default_ri2py(obj) + inherits = rinterface.baseNameSpaceEnv["inherits"] + classname = rinterface.SexpVector(["density", ], + rinterface.STRSXP) + if inherits(pyobj, classname)[0]: + pyobj = Density(pyobj) + return pyobj + robjects.ri2py = f + x = robjects.r.rnorm(100) + d = robjects.r.density(x) + + self.assertTrue(isinstance(d, Density)) + def suite(): suite = unittest.TestLoader().loadTestsFromTestCase(RObjectTestCase) return suite This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ rpy-list mailing list rpy-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rpy-list