Revision: 504 http://rpy.svn.sourceforge.net/rpy/?rev=504&view=rev Author: lgautier Date: 2008-04-28 02:56:55 -0700 (Mon, 28 Apr 2008)
Log Message: ----------- rinterface: - Added array to map R's SEXP types to their short names - Added Python-level function to get the short name for a given SEXP type - Added test of SEXP validity when instanciating a vector (and fixed the pending unit test) - Fixes in existing tests - Proper type casting for *_init functions - Added macros RPY_SEXP and RPY_COUNT robjects: - Fixed robjects to accomodate changes in rinterface (that lead to the simplification of the ugly idiosyncratic self._sexp[0]) - Added test modules for RObject and REnvironment - Edited the other tests others: - Updated demos/radmin.py to the recent changes Modified Paths: -------------- branches/rpy_nextgen/README branches/rpy_nextgen/demos/radmin.py branches/rpy_nextgen/rpy/rinterface/array.c branches/rpy_nextgen/rpy/rinterface/rinterface.c branches/rpy_nextgen/rpy/rinterface/rinterface.h branches/rpy_nextgen/rpy/rinterface/tests/test_SexpVector.py branches/rpy_nextgen/rpy/robjects/__init__.py branches/rpy_nextgen/rpy/robjects/tests/__init__.py branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py branches/rpy_nextgen/rpy/robjects/tests/testRVector.py branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py Added Paths: ----------- branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py branches/rpy_nextgen/rpy/robjects/tests/testRObject.py Removed Paths: ------------- branches/rpy_nextgen/rpy/rinterface/__init__.py Modified: branches/rpy_nextgen/README =================================================================== --- branches/rpy_nextgen/README 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/README 2008-04-28 09:56:55 UTC (rev 504) @@ -1,7 +1,7 @@ -All this is under development. +All this is under development, getting quickly to an alpha stage. -The development is currently done with Python 2.5.1 and R-2.7.0-devel +The development is currently done with Python 2.5.2 and R-2.7.0-devel Compatibility with Python 2.4.x should be ok, now or later (might already be ok). Modified: branches/rpy_nextgen/demos/radmin.py =================================================================== --- branches/rpy_nextgen/demos/radmin.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/demos/radmin.py 2008-04-28 09:56:55 UTC (rev 504) @@ -1,3 +1,8 @@ +""" +A front-end to R's packags, and help/documentation systems +""" + +import os import pygtk pygtk.require('2.0') import gtk @@ -63,7 +68,7 @@ installedLibraries = robjects.r["installed.packages"]() nrows = robjects.r.nrow(installedLibraries)[0] ncols = robjects.r.ncol(installedLibraries)[0] - for i in range(1, nrows._sexp[0]+1): + for i in range(1, nrows + 1): row = [] pack = installedLibraries.subset(i, 1)._sexp[0] row.append(pack) @@ -114,6 +119,8 @@ PACKAGE_I = 0 ITEM_I = 1 + _vignettes = None + def __init__(self): super(VignetteExplorer, self).__init__() self._table = gtk.ListStore(str, str, str) @@ -156,10 +163,12 @@ def updateKnownVignettes(self): self._table.clear() + vignettes = robjects.r["vignette"]().subset("results")[0] - nrows = robjects.r.nrow(vignettes)[0] - ncols = robjects.r.ncol(vignettes)[0] - for i in range(1, nrows._sexp[0]+1): + + nrows = robjects.baseNameSpaceEnv["nrow"](vignettes)[0] + ncols = robjects.baseNameSpaceEnv["ncol"](vignettes)[0] + for i in range(1, nrows + 1): row = [] pack = vignettes.subset(i, 1)._sexp[0] row.append(pack) @@ -168,6 +177,8 @@ pack = vignettes.subset(i, 4)._sexp[0] row.append(pack) self._table.append(row) + + self._vignettes = vignettes def viewAction(self, widget, data=None): # Get the selection in the gtk.TreeView @@ -179,9 +190,14 @@ self.PACKAGE_I) vigName = self._table.get_value(selection_iter, self.ITEM_I) - robjects.r.vignette(vigName, package = packName) - + + pdffile = robjects.r.vignette(vigName, package = packName) + pdffile = pdffile.subset("file")[0][0] + pdfviewer = robjects.baseNameSpaceEnv["options"]("pdfviewer")[0][0] + pid = os.spawnl(os.P_NOWAIT, pdfviewer, pdffile) + + class GraphicalDeviceExplorer(gtk.VBox): def __init__(self): @@ -223,17 +239,17 @@ self._table.clear() devices = robjects.r["dev.list"]() names = robjects.r["names"](devices) - current_device = robjects.r["dev.cur"]()._sexp[0] + current_device = robjects.r["dev.cur"]()[0] try: nrows = len(devices) except: return for dev, name in itertools.izip(devices, names): - if current_device == dev._sexp[0]: + if current_device == dev[0]: cur = "X" else: cur = "" - row = [cur, dev._sexp[0], name._sexp[0], ""] + row = [cur, dev[0], name[0], ""] self._table.append(row) def searchOpenedDevices(self, widget, data = None): @@ -293,7 +309,7 @@ #import pdb; pdb.set_trace() nrows = robjects.r.nrow(matches)[0] ncols = robjects.r.ncol(matches)[0] - for i in range(1, nrows._sexp[0]+1): + for i in range(1, nrows + 1): row = [] pack = matches.subset(i, 1)._sexp[0] row.append(pack) Deleted: branches/rpy_nextgen/rpy/rinterface/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/rinterface/__init__.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/rinterface/__init__.py 2008-04-28 09:56:55 UTC (rev 504) @@ -1,6 +0,0 @@ -# This file is automatically generated when installing rpy2 -# For permanent changes, edit __init__py.in in the source directory. - -import os - -from rinterface import * Modified: branches/rpy_nextgen/rpy/rinterface/array.c =================================================================== --- branches/rpy_nextgen/rpy/rinterface/array.c 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/rinterface/array.c 2008-04-28 09:56:55 UTC (rev 504) @@ -99,9 +99,9 @@ PyObject* -array_struct_get(SexpObject *self) +array_struct_get(PySexpObject *self) { - SEXP sexp = self->sexp; + SEXP sexp = RPY_SEXP(self); if (!sexp) { PyErr_SetString(PyExc_AttributeError, "Null sexp"); return NULL; Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.c =================================================================== --- branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-04-28 09:56:55 UTC (rev 504) @@ -79,6 +79,8 @@ typedef intobjargproc ssizeobjargproc; #endif +static const int maxValidSexpType = 99; +static char **validSexpType; //FIXME: see the details of error handling static PyObject *ErrorObject; @@ -147,9 +149,9 @@ embeddedR_isInitialized = PyBool_FromLong((long)1); - RPY_GETSEXP(globalEnv) = R_GlobalEnv; + RPY_SEXP(globalEnv) = R_GlobalEnv; - RPY_GETSEXP(baseNameSpaceEnv) = R_BaseNamespace; + RPY_SEXP(baseNameSpaceEnv) = R_BaseNamespace; PyObject *res = PyInt_FromLong(status); @@ -183,8 +185,8 @@ /* */ Rf_endEmbeddedR((int)fatal); - RPY_GETSEXP(globalEnv) = R_EmptyEnv; - RPY_GETSEXP(baseNameSpaceEnv) = R_EmptyEnv; + RPY_SEXP(globalEnv) = R_EmptyEnv; + RPY_SEXP(baseNameSpaceEnv) = R_EmptyEnv; Py_RETURN_NONE; } @@ -249,16 +251,16 @@ RPY_DECREF(self); #ifdef RPY_VERBOSE - printf("%p: sexp count is %i\n", self, RPY_GETCOUNT(self)); + printf("%p: sexp count is %i\n", self, RPY_COUNT(self)); #endif - if ((RPY_GETCOUNT(self) == 0) && RPY_GETSEXP(self)) { + if ((RPY_COUNT(self) == 0) && RPY_SEXP(self)) { #ifdef RPY_VERBOSE printf("freeing SEXP resources..."); #endif - if (RPY_GETSEXP(self) != R_NilValue) { - R_ReleaseObject(RPY_GETSEXP(self)); + if (RPY_SEXP(self) != R_NilValue) { + R_ReleaseObject(RPY_SEXP(self)); } free(self->sObj); ////self->ob_type->tp_free((PyObject*)self); @@ -274,7 +276,7 @@ Sexp_repr(PyObject *self) { //FIXME: make sure this is making any sense - SEXP sexp = RPY_GETSEXP((PySexpObject *)self); + SEXP sexp = RPY_SEXP((PySexpObject *)self); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL; @@ -289,7 +291,7 @@ static PyObject* Sexp_typeof(PyObject *self) { - SEXP sexp = RPY_GETSEXP(((PySexpObject*)self)); + SEXP sexp = RPY_SEXP(((PySexpObject*)self)); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL;; @@ -304,7 +306,7 @@ static PyObject* Sexp_do_slot(PyObject *self, PyObject *name) { - SEXP sexp = RPY_GETSEXP(((PySexpObject*)self)); + SEXP sexp = RPY_SEXP(((PySexpObject*)self)); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL;; @@ -331,6 +333,7 @@ the method.\n"); + static PyMethodDef Sexp_methods[] = { {"typeof", (PyCFunction)Sexp_typeof, METH_NOARGS, Sexp_typeof_doc}, @@ -430,8 +433,8 @@ if (! self->sObj) PyErr_NoMemory(); - RPY_GETCOUNT(self) = 1; - RPY_GETSEXP(self) = R_NilValue; + RPY_COUNT(self) = 1; + RPY_SEXP(self) = R_NilValue; #ifdef RPY_VERBOSE printf("done.\n"); @@ -472,11 +475,11 @@ if (PyObject_IsTrue(copy)) { SEXP oldSexp; - oldSexp = RPY_GETSEXP((PySexpObject *)sourceObject); - RPY_GETSEXP(self) = oldSexp; + oldSexp = RPY_SEXP((PySexpObject *)sourceObject); + RPY_SEXP(self) = oldSexp; RPY_INCREF(self); #ifdef RPY_VERBOSE - printf("%p: sexp count is increased to %i.\n", self, RPY_GETCOUNT(self)); + printf("%p: sexp count is increased to %i.\n", self, RPY_COUNT(self)); #endif } else { @@ -571,7 +574,7 @@ /* A SEXP with the function to call and the arguments and keywords. */ PROTECT(c_R = call_R = allocList(largs+lkwds+1)); SET_TYPEOF(c_R, LANGSXP); - fun_R = RPY_GETSEXP((PySexpObject *)self); + fun_R = RPY_SEXP((PySexpObject *)self); if (! fun_R) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); goto fail; @@ -591,7 +594,7 @@ Py_DECREF(tmp_obj); goto fail; } - tmp_R = RPY_GETSEXP((PySexpObject *)tmp_obj); + tmp_R = RPY_SEXP((PySexpObject *)tmp_obj); if (! tmp_R) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); Py_DECREF(tmp_obj); @@ -633,7 +636,7 @@ goto fail; } Py_DECREF(tmp_obj); - tmp_R = RPY_GETSEXP((PySexpObject *)argValue); + tmp_R = RPY_SEXP((PySexpObject *)argValue); if (! tmp_R) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); Py_DECREF(tmp_obj); @@ -680,7 +683,7 @@ Sexp_closureEnv(PyObject *self) { SEXP closureEnv, sexp; - sexp = RPY_GETSEXP((PySexpObject*)self); + sexp = RPY_SEXP((PySexpObject*)self); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL; @@ -753,7 +756,7 @@ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ - ClosureSexp_init, /*tp_init*/ + (initproc)ClosureSexp_init, /*tp_init*/ 0, /*tp_alloc*/ 0,//Sexp_new, /*tp_new*/ 0, /*tp_free*/ @@ -765,7 +768,6 @@ ClosureSexp_init(PySexpObject *self, PyObject *args, PyObject *kwds) { PyObject *object; - int sexptype = -1; PyObject *copy; static char *kwlist[] = {"sexpclos", "copy", NULL}; //FIXME: handle the copy argument @@ -797,7 +799,7 @@ { Py_ssize_t len; //FIXME: sanity checks. - SEXP sexp = RPY_GETSEXP((PySexpObject *)object); + SEXP sexp = RPY_SEXP((PySexpObject *)object); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return -1; @@ -812,7 +814,7 @@ { PyObject* res; R_len_t i_R; - SEXP *sexp = &(RPY_GETSEXP((PySexpObject *)object)); + SEXP *sexp = &(RPY_SEXP((PySexpObject *)object)); if (! sexp) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); @@ -880,7 +882,7 @@ return -1; } - SEXP *sexp = &(RPY_GETSEXP((PySexpObject *)object)); + SEXP *sexp = &(RPY_SEXP((PySexpObject *)object)); if (i >= GET_LENGTH(*sexp)) { PyErr_Format(PyExc_IndexError, "Index out of range."); return -1; @@ -897,7 +899,7 @@ "type 'Sexp_Type'."); return -1; } - SEXP *sexp_val = &(RPY_GETSEXP((PySexpObject *)val)); + SEXP *sexp_val = &(RPY_SEXP((PySexpObject *)val)); if (! sexp_val) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return -1; @@ -1054,6 +1056,12 @@ &PyBool_Type, ©)) { return -1; } + + if ((sexptype < 0) || (sexptype > maxValidSexpType) || + (! validSexpType[sexptype])) { + PyErr_Format(PyExc_ValueError, "Invalid SEXP type."); + return -1; + } if (PyObject_IsInstance(object, (PyObject*)&VectorSexp_Type)) { @@ -1070,7 +1078,7 @@ PyErr_Format(PyExc_ValueError, "Missing type."); return -1; } - RPY_GETSEXP(self) = newSEXP(object, sexptype); + RPY_SEXP(self) = newSEXP(object, sexptype); } #ifdef RPY_VERBOSE printf("done.\n"); @@ -1092,7 +1100,7 @@ return NULL; } - const SEXP rho_R = RPY_GETSEXP((PySexpObject *)self); + const SEXP rho_R = RPY_SEXP((PySexpObject *)self); if (! rho_R) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL; @@ -1134,7 +1142,7 @@ name = PyString_AsString(key); - SEXP rho_R = RPY_GETSEXP((PySexpObject *)self); + SEXP rho_R = RPY_SEXP((PySexpObject *)self); if (! rho_R) { PyErr_Format(PyExc_ValueError, "NULL SEXP."); return NULL; @@ -1172,14 +1180,14 @@ name = PyString_AsString(key); - SEXP rho_R = RPY_GETSEXP((PySexpObject *)self); + SEXP rho_R = RPY_SEXP((PySexpObject *)self); if (! rho_R) { PyErr_Format(PyExc_ValueError, "The environment has NULL SEXP."); return -1; } SEXP sexp_copy; - SEXP sexp = RPY_GETSEXP((PySexpObject *)value); + SEXP sexp = RPY_SEXP((PySexpObject *)value); if (! sexp) { PyErr_Format(PyExc_ValueError, "The value has NULL SEXP."); return -1; @@ -1193,7 +1201,7 @@ static Py_ssize_t EnvironmentSexp_length(PyObject *self) { - SEXP rho_R = RPY_GETSEXP((PySexpObject *)self); + SEXP rho_R = RPY_SEXP((PySexpObject *)self); if (! rho_R) { PyErr_Format(PyExc_ValueError, "The environment has NULL SEXP."); return -1; @@ -1205,7 +1213,7 @@ return len; } -static PyMappingMethods EnvironmentSexp_mappignMethods = { +static PyMappingMethods EnvironmentSexp_mappingMethods = { (lenfunc)EnvironmentSexp_length, /* mp_length */ (binaryfunc)EnvironmentSexp_subscript, /* mp_subscript */ (objobjargproc)EnvironmentSexp_ass_subscript /* mp_ass_subscript */ @@ -1214,7 +1222,7 @@ static PyObject* EnvironmentSexp_iter(PyObject *sexpEnvironment) { - SEXP rho_R = RPY_GETSEXP((PySexpObject *)sexpEnvironment); + SEXP rho_R = RPY_SEXP((PySexpObject *)sexpEnvironment); if (! rho_R) { PyErr_Format(PyExc_ValueError, "The environment has NULL SEXP."); @@ -1267,7 +1275,7 @@ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ - &EnvironmentSexp_mappignMethods, /*tp_as_mapping*/ + &EnvironmentSexp_mappingMethods,/*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0,//Sexp_str, /*tp_str*/ @@ -1290,7 +1298,7 @@ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ - EnvironmentSexp_init, /*tp_init*/ + (initproc)EnvironmentSexp_init, /*tp_init*/ 0, /*tp_alloc*/ //FIXME: add new method 0, //EnvironmentSexp_new, /*tp_new*/ @@ -1302,7 +1310,6 @@ EnvironmentSexp_init(PySexpObject *self, PyObject *args, PyObject *kwds) { PyObject *object; - int sexptype = -1; PyObject *copy; static char *kwlist[] = {"sexpenv", "copy", NULL}; //FIXME: handle the copy argument @@ -1442,7 +1449,7 @@ return NULL; } //PyObject_Init(&object, &ClosureSexp_Type); - RPY_GETSEXP(object) = sexp_ok; + RPY_SEXP(object) = sexp_ok; //FIXME: Increment reference ? //Py_INCREF(object); return object; @@ -1531,7 +1538,7 @@ "type 'Sexp_Type'."); return NULL; } - SET_ELEMENT(sexp, i, RPY_GETSEXP((PySexpObject *)item)); + SET_ELEMENT(sexp, i, RPY_SEXP((PySexpObject *)item)); Py_DECREF(item); } } @@ -1564,7 +1571,7 @@ /* --- Find a variable in an environment --- */ - +//FIXME: is this any longer useful ? static PySexpObject* EmbeddedR_findVar(PyObject *self, PyObject *args) { @@ -1589,9 +1596,31 @@ PyDoc_STRVAR(EmbeddedR_findVar_doc, "Find a variable in R's .GlobalEnv."); +static PyObject* +EmbeddedR_sexpType(PyObject *self, PyObject *args) +{ + int sexp_i; + if (! PyArg_ParseTuple(args, "i", &sexp_i)) { + //PyErr_Format(PyExc_LookupError, "Value should be an integer"); + return NULL; + } + const char *sexp_type = validSexpType[sexp_i]; + + if ((sexp_i < 0) || (sexp_i > maxValidSexpType) || (! sexp_type)) { + + PyErr_Format(PyExc_LookupError, "'%i' is not a valid SEXP value.", sexp_i); + return NULL; + } + //FIXME: store python strings when initializing validSexpType instead + PyObject *res = PyString_FromString(sexp_type); + return res; + +} + + /* --- List of functions defined in the module --- */ static PyMethodDef EmbeddedR_methods[] = { @@ -1603,6 +1632,8 @@ EmbeddedR_setWriteConsole_doc}, {"findVarEmbeddedR", (PyCFunction)EmbeddedR_findVar, METH_VARARGS, EmbeddedR_findVar_doc}, + {"sexpTypeEmbeddedR", (PyCFunction)EmbeddedR_sexpType, METH_VARARGS, + "Return the SEXP name tag corresponding to an integer."}, {NULL, NULL} /* sentinel */ }; @@ -1692,7 +1723,7 @@ Py_DECREF(pyargstup); if (PyObject_IsInstance((PyObject*)pyres, (PyObject*)&Sexp_Type)) { - res = RPY_GETSEXP((PySexpObject*)pyres); + res = RPY_SEXP((PySexpObject*)pyres); } else { res = mkPyObject(pyres); @@ -1711,7 +1742,10 @@ /* --- Initialize the module ---*/ -#define ADD_INT_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name) +#define ADD_INT_CONSTANT(module, name) \ + PyModule_AddIntConstant(module, #name, name) +#define ADD_VALID_SEXP(name) \ + validSexpType[name] = #name PyMODINIT_FUNC @@ -1761,7 +1795,7 @@ globalEnv = (PySexpObject *)Sexp_new(&EnvironmentSexp_Type, Py_None, Py_None); - RPY_GETSEXP(globalEnv) = R_EmptyEnv; + RPY_SEXP(globalEnv) = R_EmptyEnv; //SexpObject *sObj = globalEnv->sObj; //SEXP sexp = sObj->sexp; //sexp = R_EmptyEnv; @@ -1773,36 +1807,65 @@ baseNameSpaceEnv = (PySexpObject*)Sexp_new(&EnvironmentSexp_Type, Py_None, Py_None); - RPY_GETSEXP(baseNameSpaceEnv) = R_EmptyEnv; + RPY_SEXP(baseNameSpaceEnv) = R_EmptyEnv; if (PyDict_SetItemString(d, "baseNameSpaceEnv", (PyObject *)baseNameSpaceEnv) < 0) return; /* //FIXME: DECREF ? */ /* Py_DECREF(baseNameSpaceEnv); */ + /* Add SXP types */ + validSexpType = calloc(maxValidSexpType, sizeof(char *)); + if (! validSexpType) { + PyErr_NoMemory(); + return; + } ADD_INT_CONSTANT(m, NILSXP); + ADD_VALID_SEXP(NILSXP); ADD_INT_CONSTANT(m, SYMSXP); + ADD_VALID_SEXP(SYMSXP); ADD_INT_CONSTANT(m, LISTSXP); + ADD_VALID_SEXP(LISTSXP); ADD_INT_CONSTANT(m, CLOSXP); + ADD_VALID_SEXP(CLOSXP); ADD_INT_CONSTANT(m, ENVSXP); + ADD_VALID_SEXP(ENVSXP); ADD_INT_CONSTANT(m, PROMSXP); + ADD_VALID_SEXP(PROMSXP); ADD_INT_CONSTANT(m, LANGSXP); + ADD_VALID_SEXP(LANGSXP); ADD_INT_CONSTANT(m, SPECIALSXP); + ADD_VALID_SEXP(SPECIALSXP); ADD_INT_CONSTANT(m, BUILTINSXP); + ADD_VALID_SEXP(BUILTINSXP); ADD_INT_CONSTANT(m, CHARSXP); + ADD_VALID_SEXP(CHARSXP); ADD_INT_CONSTANT(m, STRSXP); + ADD_VALID_SEXP(STRSXP); ADD_INT_CONSTANT(m, LGLSXP); + ADD_VALID_SEXP(LGLSXP); ADD_INT_CONSTANT(m, INTSXP); + ADD_VALID_SEXP(INTSXP); ADD_INT_CONSTANT(m, REALSXP); + ADD_VALID_SEXP(REALSXP); ADD_INT_CONSTANT(m, CPLXSXP); + ADD_VALID_SEXP(CPLXSXP); ADD_INT_CONSTANT(m, DOTSXP); + ADD_VALID_SEXP(DOTSXP); ADD_INT_CONSTANT(m, ANYSXP); + ADD_VALID_SEXP(ANYSXP); ADD_INT_CONSTANT(m, VECSXP); + ADD_VALID_SEXP(VECSXP); ADD_INT_CONSTANT(m, EXPRSXP); + ADD_VALID_SEXP(EXPRSXP); ADD_INT_CONSTANT(m, BCODESXP); + ADD_VALID_SEXP(BCODESXP); ADD_INT_CONSTANT(m, EXTPTRSXP); + ADD_VALID_SEXP(EXTPTRSXP); ADD_INT_CONSTANT(m, RAWSXP); + ADD_VALID_SEXP(RAWSXP); ADD_INT_CONSTANT(m, S4SXP); + ADD_VALID_SEXP(S4SXP); /* longuest integer for R indexes */ ADD_INT_CONSTANT(m, R_LEN_T_MAX); @@ -1825,7 +1888,7 @@ PySexpObject *na_string = (PySexpObject *)Sexp_new(&VectorSexp_Type, Py_None, Py_None); - RPY_GETSEXP(na_string) = NA_STRING; + RPY_SEXP(na_string) = NA_STRING; if (PyDict_SetItemString(d, "NA_STRING", (PyObject *)na_string) < 0) return; /* //FIXME: DECREF ? */ Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.h =================================================================== --- branches/rpy_nextgen/rpy/rinterface/rinterface.h 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/rinterface/rinterface.h 2008-04-28 09:56:55 UTC (rev 504) @@ -24,9 +24,9 @@ } PySexpObject; -#define RPY_GETCOUNT(obj) (((obj)->sObj)->count) -#define RPY_GETSEXP(obj) (((obj)->sObj)->sexp) -//#define RPY_GETSEXP(obj) ((obj)->sexp) +#define RPY_COUNT(obj) (((obj)->sObj)->count) +#define RPY_SEXP(obj) (((obj)->sObj)->sexp) +//#define RPY_SEXP(obj) ((obj)->sexp) #define RPY_INCREF(obj) ((obj->sObj)->count++) #define RPY_DECREF(obj) ((obj->sObj)->count--) Modified: branches/rpy_nextgen/rpy/rinterface/tests/test_SexpVector.py =================================================================== --- branches/rpy_nextgen/rpy/rinterface/tests/test_SexpVector.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/rinterface/tests/test_SexpVector.py 2008-04-28 09:56:55 UTC (rev 504) @@ -1,4 +1,5 @@ import unittest +import sys import rpy2.rinterface as rinterface try: @@ -87,8 +88,8 @@ def testNew_InvalidType(self): - self.assertTrue(False) #FIXME: invalid type causes a segfault self.assertRaises(ValueError, rinterface.SexpVector, [1, ], -1) + self.assertRaises(ValueError, rinterface.SexpVector, [1, ], 250) def testGetItem(self): letters_R = rinterface.globalEnv.get("letters") @@ -97,21 +98,24 @@ for l, i in letters: self.assertTrue(letters_R[i] == l) - as_list_R = rinterface.globalEnv.get("as.list") + Rlist = rinterface.globalEnv.get("list") seq_R = rinterface.globalEnv.get("seq") mySeq = seq_R(rinterface.SexpVector([0, ], rinterface.INTSXP), rinterface.SexpVector([10, ], rinterface.INTSXP)) - myList = as_list_R(mySeq) - - for i, li in enumerate(myList): - self.assertEquals(i, myList[i][0]) + myList = Rlist(s=mySeq, l=letters_R) + idem = rinterface.globalEnv.get("identical") + self.assertTrue(idem(mySeq, myList[0])) + self.assertTrue(idem(letters_R, myList[1])) + def testGetItemOutOfBound(self): myVec = rinterface.SexpVector([0, 1, 2, 3, 4, 5], rinterface.INTSXP) self.assertRaises(IndexError, myVec.__getitem__, 10) - self.assertRaises(IndexError, myVec.__getitem__, rinterface.R_LEN_T_MAX+1) + if (sys.maxint > rinterface.R_LEN_T_MAX): + self.assertRaises(IndexError, myVec.__getitem__, + rinterface.R_LEN_T_MAX+1) def testAssignItemDifferentType(self): c_R = rinterface.globalEnv.get("c") Modified: branches/rpy_nextgen/rpy/robjects/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/__init__.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/robjects/__init__.py 2008-04-28 09:56:55 UTC (rev 504) @@ -65,15 +65,16 @@ def repr_robject(o): s = r.deparse(o) - s = str.join(os.linesep, o) + s = str.join(os.linesep, s) return s -class Robject(rinterface.Sexp): +class Robject(object): name = None + _sexp = None def __init__(self, sexp, copy=True): - super(Robject, self).__init__(sexp, copy=copy) + self._sexp = rinterface.Sexp(sexp, copy=copy) def __str__(self): tmp = r.fifo("") @@ -88,7 +89,24 @@ def __repr__(self): return repr_robject(self) -class Rvector(rinterface.SexpVector): + 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) + + def getSexp(self): + return self._sexp + + def typeof(self): + return self._sexp.typeof() + + def do_slot(self, name): + return self._sexp.do_slot(name) + +class Rvector(Robject): """ R vector-like object. Items in those instances can be accessed with the method "__getitem__" ("[" operator), or with the method "subset".""" @@ -96,7 +114,8 @@ def __init__(self, o): if not isinstance(o, rinterface.SexpVector): o = mapperPy2R(o) - super(Rvector, self).__init__(o) + o = o.getSexp() + self._sexp = o def subset(self, *args, **kwargs): @@ -119,71 +138,85 @@ res = r["["](*([self, ] + [x for x in args]), **kwargs) return res + def __getitem__(self, i): + res = self._sexp[i] + if isinstance(res, rinterface.Sexp): + res = mapperR2Py(res) + return res + def __repr__(self): return repr_robject(self) def __add__(self, x): - res = r.get("+")(self, x) + res = r.get("+")(self.getSexp(), x) return res def __sub__(self, x): - res = r.get("-")(self, x) + res = r.get("-")(self.getSexp(), x) return res def __mul__(self, x): - res = r.get("*")(self, x) + res = r.get("*")(self.getSexp(), x) return res def __div__(self, x): - res = r.get("/")(self, x) + res = r.get("/")(self.getSexp(), x) return res def __divmod__(self, x): - res = r.get("%%")(self, x) + res = r.get("%%")(self.getSexp(), x) return res def __or__(self, x): - res = r.get("|")(self, x) + res = r.get("|")(self.getSexp(), x) return res def __and__(self, x): - res = r.get("&")(self, x) + res = r.get("&")(self.getSexp(), x) return res def __len__(self): - return len(sexp) + return len(self._sexp) -class Rfunction(rinterface.SexpClosure): +class Rfunction(Robject): """ An R function (aka "closure"). """ - def __init__(self, o): - super(Rfunction, self).__init__(o) + 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)._sexp for a in args] + new_args = [mapperPy2R(a).getSexp() for a in args] new_kwargs = {} for k, v in kwargs.iteritems(): - new_kwargs[k] = mapperPy2R(v)._sexp - res = self._sexp(*new_args, **new_kwargs) + new_kwargs[k] = mapperPy2R(v).getSexp() + res = self.getSexp()(*new_args, **new_kwargs) res = mapperR2Py(res) return res + #def getSexp(self): + # return super(rinterface.SexpClosure, self).__init__(self) -class Renvironment(rinterface.SexpEnvironment): +class Renvironment(Robject): """ An R environement. """ - def __init__(self, o): - super(Renvironment, self).__init__(o) + 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) def __getitem__(self, item): - res = super(Renvironment, self).__getitem__(item) + res = self._sexp[item] res = mapperR2Py(res) return res def __setitem__(self, item, value): - self[item] = robj + robj = mapperPy2R(value) + self._sexp[item] = robj.getSexp() + def __iter__(self): + return iter(self._sexp) class RS4(Robject): def __init__(self, o): Modified: branches/rpy_nextgen/rpy/robjects/tests/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/__init__.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/robjects/tests/__init__.py 2008-04-28 09:56:55 UTC (rev 504) @@ -1,9 +1,22 @@ import unittest + +import testRObject +import testRVector +import testRFunction +import testREnvironment import testRobjects def suite(): + suite_RObject = testRObject.suite() + suite_RVector = testRVector.suite() + suite_RFunction = testRFunction.suite() + suite_REnvironment = testREnvironment.suite() suite_Robjects = testRobjects.suite() - alltests = unittest.TestSuite([suite_Robjects, ]) + alltests = unittest.TestSuite([suite_RObject, + suite_RVector, + suite_RFunction, + suite_REnvironment, + suite_Robjects ]) return alltests def main(): Added: branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py (rev 0) +++ branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py 2008-04-28 09:56:55 UTC (rev 504) @@ -0,0 +1,22 @@ +import unittest +import rpy2.robjects as robjects +rinterface = robjects.rinterface +import array + +class REnvironmentTestCase(unittest.TestCase): + def testNew(self): + env = robjects.Renvironment() + self.assertEquals(rinterface.ENVSXP, env.getSexp().typeof()) + self.assertRaises(ValueError, robjects.Renvironment, 'a') + + def testSetItem(self): + env = robjects.Renvironment() + env['a'] = 123 + self.assertTrue('a' in env) + +def suite(): + suite = unittest.TestLoader().loadTestsFromTestCase(REnvironmentTestCase) + return suite + +if __name__ == '__main__': + unittest.main() Property changes on: branches/rpy_nextgen/rpy/robjects/tests/testREnvironment.py ___________________________________________________________________ Name: svn:eol-style + native Modified: branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/robjects/tests/testRFunction.py 2008-04-28 09:56:55 UTC (rev 504) @@ -5,20 +5,24 @@ class RFunctionTestCase(unittest.TestCase): def testNew(self): + identical = rinterface.baseNameSpaceEnv["identical"] self.assertRaises(ValueError, robjects.Rfunction, 'a') ri_f = rinterface.baseNameSpaceEnv.get('help') ro_f = robjects.Rfunction(ri_f) + + self.assertTrue(identical(ri_f, ro_f.getSexp())) - #self.assertEquals(ro_v.typeof(), rinterface.INTSXP) + def testCall(self): + ri_f = rinterface.baseNameSpaceEnv.get('sum') + ro_f = robjects.Rfunction(ri_f) - #ri_v = rinterface.SexpVector(py_a) - #ri_o = rinterface.Sexp(ri_v) + ro_v = robjects.Rvector(array.array('i', [1,2,3])) - #r_v_new = robject.Rvector(ri_v) - #r_v_new = robject.Rvector(ro_v) - + s = ro_f(ro_v) + + def suite(): suite = unittest.TestLoader().loadTestsFromTestCase(RFunctionTestCase) return suite Added: branches/rpy_nextgen/rpy/robjects/tests/testRObject.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRObject.py (rev 0) +++ branches/rpy_nextgen/rpy/robjects/tests/testRObject.py 2008-04-28 09:56:55 UTC (rev 504) @@ -0,0 +1,31 @@ +import unittest +import rpy2.robjects as robjects +rinterface = robjects.rinterface +import array + +class RObjectTestCase(unittest.TestCase): + def testNew(self): + + identical = rinterface.baseNameSpaceEnv["identical"] + py_a = array.array('i', [1,2,3]) + self.assertRaises(ValueError, robjects.Robject, py_a) + + ri_v = rinterface.SexpVector(py_a, rinterface.INTSXP) + ro_v = robjects.Robject(ri_v) + + self.assertTrue(identical(ro_v._sexp, ri_v)[0]) + + #FIXME: why isn't this working ? + #del(ri_v) + self.assertEquals(rinterface.INTSXP, ro_v.typeof()) + + def testRepr(self): + prt = rinterface.baseNameSpaceEnv["print"] + s = prt.__repr__() + +def suite(): + suite = unittest.TestLoader().loadTestsFromTestCase(RObjectTestCase) + return suite + +if __name__ == '__main__': + unittest.main() Property changes on: branches/rpy_nextgen/rpy/robjects/tests/testRObject.py ___________________________________________________________________ Name: svn:eol-style + native Modified: branches/rpy_nextgen/rpy/robjects/tests/testRVector.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRVector.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/robjects/tests/testRVector.py 2008-04-28 09:56:55 UTC (rev 504) @@ -3,17 +3,70 @@ rinterface = robjects.rinterface import array +rlist = robjects.baseNameSpaceEnv["list"] + class RvectorTestCase(unittest.TestCase): def testNew(self): + identical = rinterface.baseNameSpaceEnv["identical"] py_a = array.array('i', [1,2,3]) ro_v = robjects.Rvector(py_a) self.assertEquals(ro_v.typeof(), rinterface.INTSXP) - ri_v = rinterface.SexpVector(py_a) + ri_v = rinterface.SexpVector(py_a, rinterface.INTSXP) + ro_v = robjects.Rvector(ri_v) + + self.assertTrue(identical(ro_v._sexp, ri_v)[0]) + + #FIXME: why isn't this working ? + #del(ri_v) + self.assertEquals(rinterface.INTSXP, ro_v.typeof()) - #r_v_new = robject.Rvector(ri_v) - #r_v_new = robject.Rvector(ro_v) + def testOperators(self): + seq_R = robjects.r["seq"] + mySeq = seq_R(0, 10) + mySeqAdd = mySeq + 2 + for i, li in enumerate(mySeq): + self.assertEquals(i + 2, mySeqAdd[i]) + + mySeqAdd = mySeq + mySeq + for i, li in enumerate(mySeq): + self.assertEquals(mySeq[i] * 2, mySeqAdd[i]) + + def testSubset(self): + 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))) + + 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))) + m = robjects.r.matrix(v, ncol = 2) + col = m.subset(True, 1) + self.assertEquals(11, len(col)) + + # list + letters = robjects.baseNameSpaceEnv["letters"] + myList = rlist(l=letters, f="foo") + idem = robjects.baseNameSpaceEnv["identical"] + self.assertTrue(idem(letters, myList.subset("l")[0])) + self.assertTrue(idem("foo", myList.subset("f")[0])) + + def testGetItem(self): + letters = robjects.baseNameSpaceEnv["letters"] + self.assertEquals('a', letters[0]) + self.assertEquals('z', letters[25]) + self.assertRaises(IndexError, letters.__getitem__, 26) + + mylist = rlist(letters, "foo") + idem = robjects.baseNameSpaceEnv["identical"] + self.assertTrue(idem(letters, mylist[0])) + self.assertTrue(idem("foo", mylist[1])) + def suite(): suite = unittest.TestLoader().loadTestsFromTestCase(RvectorTestCase) return suite Modified: branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py 2008-04-24 14:07:58 UTC (rev 503) +++ branches/rpy_nextgen/rpy/robjects/tests/testRobjects.py 2008-04-28 09:56:55 UTC (rev 504) @@ -22,38 +22,9 @@ for i, li in enumerate(myList): self.assertEquals(i, myList[i][0]) - def testOperators(self): - seq_R = robjects.r["seq"] - mySeq = seq_R(0, 10) - mySeqAdd = mySeq + 2 - for i, li in enumerate(mySeq): - self.assertEquals(i + 2, mySeqAdd[i]) - mySeqAdd = mySeq + mySeq - for i, li in enumerate(mySeq): - self.assertEquals(mySeq[i] * 2, mySeqAdd[i]) - - def testSubset(self): - seq_R = robjects.r["seq"] - mySeq = seq_R(0, 10) - # R indexing starts at one - myIndex = robjects.Rvector(array.array('i', range(1, 11, 2))) - mySubset = mySeq.subset(myIndex) - #import pdb; pdb.set_trace() - for i, si in enumerate(myIndex): - self.assertEquals(mySeq[si-1], mySubset[i]) - - # recycling rule - v = robjects.Rvector(array.array('i', range(1, 23))) - m = robjects.r.matrix(v, ncol = 2) - col = m.subset(True, 1) - #import pdb; pdb.set_trace() - self.assertEquals(11, len(col)) - - - def testMapperR2Python(self): sexp = rinterface.globalEnv.get("letters") ob = robjects.defaultRobjects2PyMapper(sexp) 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 the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ rpy-list mailing list rpy-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rpy-list