Revision: 614
          http://rpy.svn.sourceforge.net/rpy/?rev=614&view=rev
Author:   lgautier
Date:     2008-08-04 19:17:23 +0000 (Mon, 04 Aug 2008)

Log Message:
-----------
New function to allow Python callback for R console input

Modified Paths:
--------------
    branches/rpy_nextgen/NEWS
    branches/rpy_nextgen/rpy/rinterface/__init__.py
    branches/rpy_nextgen/rpy/rinterface/rinterface.c
    branches/rpy_nextgen/rpy/rinterface/tests/test_EmbeddedR.py
    branches/rpy_nextgen/setup.py

Modified: branches/rpy_nextgen/NEWS
===================================================================
--- branches/rpy_nextgen/NEWS   2008-08-03 18:14:48 UTC (rev 613)
+++ branches/rpy_nextgen/NEWS   2008-08-04 19:17:23 UTC (rev 614)
@@ -1,4 +1,22 @@
+SVN
+===
 
+New features
+------------
+
+:mod:`rpy2.rinterface`:
+
+- :func:`setReadConsole`: specify Python callback for console input
+
+Changes
+-------
+
+:mod:`rpy2.rinterface`:
+
+- underlying handling of interruptions is being worked on
+
+
+
 Release 2.0.0a2
 ===============
 

Modified: branches/rpy_nextgen/rpy/rinterface/__init__.py
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/__init__.py     2008-08-03 18:14:48 UTC 
(rev 613)
+++ branches/rpy_nextgen/rpy/rinterface/__init__.py     2008-08-04 19:17:23 UTC 
(rev 614)
@@ -66,3 +66,11 @@
     print(x)
 
 setWriteConsole(consolePrint)
+
+def consoleRead(prompt):
+    input = raw_input(prompt)
+    input += "\n"
+    return input
+
+setReadConsole(consoleRead)
+

Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.c
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/rinterface.c    2008-08-03 18:14:48 UTC 
(rev 613)
+++ branches/rpy_nextgen/rpy/rinterface/rinterface.c    2008-08-04 19:17:23 UTC 
(rev 614)
@@ -202,7 +202,7 @@
   arglist = Py_BuildValue("(s)", buf);
   if (! arglist) {
     PyErr_NoMemory();
-    signal(SIGINT, old_int);
+/*     signal(SIGINT, old_int); */
     //return NULL;
   }
 
@@ -213,7 +213,7 @@
   result = PyEval_CallObject(writeConsoleCallback, arglist);
 
   Py_DECREF(arglist);
-  signal(SIGINT, old_int);
+/*   signal(SIGINT, old_int); */
   
   if (result == NULL) {
     return;
@@ -223,7 +223,95 @@
   
 }
 
+static PyObject* readConsoleCallback = NULL;
 
+static PyObject* EmbeddedR_setReadConsole(PyObject *self,
+                                         PyObject *args)
+{
+  
+  PyObject *result = NULL;
+  PyObject *function;
+  
+  if ( PyArg_ParseTuple(args, "O:console", 
+                       &function)) {
+    
+    if (!PyCallable_Check(function)) {
+      PyErr_SetString(PyExc_TypeError, "parameter must be callable");
+      return NULL;
+    }
+
+    Py_XDECREF(readConsoleCallback);
+    Py_XINCREF(function);
+    readConsoleCallback = function;
+    Py_INCREF(Py_None);
+    result = Py_None;
+  } else {
+    PyErr_SetString(PyExc_TypeError, "The parameter should be a callable.");
+  }
+  return result;
+  
+}
+
+PyDoc_STRVAR(EmbeddedR_setReadConsole_doc,
+            "Use the function to handle R console input.");
+
+
+static void
+EmbeddedR_ReadConsole(const char *prompt, unsigned char *buf, 
+                     int len, int addtohistory)
+{
+  PyOS_sighandler_t old_int;
+  PyObject *arglist;
+  PyObject *result;
+
+  /* It is necessary to restore the Python handler when using a Python
+     function for I/O. */
+/*   old_int = PyOS_getsig(SIGINT); */
+/*   PyOS_setsig(SIGINT, python_sigint); */
+  arglist = Py_BuildValue("(s)", prompt);
+  if (! arglist) {
+    PyErr_NoMemory();
+/*     signal(SIGINT, old_int); */
+    //return NULL;
+  }
+
+  if (readConsoleCallback == NULL) {
+    Py_DECREF(arglist);
+    return;
+  }
+
+  #ifdef RPY_DEBUG_CONSOLE
+  printf("Callback for console input...");
+  #endif
+  result = PyEval_CallObject(readConsoleCallback, arglist);
+  #ifdef RPY_DEBUG_CONSOLE
+  printf("done.(%p)\n", result);
+  #endif
+  Py_XDECREF(arglist);
+
+  if (result == NULL) {
+/*     signal(SIGINT, old_int); */
+    return;
+  }
+
+  char *input_str = PyString_AsString(result);
+  if (! input_str) {
+    Py_XDECREF(arglist);
+    return;
+  }
+
+  /* Snatched from Rcallbacks.c in JRI */
+  int l=strlen(input_str);
+  strncpy((char *)buf, input_str, (l>len-1)?len-1:l);
+  buf[(l>len-1)?len-1:l]=0;
+  /* --- */
+  
+  Py_XDECREF(result);
+/*   signal(SIGINT, old_int); */
+  
+}
+
+
 /* --- Initialize and terminate an embedded R --- */
 /* Should having multiple threads of R become possible, 
  * useful routines could appear here...
@@ -247,18 +335,23 @@
   }
 
 
+#ifdef RIF_HAS_RSIGHAND
+  R_SignalHandlers=0;
+#endif  
   /* int status = Rf_initEmbeddedR(n_args, options);*/
-  int status = 1;
-  Rf_initialize_R(n_args, options);
+  int status = Rf_initialize_R(n_args, options);
   R_Interactive = TRUE;
+#ifdef RIF_HAS_RSIGHAND
+  R_SignalHandlers=0;
+#endif  
 
   /* Taken from JRI:
    * disable stack checking, because threads will thow it off */
   R_CStackLimit = (uintptr_t) -1;
   
-  #ifdef Win32
+#ifdef Win32
   setup_term_ui();
-  #endif
+#endif
   setup_Rmainloop();
 
   Py_XDECREF(embeddedR_isInitialized);
@@ -271,6 +364,8 @@
   ptr_R_WriteConsole = EmbeddedR_WriteConsole;
   R_Outputfile = NULL;
   R_Consolefile = NULL;
+  /* Redirect R console input */
+  ptr_R_ReadConsole = EmbeddedR_ReadConsole;
   #endif
 
   RPY_SEXP(globalEnv) = R_GlobalEnv;
@@ -673,7 +768,7 @@
 #endif
   python_sigint = old_int;
   
-  signal(SIGINT, interrupt_R);
+/*   signal(SIGINT, interrupt_R); */
 
   interrupted = 0;
   //FIXME: evaluate expression in the given
@@ -2081,6 +2176,8 @@
    EmbeddedR_end_doc},
   {"setWriteConsole",  (PyCFunction)EmbeddedR_setWriteConsole,  METH_VARARGS,
    EmbeddedR_setWriteConsole_doc},
+  {"setReadConsole",   (PyCFunction)EmbeddedR_setReadConsole,   METH_VARARGS,
+   EmbeddedR_setReadConsole_doc},
   {"findVarEmbeddedR", (PyCFunction)EmbeddedR_findVar,  METH_VARARGS,
    EmbeddedR_findVar_doc},
   {"sexpTypeEmbeddedR",        (PyCFunction)EmbeddedR_sexpType, METH_VARARGS,

Modified: branches/rpy_nextgen/rpy/rinterface/tests/test_EmbeddedR.py
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/tests/test_EmbeddedR.py 2008-08-03 
18:14:48 UTC (rev 613)
+++ branches/rpy_nextgen/rpy/rinterface/tests/test_EmbeddedR.py 2008-08-04 
19:17:23 UTC (rev 614)
@@ -20,6 +20,15 @@
         self.assertEquals('[1] "3"\n', str.join('', buf))
         rinterface.setWriteConsole(rinterface.consolePrint)
 
+    def testSetReadConsole(self):
+        yes = "yes\n"
+        def sayyes(prompt):
+            return(yes)
+        rinterface.setReadConsole(sayyes)
+        res = rinterface.baseNameSpaceEnv["readline"]()
+        self.assertEquals(yes.strip(), res[0])
+        rinterface.setReadConsole(rinterface.consoleRead)
+
     def testCallErrorWhenEndedR(self):
         t = rinterface.baseNameSpaceEnv['date']
         rinterface.endEmbeddedR(1)

Modified: branches/rpy_nextgen/setup.py
===================================================================
--- branches/rpy_nextgen/setup.py       2008-08-03 18:14:48 UTC (rev 613)
+++ branches/rpy_nextgen/setup.py       2008-08-04 19:17:23 UTC (rev 614)
@@ -4,7 +4,7 @@
 
 
 pack_name = 'rpy2'
-pack_version = '2.0.0-a2'
+pack_version = '2.0.0-dev'
 
 RHOMES = os.getenv('RHOMES')
 
@@ -99,11 +99,13 @@
         define_macros.append(('R_INTERFACE_PTRS', 1))
 
     define_macros.append(('CSTACK_DEFNS', 1))
+    define_macros.append(('RIF_HAS_RSIGHAND', 1))
 
     # defines for debugging
     #define_macros.append(('RPY_DEBUG_PRESERVE', 1))
     #define_macros.append(('RPY_DEBUG_PROMISE', 1))
     #define_macros.append(('RPY_DEBUG_OBJECTINIT', 1))
+    #define_macros.append(('RPY_DEBUG_CONSOLE', 1))
 
     
     rinterface_ext = Extension(


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

Reply via email to