Revision: 406
http://rpy.svn.sourceforge.net/rpy/?rev=406&view=rev
Author: lgautier
Date: 2008-02-24 11:07:58 -0800 (Sun, 24 Feb 2008)
Log Message:
-----------
- Added directory for tests (empty for the moment)
- Switched order of arguments for VectorSexp_new
- Added module object "globalEnv"
- Fixed 'repr' for Sexp_type to give the actual address pointed by an SEXP
- Added sanity check and error when calling ClosureSexp_call
- Method "get" for EnviromentSexp objects
- Subscript method for EnvironmentSexp objects (...but segfaults)
Modified Paths:
--------------
trunk/sandbox/rpy_nextgen/rinterface/rinterface.c
Added Paths:
-----------
trunk/sandbox/rpy_nextgen/rinterface/tests/
Modified: trunk/sandbox/rpy_nextgen/rinterface/rinterface.c
===================================================================
--- trunk/sandbox/rpy_nextgen/rinterface/rinterface.c 2008-02-23 22:53:23 UTC
(rev 405)
+++ trunk/sandbox/rpy_nextgen/rinterface/rinterface.c 2008-02-24 19:07:58 UTC
(rev 406)
@@ -89,7 +89,7 @@
Example of usage:\
import rinterface\
rinterface.initEmbeddedR(\"foo\", \"--verbose\")\
-n = rinterface.SexpVector(rinterface.REALSXP, (100,))\
+n = rinterface.SexpVector((100, ), rinterface.REALSXP)\
hist = rinterface.findVarEmbeddedR(\"hist\")\
rnorm = rinterface.findVarEmbeddedR(\"rnorm\")\
x = rnorm(n)\
@@ -109,8 +109,8 @@
} SexpObject;
+static SexpObject* globalEnv;
-
/* --- Initialize and terminate an embedded R --- */
/* Should having multiple threads of R become possible,
* Useful routines deal with can could appear here...
@@ -136,6 +136,9 @@
}
int status = Rf_initEmbeddedR(n_opt, options);
+
+ globalEnv->sexp = R_GlobalEnv;
+
PyObject *res = PyInt_FromLong(status);
return res;
}
@@ -227,10 +230,11 @@
Sexp_repr(PyObject *self)
{
//FIXME: make sure this is making any sense
+ SEXP sexp = ((SexpObject *)self)->sexp;
return PyString_FromFormat("<%s - Python:\%p / R:\%p>",
self->ob_type->tp_name,
self,
- &(((SexpObject *)self)->sexp));
+ sexp);
}
@@ -305,8 +309,8 @@
* Closure-type Sexp.
*/
-static SexpObject* newSexpObject(SEXP);
-static SEXP newSEXP(PyObject *object, int rType);
+static SexpObject* newSexpObject(const SEXP sexp);
+static SEXP newSEXP(PyObject *object, const int rType);
/* Evaluate a SEXP. It must be constructed by hand. It raises a Python
exception if an error ocurred in the evaluation */
@@ -380,13 +384,22 @@
int arg_i;
SEXP tmp_R;
+ PyObject *tmp_obj;
+ int is_SexpObject;
for (arg_i=0; arg_i<largs; arg_i++) {
//FIXME: assert that all are SexpObjects
- tmp_R = ((SexpObject *)PyTuple_GetItem(args, arg_i))->sexp;
+ tmp_obj = PyTuple_GetItem(args, arg_i);
+ is_SexpObject = PyObject_TypeCheck(tmp_obj, &Sexp_Type);
+ if (! is_SexpObject) {
+ PyErr_Format(PyExc_ValueError, "All parameters must be of type
Sexp_Type.");
+ return NULL;
+ }
+ tmp_R = ((SexpObject *)tmp_obj)->sexp;
SETCAR(c_R, tmp_R);
c_R = CDR(c_R);
}
+ //FIXME: implement named parameters.
/* if (!make_kwds(lkwds, kwds, &e)) { */
/* UNPROTECT(1); */
/* return NULL; */
@@ -490,14 +503,13 @@
{
int rType = -1;
PyObject *seq = 0;
- if (!PyArg_ParseTuple(args, "iO:new",
- &rType, &seq))
+ if (!PyArg_ParseTuple(args, "Oi:new",
+ &seq, &rType))
return NULL;
#ifdef VERBOSE
printf("type: %i\n", rType);
#endif
- SEXP sexp;
- sexp = newSEXP(seq, rType);
+ const SEXP sexp = newSEXP(seq, rType);
PyObject *res = (PyObject *)newSexpObject(sexp);
return res;
}
@@ -583,7 +595,7 @@
//FIXME: write more doc
PyDoc_STRVAR(VectorSexp_Type_doc,
-"An R object that is a vector.\
+"R object that is a vector.\
R vectors start their indexing at one,\
while Python lists or arrays start indexing\
at zero.\
@@ -657,6 +669,11 @@
}
const SEXP rho_R = ((SexpObject *)self)->sexp;
+
+ if (rho_R == NULL) {
+ PyErr_Format(PyExc_LookupError, "Fatal error: NULL environment.");
+ }
+
res_R = findVar(install(name), rho_R);
@@ -670,29 +687,58 @@
"Find an R object in the environment.");
static PyMethodDef EnvironmentSexp_methods[] = {
- {"get", (PyCFunction)EnvironmentSexp_findVar, METH_O,
+ {"get", (PyCFunction)EnvironmentSexp_findVar, METH_VARARGS,
EnvironmentSexp_findVar_doc},
{NULL, NULL} /* sentinel */
};
+//FIXME: segfault :/
+static SexpObject*
+EnvironmentSexp_subscript(PyObject *self, PyObject *key)
+{
+ char *name;
+ SEXP res_R;
+
+ if (!PyString_Check(key)) {
+ PyErr_Format(PyExc_ValueError, "Keys must be string objects.");
+ return NULL;
+ }
+
+ name = PyString_AsString(key);
+
+ SEXP rho_R = ((SexpObject *)self)->sexp;
+ res_R = findVarInFrame(install(name), rho_R);
+
+
+ if (res_R != R_UnboundValue) {
+ return newSexpObject(res_R);
+ }
+ PyErr_Format(PyExc_LookupError, "'%s' not found", name);
+ return NULL;
+}
+PyDoc_STRVAR(EnvironmentSexp_subscript_doc,
+ "Find an R object in the environment.\
+ Not all R environment are hash tables, and this may\n\
+influence performances when doing repeated lookups.");
+
//FIXME: Is this still needed ?
static PyMappingMethods EnvironmentSexp_mappignMethods = {
0, /* mp_length */
- 0, /* mp_subscript */
+ EnvironmentSexp_subscript, /* mp_subscript */
0 /* mp_ass_subscript */
};
//FIXME: write more doc - should the environments
// be made like mappings at the Python level ?
PyDoc_STRVAR(EnvironmentSexp_Type_doc,
-"An R object that is an environment.\
- R environments can be seen as similar to Python\
+"R object that is an environment.\
+ R environments can be seen as similar to Python\n\
dictionnaries, with the twist that looking for\
- a key can be recursively propagated to the enclosing\
+ a key can be recursively propagated to the enclosing\n\
environment whenever the key is not found.\
\n\
- The subsetting operator is made to match Python's\
+ The subsetting operator is made to match Python's\n\
behavior, that is the enclosing environments are not\
inspected upon absence of a given key.\
");
@@ -714,7 +760,7 @@
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
+ &EnvironmentSexp_mappignMethods,
/*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0,//Sexp_str, /*tp_str*/
@@ -748,7 +794,7 @@
//FIXME: write more doc
PyDoc_STRVAR(S4Sexp_Type_doc,
-"An R object that is an 'S4 object'.\
+"R object that is an 'S4 object'.\
");
static PyTypeObject S4Sexp_Type = {
@@ -803,10 +849,10 @@
/* --- Create a SEXP object --- */
static SexpObject*
-newSexpObject(SEXP sexp)
+newSexpObject(const SEXP sexp)
{
SexpObject *object;
- SEXP env_R;
+ SEXP sexp_ok, env_R;
//FIXME: let the possibility to manipulate un-evaluated promises ?
if (TYPEOF(sexp) == PROMSXP) {
@@ -814,13 +860,16 @@
printf("evaluating promise...");
#endif
env_R = PRENV(sexp);
- sexp = eval(sexp, env_R);
+ sexp_ok = eval(sexp, env_R);
#ifdef VERBOSE
printf("done.\n");
#endif
+ }
+ else {
+ sexp_ok = sexp;
}
- switch (TYPEOF(sexp)) {
+ switch (TYPEOF(sexp_ok)) {
case CLOSXP:
object = (SexpObject *)_PyObject_New(&ClosureSexp_Type);
break;
@@ -851,9 +900,9 @@
}
if (!object)
PyErr_NoMemory();
- object->sexp = sexp;
+ object->sexp = sexp_ok;
if (sexp)
- R_PreserveObject(sexp);
+ R_PreserveObject(sexp_ok);
return object;
}
@@ -862,11 +911,11 @@
{
SEXP sexp;
PyObject *seq_object, *item;
- seq_object = PySequence_Fast(object, "Cannot create"
- " R object from non-sequence Python object.");
- if (! seq_object)
+ seq_object = PySequence_Fast(object, "Cannot create R object from
non-sequence Python object.");
+ //FIXME: Isn't the call above supposed to fire an Exception ?
+ if (! seq_object) {
return NULL;
-
+ }
const Py_ssize_t length = PySequence_Fast_GET_SIZE(seq_object);
//FIXME: PROTECT THIS ?
sexp = allocVector(rType, length);
@@ -952,16 +1001,6 @@
//(PyTypeObject *)ClosureSexp_Type.tp_new = 0;//ClosureSexp_methods;
-static PyObject*
-Sexp_GlobalEnv(PyTypeObject* type)
-{
- SexpObject* res = (SexpObject*)type->tp_alloc(type, 0);
- res->sexp = R_GlobalEnv;
- return (PyObject*)res;
-}
-
-
-
/* --- Find a variable in an environment --- */
@@ -983,7 +1022,7 @@
if (res != R_UnboundValue) {
return newSexpObject(res);
}
- PyErr_Format(ErrorObject, "'%s' not found", name);
+ PyErr_Format(PyExc_LookupError, "'%s' not found", name);
return NULL;
}
PyDoc_STRVAR(EmbeddedR_findVar_doc,
@@ -1013,6 +1052,7 @@
#define ADD_INT_CONSTANT(module, name) PyModule_AddIntConstant(module, #name,
name)
+
PyMODINIT_FUNC
initrinterface(void)
{
@@ -1031,10 +1071,11 @@
if (PyType_Ready(&S4Sexp_Type) < 0)
return;
- PyObject *m;
+ PyObject *m, *d;
m = Py_InitModule3("rinterface", EmbeddedR_methods, module_doc);
if (m == NULL)
return;
+ d = PyModule_GetDict(m);
PyModule_AddObject(m, "Sexp", (PyObject *)&Sexp_Type);
PyModule_AddObject(m, "SexpClosure", (PyObject *)&ClosureSexp_Type);
@@ -1051,6 +1092,12 @@
Py_INCREF(ErrorObject);
PyModule_AddObject(m, "RobjectNotFound", ErrorObject);
+ globalEnv = (SexpObject*)_PyObject_New(&EnvironmentSexp_Type);
+ globalEnv->sexp = NULL;
+ if (PyDict_SetItemString(d, "globalEnv", (PyObject*)globalEnv) < 0)
+ return;
+ //FIXME: DECREF ?
+ //Py_DECREF(globalEnv);
/* Add some symbolic constants to the module */
ADD_INT_CONSTANT(m, NILSXP);
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list