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
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list