You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2010/01/05 10:16:31 UTC

svn commit: r895953 - in /tuscany/sca-cpp/trunk: ./ modules/python/

Author: jsdelfino
Date: Tue Jan  5 09:16:29 2010
New Revision: 895953

URL: http://svn.apache.org/viewvc?rev=895953&view=rev
Log:
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.

Added:
    tuscany/sca-cpp/trunk/modules/python/
    tuscany/sca-cpp/trunk/modules/python/Makefile.am
    tuscany/sca-cpp/trunk/modules/python/driver.hpp
    tuscany/sca-cpp/trunk/modules/python/eval.hpp
    tuscany/sca-cpp/trunk/modules/python/io.hpp
    tuscany/sca-cpp/trunk/modules/python/python-shell.cpp
    tuscany/sca-cpp/trunk/modules/python/python-test.cpp
    tuscany/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd
Modified:
    tuscany/sca-cpp/trunk/configure.ac

Modified: tuscany/sca-cpp/trunk/configure.ac
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/configure.ac?rev=895953&r1=895952&r2=895953&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/configure.ac (original)
+++ tuscany/sca-cpp/trunk/configure.ac Tue Jan  5 09:16:29 2010
@@ -124,6 +124,20 @@
 ])
 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 @@
 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 @@
   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 @@
                  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

Added: tuscany/sca-cpp/trunk/modules/python/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/Makefile.am?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/Makefile.am (added)
+++ tuscany/sca-cpp/trunk/modules/python/Makefile.am Tue Jan  5 09:16:29 2010
@@ -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

Added: tuscany/sca-cpp/trunk/modules/python/driver.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/driver.hpp?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/driver.hpp (added)
+++ tuscany/sca-cpp/trunk/modules/python/driver.hpp Tue Jan  5 09:16:29 2010
@@ -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 */

Added: tuscany/sca-cpp/trunk/modules/python/eval.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/eval.hpp?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/eval.hpp (added)
+++ tuscany/sca-cpp/trunk/modules/python/eval.hpp Tue Jan  5 09:16:29 2010
@@ -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 */

Added: tuscany/sca-cpp/trunk/modules/python/io.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/io.hpp?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/io.hpp (added)
+++ tuscany/sca-cpp/trunk/modules/python/io.hpp Tue Jan  5 09:16:29 2010
@@ -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 */

Added: tuscany/sca-cpp/trunk/modules/python/python-shell.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/python-shell.cpp?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/python-shell.cpp (added)
+++ tuscany/sca-cpp/trunk/modules/python/python-shell.cpp Tue Jan  5 09:16:29 2010
@@ -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;
+}

Added: tuscany/sca-cpp/trunk/modules/python/python-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/python-test.cpp?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/python-test.cpp (added)
+++ tuscany/sca-cpp/trunk/modules/python/python-test.cpp Tue Jan  5 09:16:29 2010
@@ -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;
+}

Added: tuscany/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd?rev=895953&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd (added)
+++ tuscany/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd Tue Jan  5 09:16:29 2010
@@ -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>