X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FParametersPlugin%2FParametersPlugin_PyInterp.cpp;h=054c8c3e2bdbe1b209c381d7f10551f928dd5c6d;hb=4d6bb9de0e54f09a9bbacc94a058cb7cd437d535;hp=c3546ea92d23a5fd92e14294527a6468dce03ea0;hpb=33b3a43ad2266cb044e4232c902344842adbba7c;p=modules%2Fshaper.git diff --git a/src/ParametersPlugin/ParametersPlugin_PyInterp.cpp b/src/ParametersPlugin/ParametersPlugin_PyInterp.cpp index c3546ea92..054c8c3e2 100644 --- a/src/ParametersPlugin/ParametersPlugin_PyInterp.cpp +++ b/src/ParametersPlugin/ParametersPlugin_PyInterp.cpp @@ -8,6 +8,7 @@ #include #include +#include ParametersPlugin_PyInterp::ParametersPlugin_PyInterp() : PyInterp_Interp() @@ -18,34 +19,60 @@ ParametersPlugin_PyInterp::~ParametersPlugin_PyInterp() { } -std::list ParametersPlugin_PyInterp::compile(const std::string& theExpression) +const char* aSearchCode = + "import ast\n" + "class FindName(ast.NodeVisitor):\n" + " def __init__(self, name):\n" + " self.name = name\n" + " def visit_Name(self, node):\n" + " if node.id == self.name:\n" + " positions.append((node.lineno, node.col_offset))\n" + "FindName(name).visit(ast.parse(expression))"; + +std::list > +ParametersPlugin_PyInterp::positions(const std::string& theExpression, + const std::string& theName) { - PyGILState_STATE aGilState = PyGILState_Ensure(); - std::list res = this->_compile(theExpression); - PyGILState_Release(aGilState); - return res; -} + PyLockWrapper lck; // Acquire GIL until the end of the method + + std::list > aResult; + + // prepare a context + PyObject* aContext = PyDict_New(); + PyObject* aBuiltinModule = PyImport_AddModule("__builtin__"); + PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule); + + // extend aContext with variables + PyDict_SetItemString(aContext, "expression", PyString_FromString(theExpression.c_str())); + PyDict_SetItemString(aContext, "name", PyString_FromString(theName.c_str())); + PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]")); + + // run the search code + PyObject* aExecResult = PyRun_String(aSearchCode, Py_file_input, aContext, aContext); + Py_XDECREF(aExecResult); + + // receive results from context + PyObject* aPositions = PyDict_GetItemString(aContext, "positions"); + for (int anIndex = 0; anIndex < PyList_Size(aPositions); ++anIndex) { + PyObject* aPosition = PyList_GetItem(aPositions, anIndex); + PyObject* aLineNo = PyTuple_GetItem(aPosition, 0); + PyObject* aColOffset = PyTuple_GetItem(aPosition, 1); + + aResult.push_back( + std::pair((int)PyInt_AsLong(aLineNo), + (int)PyInt_AsLong(aColOffset))); + } -void ParametersPlugin_PyInterp::extendLocalContext(const std::list& theParameters) -{ - PyGILState_STATE aGilState = PyGILState_Ensure(); - this->_extendLocalContext(theParameters); - PyGILState_Release(aGilState); -} + // TODO(spo): after this refCount of the variable is not 0. Is there memory leak? + Py_DECREF(aContext); -double ParametersPlugin_PyInterp::evaluate(const std::string& theExpression, - std::string& theError) -{ - PyGILState_STATE aGilState = PyGILState_Ensure(); - double res = this->_evaluate(theExpression, theError); - PyGILState_Release(aGilState); - return res; + return aResult; } -std::list ParametersPlugin_PyInterp::_compile(const std::string& theExpression) +std::list ParametersPlugin_PyInterp::compile(const std::string& theExpression) { - + PyLockWrapper lck; // Acquire GIL until the end of the method std::list aResult; PyObject *aCodeopModule = PyImport_AddModule("codeop"); if(!aCodeopModule) { // Fatal error. No way to go on. @@ -54,7 +81,7 @@ std::list ParametersPlugin_PyInterp::_compile(const std::string& th } PyObject *aCodePyObj = - PyObject_CallMethod(aCodeopModule, "compile_command", "(s)", theExpression.c_str()); + PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)", theExpression.c_str()); if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) { Py_XDECREF(aCodePyObj); @@ -62,10 +89,11 @@ std::list ParametersPlugin_PyInterp::_compile(const std::string& th } PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj; + std::string aCodeName(PyString_AsString(aCodeObj->co_code)); // co_names should be tuple, but can be changed in modern versions of python (>2.7.3) if(!PyTuple_Check(aCodeObj->co_names)) return aResult; - + int params_size = PyTuple_Size(aCodeObj->co_names); if (params_size > 0) { for (int i = 0; i < params_size; i++) { @@ -80,8 +108,9 @@ std::list ParametersPlugin_PyInterp::_compile(const std::string& th return aResult; } -void ParametersPlugin_PyInterp::_extendLocalContext(const std::list& theParameters) +void ParametersPlugin_PyInterp::extendLocalContext(const std::list& theParameters) { + PyLockWrapper lck; // Acquire GIL until the end of the method if (theParameters.empty()) return; std::list::const_iterator it = theParameters.begin(); @@ -91,9 +120,16 @@ void ParametersPlugin_PyInterp::_extendLocalContext(const std::list } } +void ParametersPlugin_PyInterp::clearLocalContext() +{ + PyLockWrapper lck; + PyDict_Clear(_local_context); +} + -double ParametersPlugin_PyInterp::_evaluate(const std::string& theExpression, std::string& theError) +double ParametersPlugin_PyInterp::evaluate(const std::string& theExpression, std::string& theError) { + PyLockWrapper lck; // Acquire GIL until the end of the method PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileString(theExpression.c_str(), "", Py_eval_input); if(!anExprCode) { @@ -115,7 +151,14 @@ double ParametersPlugin_PyInterp::_evaluate(const std::string& theExpression, st Py_XDECREF(anExprCode); Py_XDECREF(anEvalResult); Py_XDECREF(anEvalStrObj); - return std::stod(anEvalStr); + double result = 0.; + try { + result = std::stod(anEvalStr); + } catch (const std::invalid_argument&) { + theError = "Unable to eval " + anEvalStr; + } + + return result; } std::string ParametersPlugin_PyInterp::errorMessage() @@ -134,3 +177,24 @@ std::string ParametersPlugin_PyInterp::errorMessage() } return aPyError; } + +bool ParametersPlugin_PyInterp::initContext() +{ + PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context) + if(!m){ + PyErr_Print(); + return false; + } + _global_context = PyModule_GetDict(m); // get interpreter global variable context + Py_INCREF(_global_context); + _local_context = PyDict_New(); + Py_INCREF(_local_context); + + return PyRun_SimpleString("from math import *") == 0; +} + +void ParametersPlugin_PyInterp::closeContext() +{ + Py_XDECREF(_local_context); + PyInterp_Interp::closeContext(); +}