X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FInitializationPlugin%2FInitializationPlugin_PyInterp.cpp;h=57ef46d48b4c0e98a8363ed934e1eb2dd4884e1e;hb=97c06c5cd9fc736f9b5a1dacde369a9d7b5be703;hp=e148bdf17d650815e56770698c714bf9a1774b7c;hpb=7074394f8f08413d885f63be01df6bd5007b868c;p=modules%2Fshaper.git diff --git a/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp b/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp index e148bdf17..57ef46d48 100644 --- a/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp +++ b/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,16 +12,16 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include #include #include +#include InitializationPlugin_PyInterp::InitializationPlugin_PyInterp() : PyInterp_Interp() @@ -42,6 +42,16 @@ const char* aSearchCode = " positions.append((node.lineno, node.col_offset))\n" "FindName(name).visit(ast.parse(expression))"; +// make the expression be correct for the python interpreter even for the +// beta=alfa*2 expressions +static std::string adjustExpression(const std::string& theExpression) { + std::string anExpression = theExpression; + if (!anExpression.empty() && anExpression.back() == '=') { + anExpression = anExpression.substr(0, anExpression.length() - 1); + } + return anExpression; +} + std::list > InitializationPlugin_PyInterp::positions(const std::string& theExpression, const std::string& theName) @@ -52,12 +62,12 @@ InitializationPlugin_PyInterp::positions(const std::string& theExpression, // prepare a context PyObject* aContext = PyDict_New(); - PyObject* aBuiltinModule = PyImport_AddModule("__builtin__"); - PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule); + PyDict_SetItemString(aContext, "__builtins__", PyEval_GetBuiltins()); + std::string anExpression = adjustExpression(theExpression); // 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, "expression", PyUnicode_FromString(anExpression.c_str())); + PyDict_SetItemString(aContext, "name", PyUnicode_FromString(theName.c_str())); PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]")); // run the search code @@ -72,8 +82,8 @@ InitializationPlugin_PyInterp::positions(const std::string& theExpression, PyObject* aColOffset = PyTuple_GetItem(aPosition, 1); aResult.push_back( - std::pair((int)PyInt_AsLong(aLineNo), - (int)PyInt_AsLong(aColOffset))); + std::pair((int)PyLong_AsLong(aLineNo), + (int)PyLong_AsLong(aColOffset))); } // TODO(spo): after this refCount of the variable is not 0. Is there memory leak? @@ -92,10 +102,12 @@ std::list InitializationPlugin_PyInterp::compile(const std::string& PyErr_Print(); return aResult; } + // support "variable_name=" expression as "variable_name" + std::string anExpression = adjustExpression(theExpression); PyObject *aCodePyObj = PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)", - theExpression.c_str()); + anExpression.c_str()); if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) { Py_XDECREF(aCodePyObj); @@ -103,17 +115,18 @@ std::list InitializationPlugin_PyInterp::compile(const std::string& } PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj; - std::string aCodeName(PyString_AsString(aCodeObj->co_code)); + std::string aCodeName(PyBytes_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)) + if(!PyTuple_Check(aCodeObj->co_names)) { return aResult; + } size_t params_size = PyTuple_Size(aCodeObj->co_names); if (params_size > 0) { for (size_t i = 0; i < params_size; i++) { PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i); PyObject* aParamObjStr = PyObject_Str(aParamObj); - std::string aParamName(PyString_AsString(aParamObjStr)); + std::string aParamName(PyUnicode_AsUTF8(aParamObjStr)); aResult.push_back(aParamName); Py_XDECREF(aParamObjStr); } @@ -143,10 +156,13 @@ void InitializationPlugin_PyInterp::clearLocalContext() double InitializationPlugin_PyInterp::evaluate(const std::string& theExpression, std::string& theError) { + // support "variable_name=" expression as "variable_name" + std::string anExpression = adjustExpression(theExpression); + PyLockWrapper lck; // Acquire GIL until the end of the method PyCompilerFlags aFlags = {CO_FUTURE_DIVISION}; aFlags.cf_flags = CO_FUTURE_DIVISION; - PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileStringFlags(theExpression.c_str(), + PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileStringFlags(anExpression.c_str(), "", Py_eval_input, &aFlags); if(!anExprCode) { theError = errorMessage(); @@ -154,7 +170,7 @@ double InitializationPlugin_PyInterp::evaluate(const std::string& theExpression, return 0.; } - PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context); + PyObject* anEvalResult = PyEval_EvalCode((PyObject *)anExprCode, _global_context, _local_context); if(!anEvalResult) { theError = errorMessage(); Py_XDECREF(anExprCode); @@ -163,14 +179,19 @@ double InitializationPlugin_PyInterp::evaluate(const std::string& theExpression, } PyObject* anEvalStrObj = PyObject_Str(anEvalResult); - std::string anEvalStr(PyString_AsString(anEvalStrObj)); + std::string anEvalStr(PyUnicode_AsUTF8(anEvalStrObj)); Py_XDECREF(anExprCode); Py_XDECREF(anEvalResult); Py_XDECREF(anEvalStrObj); double result = 0.; try { + // set locale due to the #2485 + std::string aCurLocale = std::setlocale(LC_NUMERIC, 0); + std::setlocale(LC_NUMERIC, "C"); result = std::stod(anEvalStr); - } catch (const std::invalid_argument&) { + std::setlocale(LC_NUMERIC, aCurLocale.c_str()); + } + catch (const std::invalid_argument&) { theError = "Unable to eval " + anEvalStr; } @@ -185,7 +206,7 @@ std::string InitializationPlugin_PyInterp::errorMessage() PyErr_Fetch(&ptype, &pvalue, &ptraceback); PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); pstr = PyObject_Str(pvalue); - aPyError = std::string(PyString_AsString(pstr)); + aPyError = std::string(PyUnicode_AsUTF8(pstr)); Py_XDECREF(pstr); Py_XDECREF(ptype); Py_XDECREF(pvalue); @@ -206,6 +227,26 @@ bool InitializationPlugin_PyInterp::initContext() _local_context = PyDict_New(); Py_INCREF(_local_context); + // to avoid "help()" hang in the python console + const static char* aHelpTxt = "def help(): print(\"Available modules:\\n" + " salome.shaper.model : higher level access to features and data model\\n" + " BuildAPI : Build plugin features allowing to build shapes\\n" + " ConfigAPI : configuration management: preferences and XML properties\\n" + " ConstructionAPI : Construction plugin for auxiliary features creation\\n" + " EventsAPI : application events receiving and emitting manager\\n" + " ExchangeAPI : Exchange plugin with import/export features\\n" + " FeaturesAPI : Features plugin with general 3D features\\n" + " GeomAlgoAPI : geometrical algorithms\\n" + " GeomAPI : geometrical data structures\\n" + " GeomDataAPI : specific geometrical data structures stored in the data model\\n" + " ModelAPI : general low-level interface to access data model\\n" + " ModelHighAPI : general high-level interface to access data model\\n" + " ParametersAPI : Parameters plugin for parameters feature management\\n" + " PartSetAPI : PartSet plugin for management Parts features\\n" + " SketchAPI : Sketch plugin with all sketch features\")"; + + PyRun_SimpleString(aHelpTxt); + return PyRun_SimpleString("from math import *") == 0; }