Integrated python 2.6 interpreter in modules/python. The integration is much simpler than before as it now uses kernel dynamic values and lambda functions to call from/to python.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@895953 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bedb446cef
commit
aea45d9976
8 changed files with 806 additions and 2 deletions
|
|
@ -124,6 +124,20 @@ AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed htt
|
|||
])
|
||||
AC_SUBST(HTTPD_INCLUDE)
|
||||
|
||||
# Configure PYTHON_INCLUDE and PYTHON_LIB
|
||||
AC_MSG_CHECKING([for python])
|
||||
AC_ARG_WITH([curl], [AC_HELP_STRING([--with-python=PATH], [path to installed python 2.6 [default=/usr]])], [
|
||||
PYTHON_INCLUDE="${withval}/include"
|
||||
PYTHON_LIB="${withval}/lib"
|
||||
AC_MSG_RESULT("${withval}")
|
||||
], [
|
||||
PYTHON_INCLUDE="/usr/include"
|
||||
PYTHON_LIB="/usr/lib"
|
||||
AC_MSG_RESULT(/usr)
|
||||
])
|
||||
AC_SUBST(PYTHON_INCLUDE)
|
||||
AC_SUBST(PYTHON_LIB)
|
||||
|
||||
# Checks for libraries.
|
||||
original_LIBS="${LIBS}"
|
||||
AC_MSG_NOTICE([checking for libraries])
|
||||
|
|
@ -138,6 +152,8 @@ AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([couldn't find a suitabl
|
|||
LIBS="-L${APR_LIB} ${original_LIBS}"
|
||||
AC_CHECK_LIB([apr-1], [apr_pool_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])])
|
||||
AC_CHECK_LIB([aprutil-1], [apr_memcache_replace], [], [AC_MSG_ERROR([couldn't find a suitable libaprutil-1, use --with-apr=PATH])])
|
||||
LIBS="-L${PYTHON_LIB} ${original_LIBS}"
|
||||
AC_CHECK_LIB([python2.6], [Py_Initialize], [], [AC_MSG_ERROR([couldn't find a suitable libpython2.6, use --with-python=PATH])])
|
||||
LIBS="${original_LIBS}"
|
||||
|
||||
# Checks for header files.
|
||||
|
|
@ -175,7 +191,7 @@ AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [comp
|
|||
esac ],
|
||||
[ AC_MSG_RESULT(no)])
|
||||
if test "${want_maintainer_mode}" = "true"; then
|
||||
cxxflags="${cxxflags} -D_DEBUG -O0 -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0"
|
||||
cxxflags="${cxxflags} -D_DEBUG -O0 -ggdb -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0"
|
||||
ldflags="${ldflags} -pg"
|
||||
else
|
||||
cxxflags="${cxxflags} -O3 -std=c++0x -fmessage-length=0"
|
||||
|
|
@ -256,9 +272,10 @@ AC_CONFIG_FILES([Makefile
|
|||
kernel/Makefile
|
||||
modules/Makefile
|
||||
modules/atom/Makefile
|
||||
modules/eval/Makefile
|
||||
modules/scheme/Makefile
|
||||
modules/http/Makefile
|
||||
modules/json/Makefile
|
||||
modules/python/Makefile
|
||||
modules/scdl/Makefile
|
||||
modules/server/Makefile
|
||||
components/Makefile
|
||||
|
|
|
|||
31
sca-cpp/trunk/modules/python/Makefile.am
Normal file
31
sca-cpp/trunk/modules/python/Makefile.am
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
noinst_PROGRAMS = python-test python-shell
|
||||
|
||||
datadir=$(prefix)/modules/python
|
||||
nobase_data_DATA = *.xsd
|
||||
|
||||
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${PYTHON_INCLUDE}
|
||||
|
||||
python_test_SOURCES = python-test.cpp
|
||||
python_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${PYTHON_LIB} -lpython2.6
|
||||
|
||||
python_shell_SOURCES = python-shell.cpp
|
||||
python_shell_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${PYTHON_LIB} -lpython2.6
|
||||
|
||||
TESTS = python-test
|
||||
85
sca-cpp/trunk/modules/python/driver.hpp
Normal file
85
sca-cpp/trunk/modules/python/driver.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* $Rev$ $Date$ */
|
||||
|
||||
#ifndef tuscany_python_pydriver_hpp
|
||||
#define tuscany_python_pydriver_hpp
|
||||
|
||||
/**
|
||||
* Python evaluator main driver loop.
|
||||
*/
|
||||
|
||||
#include "string.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "monad.hpp"
|
||||
#include "eval.hpp"
|
||||
|
||||
namespace tuscany {
|
||||
namespace python {
|
||||
|
||||
const string evalOutputPrompt("; ");
|
||||
const string evalInputPrompt("=> ");
|
||||
|
||||
const bool promptForInput(const string& str, ostream& out) {
|
||||
out << endl << endl << str;
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool announceOutput(const string str, ostream& out) {
|
||||
out << endl << str;
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool userPrint(const value val, ostream& out) {
|
||||
writeValue(val, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
const value evalDriverLoop(PyObject* script, istream& in, ostream& out, const gc_pool& pool) {
|
||||
promptForInput(evalInputPrompt, out);
|
||||
value input = readValue(in);
|
||||
if (isNil(input))
|
||||
return input;
|
||||
const value output = evalScript(input, script, pool);
|
||||
announceOutput(evalOutputPrompt, out);
|
||||
userPrint(output, out);
|
||||
return evalDriverLoop(script, in, out, pool);
|
||||
}
|
||||
|
||||
const bool evalDriverRun(istream& in, ostream& out, const gc_pool& pool) {
|
||||
setupDisplay(out);
|
||||
evalDriverLoop(builtin(pythonRuntime), in, out, pool);
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool evalDriverRun(const char* path, istream& in, ostream& out, const gc_pool& pool) {
|
||||
setupDisplay(out);
|
||||
ifstream is(path);
|
||||
failable<PyObject*> script = readScript(path, is);
|
||||
if (!hasContent(script))
|
||||
return true;
|
||||
evalDriverLoop(content(script), in, out, pool);
|
||||
Py_DECREF(content(script));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* tuscany_scheme_pydriver_hpp */
|
||||
286
sca-cpp/trunk/modules/python/eval.hpp
Normal file
286
sca-cpp/trunk/modules/python/eval.hpp
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* $Rev$ $Date$ */
|
||||
|
||||
#ifndef tuscany_python_pyeval_hpp
|
||||
#define tuscany_python_pyeval_hpp
|
||||
|
||||
/**
|
||||
* Python script evaluation logic.
|
||||
*/
|
||||
#include <python2.6/Python.h>
|
||||
|
||||
#include "list.hpp"
|
||||
#include "value.hpp"
|
||||
#include "io.hpp"
|
||||
|
||||
namespace tuscany {
|
||||
namespace python {
|
||||
|
||||
/**
|
||||
* Initialize the Python runtime.
|
||||
*/
|
||||
class PythonRuntime {
|
||||
public:
|
||||
PythonRuntime() {
|
||||
Py_Initialize();
|
||||
|
||||
// Import the builtin module
|
||||
PyObject* p = PyString_FromString("__builtin__");
|
||||
builtin = PyImport_Import(p);
|
||||
Py_DECREF(p);
|
||||
|
||||
setupIO();
|
||||
}
|
||||
|
||||
~PythonRuntime() {
|
||||
Py_DECREF(builtin);
|
||||
}
|
||||
|
||||
private:
|
||||
friend PyObject* builtin(const PythonRuntime& r);
|
||||
|
||||
PyObject* builtin;
|
||||
|
||||
} pythonRuntime;
|
||||
|
||||
PyObject* builtin(const PythonRuntime& r) {
|
||||
return r.builtin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare conversion functions.
|
||||
*/
|
||||
PyObject* valueToPyObject(const value& v);
|
||||
const value pyObjectToValue(PyObject *o);
|
||||
PyObject* valuesToPyTuple(const list<value>& v);
|
||||
const list<value> pyTupleToValues(PyObject* o);
|
||||
|
||||
/**
|
||||
* Callable python type used to represent a lambda expression.
|
||||
*/
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
lambda<value(const list<value>&)> func;
|
||||
} pyLambda;
|
||||
|
||||
void pyLambda_dealloc(PyObject* self) {
|
||||
PyMem_DEL(self);
|
||||
}
|
||||
|
||||
PyObject* pyLambda_call(PyObject* self, PyObject* args, unused PyObject* kwds) {
|
||||
const pyLambda* pyl = (pyLambda*)self;
|
||||
const value result = pyl->func(pyTupleToValues(args));
|
||||
Py_DECREF(args);
|
||||
PyObject *pyr = valueToPyObject(result);
|
||||
return pyr;
|
||||
}
|
||||
|
||||
PyTypeObject pyLambda_type = {
|
||||
PyObject_HEAD_INIT(0)
|
||||
0,
|
||||
"lambda",
|
||||
sizeof(pyLambda),
|
||||
0,
|
||||
(destructor)pyLambda_dealloc,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
(ternaryfunc)pyLambda_call,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new python object representing a lambda expression.
|
||||
*/
|
||||
PyObject *mkPyLambda(const lambda<value(const list<value>&)> l) {
|
||||
pyLambda* pyl = NULL;
|
||||
pyl = PyObject_NEW(pyLambda, &pyLambda_type);
|
||||
if (pyl != NULL)
|
||||
pyl->func = l;
|
||||
return (PyObject *)pyl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a list of values to a python list.
|
||||
*/
|
||||
|
||||
PyObject* valuesToPyListHelper(PyObject* l, const list<value>& v) {
|
||||
if (isNil(v))
|
||||
return l;
|
||||
PyList_Append(l, valueToPyObject(car(v)));
|
||||
return valuesToPyListHelper(l, cdr(v));
|
||||
}
|
||||
|
||||
PyObject* valuesToPyTuple(const list<value>& v) {
|
||||
return PyList_AsTuple(valuesToPyListHelper(PyList_New(0), v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value to a python object.
|
||||
*/
|
||||
PyObject* valueToPyObject(const value& v) {
|
||||
switch (type(v)) {
|
||||
case value::List:
|
||||
return valuesToPyTuple(v);
|
||||
case value::Lambda:
|
||||
return mkPyLambda(v);
|
||||
case value::Symbol:
|
||||
case value::String:
|
||||
return PyString_FromString(c_str(v));
|
||||
case value::Number:
|
||||
return PyFloat_FromDouble((double)v);
|
||||
case value::Bool:
|
||||
return (bool)v? Py_True : Py_False;
|
||||
case value::Char:
|
||||
return PyInt_FromLong((long)((char)v));
|
||||
case value::Ptr:
|
||||
return NULL;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a python tuple to a list of values.
|
||||
*/
|
||||
|
||||
const list<value> pyTupleToValuesHelper(PyObject* o, int i, int size) {
|
||||
if (i == size)
|
||||
return list<value>();
|
||||
return cons(pyObjectToValue(PyTuple_GetItem(o, i)), pyTupleToValuesHelper(o, i + 1, size));
|
||||
}
|
||||
|
||||
const list<value> pyTupleToValues(PyObject* o) {
|
||||
return pyTupleToValuesHelper(o, 0, PyTuple_Size(o));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lambda function used to represent a python callable object.
|
||||
*/
|
||||
struct pyCallable {
|
||||
PyObject* func;
|
||||
|
||||
pyCallable(PyObject* func) : func(func) {
|
||||
Py_INCREF(func);
|
||||
}
|
||||
|
||||
~pyCallable() {
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
const value operator()(const list<value>& args) const {
|
||||
PyObject* pyargs = valuesToPyTuple(args);
|
||||
PyObject* result = PyObject_CallObject(func, pyargs);
|
||||
Py_DECREF(pyargs);
|
||||
const value v = pyObjectToValue(result);
|
||||
Py_DECREF(result);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a python object to a value.
|
||||
*/
|
||||
const value pyObjectToValue(PyObject *o) {
|
||||
if (PyString_Check(o))
|
||||
return value(string(PyString_AsString(o)));
|
||||
if (PyBool_Check(o))
|
||||
return value(o == Py_True);
|
||||
if (PyInt_Check(o))
|
||||
return value((double)PyInt_AsLong(o));
|
||||
if (PyLong_Check(o))
|
||||
return value((double)PyLong_AsLong(o));
|
||||
if (PyFloat_Check(o))
|
||||
return value((double)PyFloat_AsDouble(o));
|
||||
if (PyTuple_Check(o))
|
||||
return pyTupleToValues(o);
|
||||
if (PyCallable_Check(o))
|
||||
return lambda<value(const list<value>&)>(pyCallable(o));
|
||||
return value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a python script from an input stream.
|
||||
*/
|
||||
const failable<PyObject*> readScript(const string& path, istream& is) {
|
||||
const list<string> ls = streamList(is);
|
||||
ostringstream os;
|
||||
write(ls, os);
|
||||
PyObject* code = Py_CompileStringFlags(c_str(str(os)), c_str(path), Py_file_input, NULL);
|
||||
if (code == NULL)
|
||||
return mkfailure<PyObject*>(string("Couldn't compile script: ") + path + " : " + lastError());
|
||||
PyObject* mod = PyImport_ExecCodeModule(const_cast<char*>(c_str(path)), code);
|
||||
if (mod == NULL)
|
||||
return mkfailure<PyObject*>(string("Couldn't import module: ") + path + " : " + lastError());
|
||||
return mod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression against a script provided as a python object.
|
||||
*/
|
||||
const failable<value> evalScript(const value& expr, PyObject* script, unused const gc_pool& pool) {
|
||||
|
||||
// Get the requested function
|
||||
PyObject* func = PyObject_GetAttrString(script, c_str(car<value>(expr)));
|
||||
if (func == NULL)
|
||||
return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastError());
|
||||
if (!PyCallable_Check(func)) {
|
||||
Py_DECREF(func);
|
||||
return mkfailure<value>(string("Couldn't find callable function: ") + car<value>(expr));
|
||||
}
|
||||
|
||||
// Convert args to python objects
|
||||
PyObject* args = valuesToPyTuple(cdr<value>(expr));
|
||||
|
||||
// Call the function
|
||||
PyObject* result = PyObject_CallObject(func, args);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(func);
|
||||
if (result == NULL)
|
||||
return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + lastError());
|
||||
|
||||
// Convert python result to a value
|
||||
const value v = pyObjectToValue(result);
|
||||
Py_DECREF(result);
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression against a script provided as an input stream.
|
||||
*/
|
||||
const failable<value> evalScript(const value& expr, istream& is, unused const gc_pool& pool) {
|
||||
failable<PyObject*> script = readScript("script", is);
|
||||
if (!hasContent(script))
|
||||
return mkfailure<value>(reason(script));
|
||||
return evalScript(expr, content(script), pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression against the python builtin module, no script is provided.
|
||||
*/
|
||||
const failable<value> evalExpr(const value& expr, const gc_pool& pool) {
|
||||
return evalScript(expr, builtin(pythonRuntime), pool);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* tuscany_python_pyeval_hpp */
|
||||
167
sca-cpp/trunk/modules/python/io.hpp
Normal file
167
sca-cpp/trunk/modules/python/io.hpp
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* $Rev$ $Date$ */
|
||||
|
||||
#ifndef tuscany_python_pyio_hpp
|
||||
#define tuscany_python_pyio_hpp
|
||||
|
||||
/**
|
||||
* Hooks used to capture python stdout and stderr.
|
||||
*/
|
||||
#include <python2.6/Python.h>
|
||||
|
||||
#include "stream.hpp"
|
||||
#include "../scheme/io.hpp"
|
||||
|
||||
namespace tuscany {
|
||||
namespace python {
|
||||
|
||||
#ifdef _REENTRANT
|
||||
__thread
|
||||
#endif
|
||||
ostream* displayOutStream = NULL;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
__thread
|
||||
#endif
|
||||
ostream* logOutStream = NULL;
|
||||
|
||||
/**
|
||||
* Setup the display stream.
|
||||
*/
|
||||
const bool setupDisplay(ostream& out) {
|
||||
scheme::setupDisplay(out);
|
||||
displayOutStream = &out;
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& displayStream() {
|
||||
if (displayOutStream == NULL)
|
||||
return cout;
|
||||
return *displayOutStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the log stream.
|
||||
*/
|
||||
const bool setupLog(ostream& out) {
|
||||
scheme::setupLog(out);
|
||||
logOutStream = &out;
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& logStream() {
|
||||
if (logOutStream == NULL)
|
||||
return cerr;
|
||||
return *logOutStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method used to redirect python output to a stream.
|
||||
*/
|
||||
PyObject* display(unused PyObject* self, PyObject* args) {
|
||||
char* s = NULL;
|
||||
if (!PyArg_ParseTuple(args, "s", &s))
|
||||
return NULL;
|
||||
|
||||
displayStream() << s;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyMethodDef displayHookMethods[] = {
|
||||
{"display", display, METH_VARARGS, "Redirects stdout"},
|
||||
{NULL, NULL, 0, NULL}};
|
||||
|
||||
/**
|
||||
* Hook method used to redirect python errors to a stream.
|
||||
*/
|
||||
PyObject* log(unused PyObject* self, PyObject* args) {
|
||||
char* s = NULL;
|
||||
if (!PyArg_ParseTuple(args, "s", &s))
|
||||
return NULL;
|
||||
|
||||
logStream() << s;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyMethodDef logHookMethods[] = {
|
||||
{"log", log, METH_VARARGS, "Redirects stdout"},
|
||||
{NULL, NULL, 0, NULL}};
|
||||
|
||||
/**
|
||||
* Setup the display and log hooks.
|
||||
*/
|
||||
bool setupIO() {
|
||||
Py_InitModule("displayhook", displayHookMethods);
|
||||
PyRun_SimpleString(
|
||||
"import sys\n"
|
||||
"import displayhook\n"
|
||||
"\n"
|
||||
"class DisplayHook:\n"
|
||||
" def write(self, text):\n"
|
||||
" displayhook.display(text)\n"
|
||||
"\n"
|
||||
"sys.stdout = DisplayHook()\n");
|
||||
|
||||
Py_InitModule("loghook", logHookMethods);
|
||||
PyRun_SimpleString(
|
||||
"import sys\n"
|
||||
"import loghook\n"
|
||||
"\n"
|
||||
"class LogHook:\n"
|
||||
" def write(self, text):\n"
|
||||
" loghook.log(text)\n"
|
||||
"\n"
|
||||
"sys.stderr = LogHook()\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last python error.
|
||||
*/
|
||||
const string lastError() {
|
||||
ostream* pos = logOutStream;
|
||||
ostringstream eos;
|
||||
logOutStream = &eos;
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
logOutStream = pos;
|
||||
return str(eos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and write values (using the scheme representation as it's the canonical
|
||||
* representation used throughout the runtime.)
|
||||
*/
|
||||
const value readValue(istream& in) {
|
||||
return scheme::readValue(in);
|
||||
}
|
||||
|
||||
const bool writeValue(const value& val, ostream& out) {
|
||||
return scheme::writeValue(val, out);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* tuscany_python_pyio_hpp */
|
||||
40
sca-cpp/trunk/modules/python/python-shell.cpp
Normal file
40
sca-cpp/trunk/modules/python/python-shell.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* $Rev$ $Date$ */
|
||||
|
||||
/**
|
||||
* Python script evaluator shell, used for interactive testing of scripts.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "gc.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "string.hpp"
|
||||
#include "driver.hpp"
|
||||
|
||||
int main(const int argc, char** argv) {
|
||||
tuscany::gc_scoped_pool pool;
|
||||
if (argc == 1) {
|
||||
tuscany::python::evalDriverRun(tuscany::cin, tuscany::cout, pool);
|
||||
return 0;
|
||||
}
|
||||
tuscany::python::evalDriverRun(argv[1], tuscany::cin, tuscany::cout, pool);
|
||||
return 0;
|
||||
}
|
||||
135
sca-cpp/trunk/modules/python/python-test.cpp
Normal file
135
sca-cpp/trunk/modules/python/python-test.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* $Rev$ $Date$ */
|
||||
|
||||
/**
|
||||
* Test Python script evaluator.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "stream.hpp"
|
||||
#include "string.hpp"
|
||||
#include "driver.hpp"
|
||||
|
||||
namespace tuscany {
|
||||
namespace python {
|
||||
|
||||
const value evalBuiltin(const string& py, const gc_pool& pool) {
|
||||
istringstream is(py);
|
||||
ostringstream os;
|
||||
evalDriverRun(is, os, pool);
|
||||
return str(os);
|
||||
}
|
||||
|
||||
const string testPythonPrint(
|
||||
"(print \"testPrint ok\")");
|
||||
|
||||
bool testEval() {
|
||||
gc_scoped_pool pool;
|
||||
assert(contains(evalBuiltin(testPythonPrint, pool), "testPrint ok"));
|
||||
return true;
|
||||
}
|
||||
|
||||
const string testPythonAdd =
|
||||
"def add(x, y):\n"
|
||||
" return x + y\n";
|
||||
|
||||
bool testEvalExpr() {
|
||||
gc_scoped_pool pool;
|
||||
{
|
||||
const value exp = mklist<value>("abs", -5);
|
||||
const failable<value> r = evalExpr(exp, pool);
|
||||
assert(hasContent(r));
|
||||
assert(content(r) == value(5));
|
||||
}
|
||||
{
|
||||
istringstream is(testPythonAdd);
|
||||
failable<PyObject*> script = readScript("script", is);
|
||||
assert(hasContent(script));
|
||||
const value exp = mklist<value>("add", 2, 3);
|
||||
const failable<value> r = evalScript(exp, content(script), pool);
|
||||
assert(hasContent(r));
|
||||
assert(content(r) == value(5));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool testEvalRun() {
|
||||
gc_scoped_pool pool;
|
||||
evalDriverRun(cin, cout, pool);
|
||||
return true;
|
||||
}
|
||||
|
||||
const value mult(const list<value>& args) {
|
||||
const double x = car(args);
|
||||
const double y = cadr(args);
|
||||
return x * y;
|
||||
}
|
||||
|
||||
const string testReturnLambda(
|
||||
"def mul(x, y):\n"
|
||||
" return x * y\n"
|
||||
"\n"
|
||||
"def testReturnLambda():\n"
|
||||
" return mul\n");
|
||||
|
||||
const string testCallLambda(
|
||||
"def testCallLambda(l, x, y):\n"
|
||||
" return l(x, y)\n");
|
||||
|
||||
bool testEvalLambda() {
|
||||
gc_scoped_pool pool;
|
||||
|
||||
const value trl = mklist<value>("testReturnLambda");
|
||||
istringstream trlis(testReturnLambda);
|
||||
const failable<value> trlv = evalScript(trl, trlis, pool);
|
||||
|
||||
assert(hasContent(trlv));
|
||||
assert(isLambda(content(trlv)));
|
||||
const lambda<value(const list<value>&)> trll(content(trlv));
|
||||
assert(trll(mklist<value>(2, 3)) == value(6));
|
||||
|
||||
istringstream tclis(testCallLambda);
|
||||
const value tcl = mklist<value>("testCallLambda", content(trlv), 2, 3);
|
||||
const failable<value> tclv = evalScript(tcl, tclis, pool);
|
||||
assert(hasContent(tclv));
|
||||
assert(content(tclv) == value(6));
|
||||
|
||||
istringstream tcelis(testCallLambda);
|
||||
const value tcel = mklist<value>("testCallLambda", lambda<value(const list<value>&)>(mult), 3, 4);
|
||||
const failable<value> tcelv = evalScript(tcel, tcelis, pool);
|
||||
assert(hasContent(tcelv));
|
||||
assert(content(tcelv) == value(12));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
tuscany::cout << "Testing..." << tuscany::endl;
|
||||
|
||||
tuscany::python::testEval();
|
||||
tuscany::python::testEvalExpr();
|
||||
tuscany::python::testEvalLambda();
|
||||
|
||||
tuscany::cout << "OK" << tuscany::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://tuscany.apache.org/xmlns/sca/1.1"
|
||||
xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200903"
|
||||
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<import namespace="http://docs.oasis-open.org/ns/opencsa/sca/200903" schemaLocation="sca-1.1-cd04.xsd"/>
|
||||
|
||||
<element name="implementation.python" type="t:PythonImplementation" substitutionGroup="sca:implementation"/>
|
||||
|
||||
<complexType name="PythonImplementation">
|
||||
<complexContent>
|
||||
<extension base="sca:Implementation">
|
||||
<sequence>
|
||||
<any namespace="##targetNamespace" processContents="lax"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="location" type="anyURI" use="required"/>
|
||||
<anyAttribute namespace="##any" processContents="lax"/>
|
||||
</extension>
|
||||
</complexContent>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
Loading…
Add table
Add a link
Reference in a new issue