Revision: 595
http://rpy.svn.sourceforge.net/rpy/?rev=595&view=rev
Author: lgautier
Date: 2008-07-26 09:14:58 +0000 (Sat, 26 Jul 2008)
Log Message:
-----------
rinterface:
- added method rcall for SexpClosure, to allow calls to R functions mixing
named and
anonymous parameters while keeping the order of the parameters
Modified Paths:
--------------
branches/rpy_nextgen/rpy/rinterface/rinterface.c
branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.c
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-07-25 21:36:56 UTC
(rev 594)
+++ branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-07-26 09:14:58 UTC
(rev 595)
@@ -770,6 +770,7 @@
/* named args */
PyObject *citems, *argValue, *argName;
char *argNameString;
+ unsigned int addArgName;
if (kwds) {
citems = PyMapping_Items(kwds);
@@ -778,26 +779,28 @@
tmp_obj = PySequence_GetItem(citems, arg_i);
if (! tmp_obj) {
PyErr_Format(PyExc_ValueError, "No un-named item %i !?", arg_i);
- Py_DECREF(tmp_obj);
+ Py_XDECREF(tmp_obj);
Py_XDECREF(citems);
goto fail;
}
argName = PyTuple_GetItem(tmp_obj, 0);
if (argName == Py_None) {
+ addArgName = 0;
PyErr_SetString(PyExc_TypeError,
"None/missing keywords not yet supported.");
Py_DECREF(tmp_obj);
Py_XDECREF(citems);
goto fail;
- }
-
- if (! PyString_Check(argName)) {
+ } else if (PyString_Check(argName)) {
+ addArgName = 1;
+ } else {
PyErr_SetString(PyExc_TypeError, "All keywords must be strings.");
Py_DECREF(tmp_obj);
Py_XDECREF(citems);
goto fail;
}
+
argValue = PyTuple_GetItem(tmp_obj, 1);
is_PySexpObject = PyObject_TypeCheck(argValue, &Sexp_Type);
if (! is_PySexpObject) {
@@ -818,11 +821,13 @@
goto fail;
}
SETCAR(c_R, tmp_R);
- argNameString = PyString_AsString(argName);
- SET_TAG(c_R, install(argNameString));
+ if (addArgName) {
+ argNameString = PyString_AsString(argName);
+ SET_TAG(c_R, install(argNameString));
//printf("PyMem_Free...");
//FIXME: probably memory leak with argument names.
//PyMem_Free(argNameString);
+ }
c_R = CDR(c_R);
}
Py_XDECREF(citems);
@@ -861,8 +866,153 @@
}
+/* This is the method to call when invoking an 'Sexp' */
+static PyObject *
+Sexp_rcall(PyObject *self, PyObject *args)
+{
+
+ if (! (embeddedR_status & RPY_R_INITIALIZED)) {
+ PyErr_Format(PyExc_RuntimeError,
+ "R must be initialized before any call to R functions is
possible.");
+ return NULL;
+ }
+
+ if (! PyTuple_Check(args)) {
+ PyErr_Format(PyExc_ValueError, "Parameter must be a tuple.");
+ return NULL;
+ }
+ if (embeddedR_status & RPY_R_BUSY) {
+ PyErr_Format(PyExc_RuntimeError, "Concurrent access to R is not allowed.");
+ return NULL;
+ }
+ embeddedR_setlock();
+
+ SEXP call_R, c_R, res_R;
+ int largs;
+ SEXP tmp_R, fun_R;
+
+ largs = 0;
+ if (args)
+ largs = PyObject_Length(args);
+ if (args<0) {
+ PyErr_Format(PyExc_ValueError, "Negative number of parameters !?.");
+ embeddedR_freelock();
+ return NULL;
+ }
+
+ /* A SEXP with the function to call and the arguments and keywords. */
+ PROTECT(c_R = call_R = allocList(largs+1));
+ SET_TYPEOF(c_R, LANGSXP);
+ fun_R = RPY_SEXP((PySexpObject *)self);
+ if (! fun_R) {
+ PyErr_Format(PyExc_ValueError, "NULL SEXP.");
+ goto fail;
+ }
+ SETCAR(c_R, fun_R);
+ c_R = CDR(c_R);
+
+ int arg_i;
+ PyObject *tmp_obj;
+ int is_PySexpObject;
+
+ /* named args */
+ PyObject *citems, *argValue, *argName;
+ char *argNameString;
+ unsigned int addArgName;
+ Py_ssize_t itemLength;
+ //citems = PyMapping_Items(args);
+ for (arg_i=0; arg_i<largs; arg_i++) {
+ //printf("item: %i\n", arg_i);
+ tmp_obj = PyTuple_GetItem(args, arg_i);
+ if (! tmp_obj) {
+ PyErr_Format(PyExc_ValueError, "No un-named item %i !?", arg_i);
+ //Py_XDECREF(citems);
+ goto fail;
+ }
+ itemLength = PyObject_Length(tmp_obj);
+ if (itemLength != 2) {
+ PyErr_Format(PyExc_ValueError, "Item %i does not have two elements.",
+ arg_i);
+ goto fail;
+ }
+ argName = PyTuple_GetItem(tmp_obj, 0);
+ if (argName == Py_None) {
+ addArgName = 0;
+ } else if (PyString_Check(argName)) {
+ addArgName = 1;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "All keywords must be strings.");
+ Py_XDECREF(citems);
+ goto fail;
+ }
+ argValue = PyTuple_GetItem(tmp_obj, 1);
+ is_PySexpObject = PyObject_TypeCheck(argValue, &Sexp_Type);
+ if (! is_PySexpObject) {
+ PyErr_Format(PyExc_ValueError,
+ "All parameters must be of type Sexp_Type.");
+ //Py_XDECREF(citems);
+ goto fail;
+ }
+ tmp_R = RPY_SEXP((PySexpObject *)argValue);
+ //tmp_R = Rf_duplicate(tmp_R);
+ if (! tmp_R) {
+ PyErr_Format(PyExc_ValueError, "NULL SEXP.");
+ //Py_XDECREF(citems);
+ goto fail;
+ }
+ SETCAR(c_R, tmp_R);
+ if (addArgName) {
+ argNameString = PyString_AsString(argName);
+ SET_TAG(c_R, install(argNameString));
+ //printf("PyMem_Free...");
+ //FIXME: probably memory leak with argument names.
+ //PyMem_Free(argNameString);
+ }
+ c_R = CDR(c_R);
+ }
+
+ //Py_XDECREF(citems);
+
+//FIXME: R_GlobalContext ?
+ PROTECT(res_R = do_eval_expr(call_R, R_GlobalEnv));
+ //PROTECT(res_R = do_eval_expr(call_R, CLOENV(fun_R)));
+
+/* if (!res) { */
+/* UNPROTECT(2); */
+/* return NULL; */
+/* } */
+ UNPROTECT(2);
+
+ if (! res_R) {
+ EmbeddedR_exception_from_errmessage();
+ //PyErr_Format(PyExc_RuntimeError, "Error while running R code");
+ embeddedR_freelock();
+ return NULL;
+ }
+
+ //FIXME: standardize R outputs
+ extern void Rf_PrintWarnings(void);
+ Rf_PrintWarnings(); /* show any warning messages */
+
+ PyObject *res = (PyObject *)newPySexpObject(res_R);
+ embeddedR_freelock();
+ return res;
+
+ fail:
+ UNPROTECT(1);
+ embeddedR_freelock();
+ return NULL;
+
+}
+
+PyDoc_STRVAR(SexpClosure_rcall_doc,
+"Call using the items of the object passed as Python \n\
+argument to build the list of parameters passed to the \n\
+R function.");
+
+
static PySexpObject*
Sexp_closureEnv(PyObject *self)
{
@@ -888,7 +1038,9 @@
static PyMethodDef ClosureSexp_methods[] = {
{"closureEnv", (PyCFunction)Sexp_closureEnv, METH_NOARGS,
- Sexp_closureEnv_doc},
+ Sexp_closureEnv_doc},
+ {"rcall", (PyCFunction)Sexp_rcall, METH_O,
+ SexpClosure_rcall_doc},
{NULL, NULL} /* sentinel */
};
Modified: branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
2008-07-25 21:36:56 UTC (rev 594)
+++ branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
2008-07-26 09:14:58 UTC (rev 595)
@@ -1,5 +1,6 @@
import unittest
import rpy2.rinterface as rinterface
+import rpy2.rlike.container as rlc
try:
#FIXME: can starting and stopping an embedded R be done several times ?
@@ -44,7 +45,6 @@
rinterface.INTSXP)
self.assertEquals('b', fun(vec)[0])
-
def testCallS4SetClass(self):
# R's package "methods" can perform uncommon operations
r_setClass = rinterface.globalEnv.get('setClass')
@@ -58,9 +58,15 @@
classrepr)
-
-
+ def testRcall(self):
+ ad = rlc.ArgsDict((('a', rinterface.SexpVector([2, ],
rinterface.INTSXP)),
+ ('b', rinterface.SexpVector([1, ],
rinterface.INTSXP)),
+ ('c', rinterface.SexpVector([0, ],
rinterface.INTSXP))))
+
+ mylist = rinterface.baseNameSpaceEnv['list'].rcall(ad.items())
+
+
def suite():
suite = unittest.TestLoader().loadTestsFromTestCase(SexpClosureTestCase)
return suite
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 Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
rpy-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list