2 * ParametersPlugin_PyInterp.cpp
4 * Created on: Apr 2, 2015
8 #include <ParametersPlugin_PyInterp.h>
13 ParametersPlugin_PyInterp::ParametersPlugin_PyInterp()
18 ParametersPlugin_PyInterp::~ParametersPlugin_PyInterp()
22 const char* aSearchCode =
24 "class FindName(ast.NodeVisitor):\n"
25 " def __init__(self, name):\n"
27 " def visit_Name(self, node):\n"
28 " if node.id == self.name:\n"
29 " positions.append((node.lineno, node.col_offset))\n"
30 "FindName(name).visit(ast.parse(expression))";
32 std::list<std::pair<int, int> >
33 ParametersPlugin_PyInterp::positions(const std::string& theExpression,
34 const std::string& theName)
36 PyLockWrapper lck; // Acquire GIL until the end of the method
38 std::list<std::pair<int, int> > aResult;
41 PyObject* aContext = PyDict_New();
42 PyObject* aBuiltinModule = PyImport_AddModule("__builtin__");
43 PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule);
45 // extend aContext with variables
46 PyDict_SetItemString(aContext, "expression", PyString_FromString(theExpression.c_str()));
47 PyDict_SetItemString(aContext, "name", PyString_FromString(theName.c_str()));
48 PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]"));
50 // run the search code
51 PyObject* aExecResult = PyRun_String(aSearchCode, Py_file_input, aContext, aContext);
52 Py_XDECREF(aExecResult);
54 // receive results from context
55 PyObject* aPositions = PyDict_GetItemString(aContext, "positions");
56 for (int anIndex = 0; anIndex < PyList_Size(aPositions); ++anIndex) {
57 PyObject* aPosition = PyList_GetItem(aPositions, anIndex);
58 PyObject* aLineNo = PyTuple_GetItem(aPosition, 0);
59 PyObject* aColOffset = PyTuple_GetItem(aPosition, 1);
62 std::pair<int, int>((int)PyInt_AsLong(aLineNo),
63 (int)PyInt_AsLong(aColOffset)));
66 // TODO(spo): after this refCount of the variable is not 0. Is there memory leak?
73 std::list<std::string> ParametersPlugin_PyInterp::compile(const std::string& theExpression)
75 PyLockWrapper lck; // Acquire GIL until the end of the method
76 std::list<std::string> aResult;
77 PyObject *aCodeopModule = PyImport_AddModule("codeop");
78 if(!aCodeopModule) { // Fatal error. No way to go on.
83 PyObject *aCodePyObj =
84 PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)", theExpression.c_str());
86 if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) {
87 Py_XDECREF(aCodePyObj);
91 PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj;
92 std::string aCodeName(PyString_AsString(aCodeObj->co_code));
93 // co_names should be tuple, but can be changed in modern versions of python (>2.7.3)
94 if(!PyTuple_Check(aCodeObj->co_names))
97 int params_size = PyTuple_Size(aCodeObj->co_names);
98 if (params_size > 0) {
99 for (int i = 0; i < params_size; i++) {
100 PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i);
101 PyObject* aParamObjStr = PyObject_Str(aParamObj);
102 std::string aParamName(PyString_AsString(aParamObjStr));
103 aResult.push_back(aParamName);
104 Py_XDECREF(aParamObjStr);
107 Py_XDECREF(aCodeObj);
111 void ParametersPlugin_PyInterp::extendLocalContext(const std::list<std::string>& theParameters)
113 PyLockWrapper lck; // Acquire GIL until the end of the method
114 if (theParameters.empty())
116 std::list<std::string>::const_iterator it = theParameters.begin();
117 for ( ; it != theParameters.cend(); it++) {
118 std::string aParamValue = *it;
119 simpleRun(aParamValue.c_str(), false);
123 void ParametersPlugin_PyInterp::clearLocalContext()
126 PyDict_Clear(_local_context);
130 double ParametersPlugin_PyInterp::evaluate(const std::string& theExpression, std::string& theError)
132 PyLockWrapper lck; // Acquire GIL until the end of the method
133 PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileString(theExpression.c_str(),
134 "<string>", Py_eval_input);
136 theError = errorMessage();
137 Py_XDECREF(anExprCode);
141 PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
143 theError = errorMessage();
144 Py_XDECREF(anExprCode);
145 Py_XDECREF(anEvalResult);
149 PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
150 std::string anEvalStr(PyString_AsString(anEvalStrObj));
151 Py_XDECREF(anExprCode);
152 Py_XDECREF(anEvalResult);
153 Py_XDECREF(anEvalStrObj);
156 result = std::stod(anEvalStr);
157 } catch (const std::invalid_argument&) {
158 theError = "Unable to eval " + anEvalStr;
164 std::string ParametersPlugin_PyInterp::errorMessage()
166 std::string aPyError;
167 if (PyErr_Occurred()) {
168 PyObject *pstr, *ptype, *pvalue, *ptraceback;
169 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
170 PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
171 pstr = PyObject_Str(pvalue);
172 aPyError = std::string(PyString_AsString(pstr));
176 Py_XDECREF(ptraceback);
181 bool ParametersPlugin_PyInterp::initContext()
183 PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context)
188 _global_context = PyModule_GetDict(m); // get interpreter global variable context
189 Py_INCREF(_global_context);
190 _local_context = PyDict_New();
191 Py_INCREF(_local_context);
193 return PyRun_SimpleString("from math import *") == 0;
196 void ParametersPlugin_PyInterp::closeContext()
198 Py_XDECREF(_local_context);
199 PyInterp_Interp::closeContext();