X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FInitializationPlugin%2FInitializationPlugin_PyInterp.cpp;h=3d9f7e8e75fadd8a54f9746befa442e626363fae;hb=a55586483e5dccc5466d6ec241e2147e210d839f;hp=ac32047ac0d834d2bde0db14016f2caabaef151f;hpb=332f6b9a2a68158cf49feab94e21dd384d144b37;p=modules%2Fshaper.git diff --git a/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp b/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp index ac32047ac..3d9f7e8e7 100644 --- a/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp +++ b/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp @@ -1,15 +1,28 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -/* - * InitializationPlugin_PyInterp.cpp - * - * Created on: Apr 2, 2015 - * Author: sbh - */ +// Copyright (C) 2014-2017 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include #include #include +#include InitializationPlugin_PyInterp::InitializationPlugin_PyInterp() : PyInterp_Interp() @@ -30,6 +43,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) @@ -40,12 +63,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 @@ -60,8 +83,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? @@ -80,10 +103,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); @@ -91,17 +116,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); } @@ -128,12 +154,16 @@ void InitializationPlugin_PyInterp::clearLocalContext() PyDict_Clear(_local_context); } -double InitializationPlugin_PyInterp::evaluate(const std::string& theExpression, std::string& theError) +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(); @@ -141,7 +171,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); @@ -150,14 +180,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; } @@ -172,7 +207,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);