#include <string>
#include <stdexcept>
+#include <clocale>
InitializationPlugin_PyInterp::InitializationPlugin_PyInterp()
: PyInterp_Interp()
" 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<std::pair<int, int> >
InitializationPlugin_PyInterp::positions(const std::string& theExpression,
const std::string& theName)
// 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
PyObject* aColOffset = PyTuple_GetItem(aPosition, 1);
aResult.push_back(
- std::pair<int, int>((int)PyInt_AsLong(aLineNo),
- (int)PyInt_AsLong(aColOffset)));
+ std::pair<int, int>((int)PyLong_AsLong(aLineNo),
+ (int)PyLong_AsLong(aColOffset)));
}
// TODO(spo): after this refCount of the variable is not 0. Is there memory leak?
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);
}
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);
}
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(),
"<string>", Py_eval_input, &aFlags);
if(!anExprCode) {
theError = errorMessage();
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);
}
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;
}
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);