Skip to content
Snippets Groups Projects
Commit 3df7157f authored by olivier stasse's avatar olivier stasse
Browse files

Merge pull request #10 from francois-keith/master_2

Improve the interpreter
parents 4038b10c 4c192704
No related branches found
No related tags found
No related merge requests found
...@@ -45,6 +45,7 @@ ADD_REQUIRED_DEPENDENCY("dynamic-graph >= 2.5.5-6") ...@@ -45,6 +45,7 @@ ADD_REQUIRED_DEPENDENCY("dynamic-graph >= 2.5.5-6")
PKG_CONFIG_APPEND_LIBS("dynamic-graph-python") PKG_CONFIG_APPEND_LIBS("dynamic-graph-python")
# Search for Boost. # Search for Boost.
SET(BOOST_COMPONENTS python filesystem system thread program_options unit_test_framework)
SEARCH_FOR_BOOST() SEARCH_FOR_BOOST()
# Make sure Boost.Filesystem v2 is used. # Make sure Boost.Filesystem v2 is used.
......
...@@ -51,6 +51,7 @@ namespace dynamicgraph { ...@@ -51,6 +51,7 @@ namespace dynamicgraph {
/// \brief Method to exectue a python script. /// \brief Method to exectue a python script.
/// \param filename the filename /// \param filename the filename
void runPythonFile( std::string filename ); void runPythonFile( std::string filename );
void runPythonFile( std::string filename, std::string& err);
void runMain( void ); void runMain( void );
/// \brief Process input stream to send relevant blocks to python /// \brief Process input stream to send relevant blocks to python
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
#include "dynamic-graph/python/interpreter.hh" #include "dynamic-graph/python/interpreter.hh"
#include "link-to-python.hh" #include "link-to-python.hh"
#include <boost/python/errors.hpp>
#include <boost/python/object.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/extract.hpp>
using namespace boost::python;
std::ofstream dg_debugfile( "/tmp/dynamic-graph-traces.txt", std::ios::trunc&std::ios::out ); std::ofstream dg_debugfile( "/tmp/dynamic-graph-traces.txt", std::ios::trunc&std::ios::out );
// Python initialization commands // Python initialization commands
...@@ -136,6 +143,8 @@ Interpreter::Interpreter() ...@@ -136,6 +143,8 @@ Interpreter::Interpreter()
PyRun_SimpleString(pythonPrefix[2].c_str()); PyRun_SimpleString(pythonPrefix[2].c_str());
PyRun_SimpleString(pythonPrefix[3].c_str()); PyRun_SimpleString(pythonPrefix[3].c_str());
PyRun_SimpleString(pythonPrefix[4].c_str()); PyRun_SimpleString(pythonPrefix[4].c_str());
PyRun_SimpleString("import linecache");
traceback_format_exception_ = PyDict_GetItemString traceback_format_exception_ = PyDict_GetItemString
(PyModule_GetDict(PyImport_AddModule("traceback")), "format_exception"); (PyModule_GetDict(PyImport_AddModule("traceback")), "format_exception");
assert(PyCallable_Check(traceback_format_exception_)); assert(PyCallable_Check(traceback_format_exception_));
...@@ -229,14 +238,66 @@ PyObject* Interpreter::globals() ...@@ -229,14 +238,66 @@ PyObject* Interpreter::globals()
void Interpreter::runPythonFile( std::string filename ) void Interpreter::runPythonFile( std::string filename )
{ {
std::string err = "";
runPythonFile(filename, err);
}
void Interpreter::runPythonFile( std::string filename, std::string& err)
{
err = "";
PyObject* pymainContext = globals_; PyObject* pymainContext = globals_;
PyRun_File(fopen( filename.c_str(),"r" ), filename.c_str(), PyObject* run = PyRun_FileExFlags(fopen( filename.c_str(),"r" ), filename.c_str(),
Py_file_input, pymainContext,pymainContext); Py_file_input, pymainContext,pymainContext, true, NULL);
if (PyErr_Occurred()) if (PyErr_Occurred())
{ {
std::cout << "Error occures..." << std::endl; PyObject *ptype, *pvalue, *ptraceback;
PyErr_Print(); PyErr_Fetch(&ptype, &pvalue, &ptraceback);
handle<> hTraceback(ptraceback);
object traceback(hTraceback);
//Extract error message
std::string strErrorMessage = extract<std::string>(pvalue);
std::ostringstream errstream;
//TODO does not work for now for a single command.
do
{
//Extract line number (top entry of call stack)
// if you want to extract another levels of call stack
// also process traceback.attr("tb_next") recurently
long lineno = extract<long> (traceback.attr("tb_lineno"));
std::string filename = extract<std::string>
(traceback.attr("tb_frame").attr("f_code").attr("co_filename"));
std::string funcname = extract<std::string>
(traceback.attr("tb_frame").attr("f_code").attr("co_name"));
errstream << " File \"" << filename <<"\", line "
<< lineno << ", in "<< funcname << std::endl;
// get the corresponding line.
std::ostringstream cmd;
cmd << "linecache.getline('"<<filename<<"', "<<lineno <<")";
PyObject* line_obj = PyRun_String(cmd.str().c_str(),
Py_eval_input, globals_, globals_);
std::string line = PyString_AsString(line_obj);
Py_DecRef(line_obj);
// remove the spaces at the beginning of the line.
size_t index = line.find_first_not_of (" \t");
errstream << " " << line.substr(index, line.size()-index);
// go to the next line.
traceback = traceback.attr("tb_next");
}
while (traceback);
// recreate the error message
errstream << strErrorMessage << std::endl;
err =errstream.str();
std::cerr << err;
} }
Py_DecRef(run);
} }
void Interpreter::runMain( void ) void Interpreter::runMain( void )
......
...@@ -26,10 +26,21 @@ ADD_DEFINITIONS(${DYNAMIC_GRAPH_CFLAGS}) ...@@ -26,10 +26,21 @@ ADD_DEFINITIONS(${DYNAMIC_GRAPH_CFLAGS})
SET(EXECUTABLE_NAME interpreter-test) SET(EXECUTABLE_NAME interpreter-test)
ADD_EXECUTABLE(${EXECUTABLE_NAME} interpreter-test.cc) ADD_EXECUTABLE(${EXECUTABLE_NAME} interpreter-test.cc)
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} dynamic-graph-python) TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} dynamic-graph-python)
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} ${DYNAMIC_GRAPH_LIBRARIES} -lpthread -ldl -lutil) ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME})
## Test runfile
SET(EXECUTABLE_NAME interpreter-test-runfile)
ADD_EXECUTABLE(${EXECUTABLE_NAME} interpreter-test-runfile.cc)
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} dynamic-graph-python)
ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME}) ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME})
ADD_CUSTOM_COMMAND(TARGET interpreter-test-runfile POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/unitTesting/test_python_ok.py
${CMAKE_BINARY_DIR}/unitTesting
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/unitTesting/test_python_error.py
${CMAKE_BINARY_DIR}/unitTesting
)
// The purpose of this unit test is to check the interpreter::runPythonFile method
#include <cstring>
#include <iostream>
#include "dynamic-graph/python/interpreter.hh"
int main(int argc, char ** argv)
{
// execute numerous time the same file.
// While running 1025, we can notice a change in the error.
// unfortunately, it can not be shown using a redirection of the streams
int numTest = 1025;
if (argc > 1)
numTest = atoi(argv[1]);
std::string empty_err = "";
dynamicgraph::python::Interpreter interp;
for (int i=0; i<numTest; ++i)
{
interp.runPythonFile("test_python_ok.py", empty_err);
if (empty_err != "")
{
std::cerr << "At iteration " << i << ", the error was not empty:" << std::endl;
std::cerr << " err " << empty_err << std::endl;
return -1;
}
}
// check that the error remains the same, despite of the number of executions
std::string old_err;
interp.runPythonFile("test_python_error.py", old_err);
std::string new_err = old_err;
for (int i=0; i<numTest; ++i)
{
interp.runPythonFile("test_python_error.py", new_err);
if (old_err != new_err)
{
std::cerr << "At iteration " << i << ", the error changed:" << std::endl;
std::cerr << " old " << old_err << std::endl;
std::cerr << " new " << new_err << std::endl;
return -1;
}
}
return 0;
}
import sys, os
pkgConfigPath = os.environ.get("PKG_CONFIG_PATH")
if pkgConfigPath == None:
pkgConfigPath = ''
pathList = re.split(':', pkgConfigPath)
print pathList
import sys, os
import re
pkgConfigPath = os.environ.get("PKG_CONFIG_PATH")
if pkgConfigPath == None:
pkgConfigPath = ''
pathList = re.split(':', pkgConfigPath)
print pathList
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment