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
rpy-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpy-list

Reply via email to