Skip to content
Snippets Groups Projects
Unverified Commit bd7264b9 authored by olivier stasse's avatar olivier stasse Committed by GitHub
Browse files

Merge pull request #23 from jmirabel/master

[Interpreter] Ignore empty command and Python comments.
parents 3204d735 c8be57af
No related branches found
No related tags found
No related merge requests found
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <boost/python/str.hpp> #include <boost/python/str.hpp>
#include <boost/python/import.hpp> #include <boost/python/import.hpp>
using namespace boost::python;
namespace py=boost::python; namespace py=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 );
...@@ -164,10 +163,44 @@ Interpreter::Interpreter() ...@@ -164,10 +163,44 @@ Interpreter::Interpreter()
Interpreter::~Interpreter() Interpreter::~Interpreter()
{ {
PyEval_RestoreThread(_pyState); PyEval_RestoreThread(_pyState);
//Py_DECREF(mainmod_);
//Py_DECREF(globals_); // Ideally, we should call Py_Finalize but this is not really supported by
//Py_DECREF(traceback_format_exception_); // Python.
Py_Finalize(); // Instead, we merelly remove variables.
// Code was taken here: https://github.com/numpy/numpy/issues/8097#issuecomment-356683953
{
PyObject * poAttrList = PyObject_Dir(mainmod_);
PyObject * poAttrIter = PyObject_GetIter(poAttrList);
PyObject * poAttrName;
while ((poAttrName = PyIter_Next(poAttrIter)) != NULL)
{
std::string oAttrName (PyString_AS_STRING(poAttrName));
// Make sure we don't delete any private objects.
if (oAttrName.compare( 0,2,"__")!=0 ||
oAttrName.compare(oAttrName.size()-2,2,"__")!=0)
{
PyObject * poAttr = PyObject_GetAttr(mainmod_, poAttrName);
// Make sure we don't delete any module objects.
if (poAttr && poAttr->ob_type != mainmod_->ob_type)
PyObject_SetAttr(mainmod_, poAttrName, NULL);
Py_DecRef(poAttr);
}
Py_DecRef(poAttrName);
}
Py_DecRef(poAttrIter);
Py_DecRef(poAttrList);
}
Py_DECREF(mainmod_);
Py_DECREF(globals_);
Py_DECREF(traceback_format_exception_);
//Py_Finalize();
} }
std::string Interpreter::python( const std::string& command ) std::string Interpreter::python( const std::string& command )
...@@ -185,6 +218,13 @@ void Interpreter::python( const std::string& command, std::string& res, ...@@ -185,6 +218,13 @@ void Interpreter::python( const std::string& command, std::string& res,
out = ""; out = "";
err = ""; err = "";
// Check if the command is not a python comment or empty.
std::string::size_type iFirstNonWhite = command.find_first_not_of (" \t");
// Empty command
if (iFirstNonWhite == std::string::npos) return;
// Command is a comment. Ignore it.
if (command[iFirstNonWhite] == '#') return;
PyEval_RestoreThread(_pyState); PyEval_RestoreThread(_pyState);
std::cout << command.c_str() << std::endl; std::cout << command.c_str() << std::endl;
......
...@@ -32,6 +32,8 @@ ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME}) ...@@ -32,6 +32,8 @@ ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME})
SET(EXECUTABLE_NAME interpreter-test-runfile) SET(EXECUTABLE_NAME interpreter-test-runfile)
ADD_EXECUTABLE(${EXECUTABLE_NAME} interpreter-test-runfile.cc) ADD_EXECUTABLE(${EXECUTABLE_NAME} interpreter-test-runfile.cc)
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} dynamic-graph-python) TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} dynamic-graph-python)
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} ${PYTHON_LIBRARY})
TARGET_LINK_BOOST_PYTHON(${EXECUTABLE_NAME})
ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME}) ADD_TEST(${EXECUTABLE_NAME} ${EXECUTABLE_NAME})
ADD_CUSTOM_COMMAND(TARGET interpreter-test-runfile POST_BUILD ADD_CUSTOM_COMMAND(TARGET interpreter-test-runfile POST_BUILD
......
...@@ -24,6 +24,28 @@ bool testFile(const std::string & filename, ...@@ -24,6 +24,28 @@ bool testFile(const std::string & filename,
return true; return true;
} }
bool testInterpreterDestructor(const std::string & filename,
const std::string & expectedOutput)
{
std::string err = "";
{
dynamicgraph::python::Interpreter interp;
interp.runPythonFile(filename, err);
}
{
dynamicgraph::python::Interpreter interp;
interp.runPythonFile(filename, err);
if (err != expectedOutput)
{
std::cerr << "The output was not the one expected:" << std::endl;
std::cerr << " expected: " << expectedOutput << std::endl;
std::cerr << " err: " << err << std::endl;
return false;
}
}
return true;
}
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
// execute numerous time the same file. // execute numerous time the same file.
...@@ -34,17 +56,23 @@ int main(int argc, char ** argv) ...@@ -34,17 +56,23 @@ int main(int argc, char ** argv)
numTest = atoi(argv[1]); numTest = atoi(argv[1]);
bool res = true; bool res = true;
res = testFile("test_python-ok.py", "", numTest) && res; // This test succeeds only because it is launched before "test_python-ok.py"
res = testFile("unexistant_file.py", // because re as been imported in a previous test and it is not
"unexistant_file.py cannot be open", // safe to delete imported module...
numTest) && res;
res = testFile("test_python-name_error.py", res = testFile("test_python-name_error.py",
std::string("<type 'exceptions.NameError'>: name 're' is not defined:")+ std::string("<type 'exceptions.NameError'>: name 're' is not defined:")+
" File \"test_python-name_error.py\", line 6, in <module>\n" + " File \"test_python-name_error.py\", line 6, in <module>\n" +
" pathList = re.split(':', pkgConfigPath)\n", numTest) && res; " pathList = re.split(':', pkgConfigPath)\n", numTest) && res;
res = testFile("test_python-ok.py", "", numTest) && res;
res = testFile("unexistant_file.py",
"unexistant_file.py cannot be open",
numTest) && res;
res = testFile("test_python-syntax_error.py", res = testFile("test_python-syntax_error.py",
std::string("<type 'exceptions.SyntaxError'>: ('invalid syntax', ")+ std::string("<type 'exceptions.SyntaxError'>: ('invalid syntax', ")+
"('test_python-syntax_error.py', 1, 11, "+ "('test_python-syntax_error.py', 1, 11, "+
"'hello world\\n'))", numTest) && res; "'hello world\\n'))", numTest) && res;
res = testInterpreterDestructor ("test_python-restart_interpreter.py",
"") && res;
return (res?0:1); return (res?0:1);
} }
# this causes troubles when Py_Finalize is called in Interpreter destructor.
import dynamic_graph.sot.core
# numpy causes troubles when Py_Finalize is called in Interpreter destructor.
import numpy
# Make sure the variable is deleted.
if "var" in locals() or "var" in globals():
raise ValueError('Not cleaned')
var = "This string should have been deleted."
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