Revision: 567
http://rpy.svn.sourceforge.net/rpy/?rev=567&view=rev
Author: lgautier
Date: 2008-07-02 07:57:48 -0700 (Wed, 02 Jul 2008)
Log Message:
-----------
rinterface:
- added sketchy systems for locking R when accessed
- evaluation of expression in R_GlobalEnv rather than in R_CLOENV(fun_R)
seems to be the right thing
- added test on setClass (as it triggered a problem, and the fix above)
- more docstrings
Modified Paths:
--------------
branches/rpy_nextgen/rpy/rinterface/rinterface.c
branches/rpy_nextgen/rpy/rinterface/rinterface.h
branches/rpy_nextgen/rpy/rinterface/tests/__init__.py
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-06-25 21:31:56 UTC
(rev 566)
+++ branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-07-02 14:57:48 UTC
(rev 567)
@@ -110,11 +110,18 @@
error("Interrupted");
}
-/* Helper variable to store whether the embedded R is initialized
- * or not.
+/* Helper variable to store R's status
*/
+static unsigned int embeddedR_status = 0;
static PyObject *embeddedR_isInitialized;
+inline void embeddedR_setlock() {
+ embeddedR_status = embeddedR_status | RPY_R_BUSY;
+}
+inline void embeddedR_freelock() {
+ embeddedR_status = embeddedR_status ^ RPY_R_BUSY;
+}
+
/* The Python original SIGINT handler */
PyOS_sighandler_t python_sigint;
@@ -219,7 +226,7 @@
static PyObject* EmbeddedR_init(PyObject *self)
{
- if (PyObject_IsTrue(embeddedR_isInitialized)) {
+ if (embeddedR_status & RPY_R_INITIALIZED) {
PyErr_Format(PyExc_RuntimeError, "R can only be initialized once.");
return NULL;
}
@@ -242,6 +249,7 @@
setup_Rmainloop();
Py_XDECREF(embeddedR_isInitialized);
+ embeddedR_status = RPY_R_INITIALIZED;
embeddedR_isInitialized = Py_True;
Py_INCREF(Py_True);
@@ -316,7 +324,7 @@
EmbeddedR_exception_from_errmessage(void)
{
SEXP expr, res;
- //PROTECT(GetErrMessage_SEXP);
+ //PROTECT(GetErrMessage_SEXP)
PROTECT(expr = allocVector(LANGSXP, 1));
SETCAR(expr, GetErrMessage_SEXP);
PROTECT(res = Rf_eval(expr, R_GlobalEnv));
@@ -606,7 +614,6 @@
int error = 0;
PyOS_sighandler_t old_int;
-
//FIXME: if env_R is null, use R_BaseEnv
//shouldn't it be R_GlobalContext (but then it throws a NULL error) ?
if (isNull(env_R)) {
@@ -630,19 +637,17 @@
python_sigint = old_int;
signal(SIGINT, interrupt_R);
-
+
interrupted = 0;
//FIXME: evaluate expression in the given
res_R = R_tryEval(expr_R, env_R, &error);
-
#ifdef _WIN32
PyOS_setsig(SIGBREAK, old_int);
#else
PyOS_setsig(SIGINT, old_int);
#endif
-
/* start_events(); */
-
+
if (error) {
if (interrupted) {
PyErr_SetNone(PyExc_KeyboardInterrupt);
@@ -652,7 +657,6 @@
}
return NULL;
}
-
return res_R;
}
@@ -661,6 +665,13 @@
static PyObject *
Sexp_call(PyObject *self, PyObject *args, PyObject *kwds)
{
+
+ 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, lkwds;
SEXP tmp_R, fun_R;
@@ -672,6 +683,7 @@
lkwds = PyObject_Length(kwds);
if ((largs<0) || (lkwds<0)) {
PyErr_Format(PyExc_ValueError, "Negative number of parameters !?.");
+ embeddedR_freelock();
return NULL;
}
@@ -756,10 +768,10 @@
}
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)));
+ 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); */
@@ -770,6 +782,7 @@
if (! res_R) {
EmbeddedR_exception_from_errmessage();
//PyErr_Format(PyExc_RuntimeError, "Error while running R code");
+ embeddedR_freelock();
return NULL;
}
@@ -778,10 +791,12 @@
Rf_PrintWarnings(); /* show any warning messages */
PyObject *res = (PyObject *)newPySexpObject(res_R);
+ embeddedR_freelock();
return res;
fail:
UNPROTECT(1);
+ embeddedR_freelock();
return NULL;
}
@@ -798,7 +813,13 @@
PyErr_Format(PyExc_ValueError, "NULL SEXP.");
return NULL;
}
+ if (embeddedR_status & RPY_R_BUSY) {
+ PyErr_Format(PyExc_RuntimeError, "Concurrent access to R is not allowed.");
+ return NULL;
+ }
+ embeddedR_setlock();
closureEnv = CLOENV(sexp);
+ embeddedR_freelock();
return newPySexpObject(closureEnv);
}
PyDoc_STRVAR(Sexp_closureEnv_doc,
@@ -1242,7 +1263,11 @@
return (PyObject *)res;
}
PyDoc_STRVAR(EnvironmentSexp_findVar_doc,
- "Find an R object in a given environment.");
+ "Find a name/symbol in the environment, following the chain of
enclosing\n"
+ " environment until either the topmost environment is reached or
the name\n"
+ "is found, and returned the associated object. \n"
+ "The optional parameter `wantFun` indicates whether functions
should be\n"
+ "returned or not.");
static PyMethodDef EnvironmentSexp_methods[] = {
{"get", (PyCFunction)EnvironmentSexp_findVar, METH_VARARGS | METH_KEYWORDS,
@@ -1277,11 +1302,8 @@
PyErr_Format(PyExc_LookupError, "'%s' not found", name);
return NULL;
}
-PyDoc_STRVAR(EnvironmentSexp_subscript_doc,
- "Find an R object in the environment.\n"
- "Not all R environment are hash tables, and this may"
- " influence performances when doing repeated lookups.");
+
static int
EnvironmentSexp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
{
@@ -1362,19 +1384,20 @@
}
PyDoc_STRVAR(EnvironmentSexp_Type_doc,
-"R object that is an environment.\
- R environments can be seen as similar to Python\
- dictionnaries, with the following twists:\n\
- - an environment can be a list of frames to sequentially\
- search into\n\
-- the search can be recursively propagated to the enclosing\
- environment whenever the key is not found (in that respect\
- they can be seen as scopings).\n\
-\n\
- The subsetting operator \"[\" is made to match Python's\
- behavior, that is the enclosing environments are not\
- inspected upon absence of a given key.\n\
-");
+"R object that is an environment.\n"
+"R environments can be seen as similar to Python\n"
+"dictionnaries, with the following twists:\n"
+"\n"
+"- an environment can be a list of frames to sequentially\n"
+"search into\n"
+"\n"
+"- the search can be recursively propagated to the enclosing\n"
+"environment whenever the key is not found (in that respect\n"
+"they can be seen as scopings).\n"
+"\n"
+"The subsetting operator \"[\" is made to match Python's\n"
+"behavior, that is the enclosing environments are not\n"
+"inspected upon absence of a given key.\n");
static int
Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.h
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/rinterface.h 2008-06-25 21:31:56 UTC
(rev 566)
+++ branches/rpy_nextgen/rpy/rinterface/rinterface.h 2008-07-02 14:57:48 UTC
(rev 567)
@@ -8,6 +8,10 @@
//#define RPY_VERBOSE
+
+const unsigned int RPY_R_INITIALIZED = 0x01;
+const unsigned int RPY_R_BUSY = 0x02;
+
/* Representation of R objects (instances) as instances in Python.
*/
Modified: branches/rpy_nextgen/rpy/rinterface/tests/__init__.py
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/tests/__init__.py 2008-06-25
21:31:56 UTC (rev 566)
+++ branches/rpy_nextgen/rpy/rinterface/tests/__init__.py 2008-07-02
14:57:48 UTC (rev 567)
@@ -6,6 +6,7 @@
import test_SexpClosure
import test_SexpVectorNumeric
import test_EmbeddedR
+import test_EmbeddedR_multithreaded
def suite():
@@ -15,12 +16,15 @@
suite_SexpClosure = test_SexpClosure.suite()
suite_SexpVectorNumeric = test_SexpVectorNumeric.suite()
suite_EmbeddedR = test_EmbeddedR.suite()
- alltests = unittest.TestSuite([suite_SexpVector,
- suite_SexpEnvironment,
- suite_Sexp,
- suite_SexpClosure,
- suite_SexpVectorNumeric,
- suite_EmbeddedR])
+ #suite_EmbeddedR_multithreaded = test_EmbeddedR_multithreaded.suite()
+ alltests = unittest.TestSuite([suite_SexpVector
+ ,suite_SexpEnvironment
+ ,suite_Sexp
+ ,suite_SexpClosure
+ ,suite_SexpVectorNumeric
+ ,suite_EmbeddedR
+ # suite_EmbeddedR_multithreaded
+ ])
return alltests
def main():
Modified: branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
2008-06-25 21:31:56 UTC (rev 566)
+++ branches/rpy_nextgen/rpy/rinterface/tests/test_SexpClosure.py
2008-07-02 14:57:48 UTC (rev 567)
@@ -9,7 +9,7 @@
class SexpClosureTestCase(unittest.TestCase):
- #def setUpt(self):
+ #def setUp(self):
# rinterface.initEmbeddedR("foo", "--no-save")
#def tearDown(self):
@@ -45,6 +45,22 @@
self.assertEquals('b', fun(vec)[0])
+ def testCallS4SetClass(self):
+ # R's package "methods" can perform uncommon operations
+ r_setClass = rinterface.globalEnv.get('setClass')
+ r_representation = rinterface.globalEnv.get('representation')
+ attrnumeric = rinterface.SexpVector(["numeric", ],
+ rinterface.STRSXP)
+ classname = rinterface.SexpVector(['Track', ], rinterface.STRSXP)
+ classrepr = r_representation(x = attrnumeric,
+ y = attrnumeric)
+ r_setClass(classname,
+ classrepr)
+
+
+
+
+
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.
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
rpy-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list