X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FInitializationPlugin%2FInitializationPlugin_PyInterp.cpp;h=a9c57539ca98608eaa9046dde78b61d5fd7c9775;hb=fc72d43b677baa05ae7fd317346fd8b723b799ed;hp=ac32047ac0d834d2bde0db14016f2caabaef151f;hpb=332f6b9a2a68158cf49feab94e21dd384d144b37;p=modules%2Fshaper.git diff --git a/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp b/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp index ac32047ac..a9c57539c 100644 --- a/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp +++ b/src/InitializationPlugin/InitializationPlugin_PyInterp.cpp @@ -1,15 +1,30 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -/* - * InitializationPlugin_PyInterp.cpp - * - * Created on: Apr 2, 2015 - * Author: sbh - */ +// Copyright (C) 2014-2023 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 +#include +#include InitializationPlugin_PyInterp::InitializationPlugin_PyInterp() : PyInterp_Interp() @@ -30,9 +45,19 @@ 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::wstring adjustExpression(const std::wstring& theExpression) { + std::wstring anExpression = theExpression; + if (!anExpression.empty() && anExpression.back() == L'=') { + anExpression = anExpression.substr(0, anExpression.length() - 1); + } + return anExpression; +} + std::list > -InitializationPlugin_PyInterp::positions(const std::string& theExpression, - const std::string& theName) +InitializationPlugin_PyInterp::positions(const std::wstring& theExpression, + const std::wstring& theName) { PyLockWrapper lck; // Acquire GIL until the end of the method @@ -40,12 +65,13 @@ 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::wstring 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_FromWideChar(anExpression.c_str(), anExpression.size())); + PyDict_SetItemString(aContext, "name", PyUnicode_FromWideChar(theName.c_str(), theName.size())); PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]")); // run the search code @@ -60,8 +86,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? @@ -71,19 +97,21 @@ InitializationPlugin_PyInterp::positions(const std::string& theExpression, } -std::list InitializationPlugin_PyInterp::compile(const std::string& theExpression) +std::list InitializationPlugin_PyInterp::compile(const std::wstring& theExpression) { PyLockWrapper lck; // Acquire GIL until the end of the method - std::list aResult; + std::list aResult; PyObject *aCodeopModule = PyImport_AddModule("codeop"); if(!aCodeopModule) { // Fatal error. No way to go on. PyErr_Print(); return aResult; } + // support "variable_name=" expression as "variable_name" + std::wstring anExpression = adjustExpression(theExpression); PyObject *aCodePyObj = PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)", - theExpression.c_str()); + Locale::Convert::toString(anExpression).c_str()); if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) { Py_XDECREF(aCodePyObj); @@ -91,17 +119,23 @@ std::list InitializationPlugin_PyInterp::compile(const std::string& } PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj; - std::string aCodeName(PyString_AsString(aCodeObj->co_code)); +#if PY_VERSION_HEX >= 0x030B0000 + std::string aCodeName(PyBytes_AsString(PyObject_GetAttrString((PyObject *)(aCodeObj), "co_code"))); +#else + std::string aCodeName(PyBytes_AsString(aCodeObj->co_code)); +#endif // 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)); + Py_ssize_t aSize; + std::wstring aParamName(PyUnicode_AsWideCharString(aParamObjStr, &aSize)); aResult.push_back(aParamName); Py_XDECREF(aParamObjStr); } @@ -110,14 +144,14 @@ std::list InitializationPlugin_PyInterp::compile(const std::string& return aResult; } -void InitializationPlugin_PyInterp::extendLocalContext(const std::list& theParameters) +void InitializationPlugin_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(); + std::list::const_iterator it = theParameters.begin(); for ( ; it != theParameters.cend(); it++) { - std::string aParamValue = *it; + std::string aParamValue = Locale::Convert::toString(*it); simpleRun(aParamValue.c_str(), false); } } @@ -128,12 +162,17 @@ 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::wstring& theExpression, + std::string& theError) { + // support "variable_name=" expression as "variable_name" + std::wstring 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( + Locale::Convert::toString(anExpression).c_str(), "", Py_eval_input, &aFlags); if(!anExprCode) { theError = errorMessage(); @@ -141,7 +180,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 +189,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 +216,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); @@ -193,6 +237,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; } @@ -201,3 +265,9 @@ void InitializationPlugin_PyInterp::closeContext() Py_XDECREF(_local_context); PyInterp_Interp::closeContext(); } + +bool InitializationPlugin_PyInterp::runString(std::string theString) +{ + PyLockWrapper lck; // Acquire GIL until the end of the method + return PyRun_SimpleString(theString.c_str()); +}