1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 * InitializationPlugin_PyInterp.cpp
5 * Created on: Apr 2, 2015
9 #include <InitializationPlugin_PyInterp.h>
14 InitializationPlugin_PyInterp::InitializationPlugin_PyInterp()
19 InitializationPlugin_PyInterp::~InitializationPlugin_PyInterp()
23 const char* aSearchCode =
25 "class FindName(ast.NodeVisitor):\n"
26 " def __init__(self, name):\n"
28 " def visit_Name(self, node):\n"
29 " if node.id == self.name:\n"
30 " positions.append((node.lineno, node.col_offset))\n"
31 "FindName(name).visit(ast.parse(expression))";
33 std::list<std::pair<int, int> >
34 InitializationPlugin_PyInterp::positions(const std::string& theExpression,
35 const std::string& theName)
37 PyLockWrapper lck; // Acquire GIL until the end of the method
39 std::list<std::pair<int, int> > aResult;
42 PyObject* aContext = PyDict_New();
43 PyObject* aBuiltinModule = PyImport_AddModule("__builtin__");
44 PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule);
46 // extend aContext with variables
47 PyDict_SetItemString(aContext, "expression", PyString_FromString(theExpression.c_str()));
48 PyDict_SetItemString(aContext, "name", PyString_FromString(theName.c_str()));
49 PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]"));
51 // run the search code
52 PyObject* aExecResult = PyRun_String(aSearchCode, Py_file_input, aContext, aContext);
53 Py_XDECREF(aExecResult);
55 // receive results from context
56 PyObject* aPositions = PyDict_GetItemString(aContext, "positions");
57 for (int anIndex = 0; anIndex < PyList_Size(aPositions); ++anIndex) {
58 PyObject* aPosition = PyList_GetItem(aPositions, anIndex);
59 PyObject* aLineNo = PyTuple_GetItem(aPosition, 0);
60 PyObject* aColOffset = PyTuple_GetItem(aPosition, 1);
63 std::pair<int, int>((int)PyInt_AsLong(aLineNo),
64 (int)PyInt_AsLong(aColOffset)));
67 // TODO(spo): after this refCount of the variable is not 0. Is there memory leak?
74 std::list<std::string> InitializationPlugin_PyInterp::compile(const std::string& theExpression)
76 PyLockWrapper lck; // Acquire GIL until the end of the method
77 std::list<std::string> aResult;
78 PyObject *aCodeopModule = PyImport_AddModule("codeop");
79 if(!aCodeopModule) { // Fatal error. No way to go on.
84 PyObject *aCodePyObj =
85 PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)",
86 theExpression.c_str());
88 if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) {
89 Py_XDECREF(aCodePyObj);
93 PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj;
94 std::string aCodeName(PyString_AsString(aCodeObj->co_code));
95 // co_names should be tuple, but can be changed in modern versions of python (>2.7.3)
96 if(!PyTuple_Check(aCodeObj->co_names))
99 size_t params_size = PyTuple_Size(aCodeObj->co_names);
100 if (params_size > 0) {
101 for (size_t i = 0; i < params_size; i++) {
102 PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i);
103 PyObject* aParamObjStr = PyObject_Str(aParamObj);
104 std::string aParamName(PyString_AsString(aParamObjStr));
105 aResult.push_back(aParamName);
106 Py_XDECREF(aParamObjStr);
109 Py_XDECREF(aCodeObj);
113 void InitializationPlugin_PyInterp::extendLocalContext(const std::list<std::string>& theParameters)
115 PyLockWrapper lck; // Acquire GIL until the end of the method
116 if (theParameters.empty())
118 std::list<std::string>::const_iterator it = theParameters.begin();
119 for ( ; it != theParameters.cend(); it++) {
120 std::string aParamValue = *it;
121 simpleRun(aParamValue.c_str(), false);
125 void InitializationPlugin_PyInterp::clearLocalContext()
128 PyDict_Clear(_local_context);
131 double InitializationPlugin_PyInterp::evaluate(const std::string& theExpression,
132 std::string& theError)
134 PyLockWrapper lck; // Acquire GIL until the end of the method
135 PyCompilerFlags aFlags = {CO_FUTURE_DIVISION};
136 aFlags.cf_flags = CO_FUTURE_DIVISION;
137 PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileStringFlags(theExpression.c_str(),
138 "<string>", Py_eval_input, &aFlags);
140 theError = errorMessage();
141 Py_XDECREF(anExprCode);
145 PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
147 theError = errorMessage();
148 Py_XDECREF(anExprCode);
149 Py_XDECREF(anEvalResult);
153 PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
154 std::string anEvalStr(PyString_AsString(anEvalStrObj));
155 Py_XDECREF(anExprCode);
156 Py_XDECREF(anEvalResult);
157 Py_XDECREF(anEvalStrObj);
160 result = std::stod(anEvalStr);
161 } catch (const std::invalid_argument&) {
162 theError = "Unable to eval " + anEvalStr;
168 std::string InitializationPlugin_PyInterp::errorMessage()
170 std::string aPyError;
171 if (PyErr_Occurred()) {
172 PyObject *pstr, *ptype, *pvalue, *ptraceback;
173 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
174 PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
175 pstr = PyObject_Str(pvalue);
176 aPyError = std::string(PyString_AsString(pstr));
180 Py_XDECREF(ptraceback);
185 bool InitializationPlugin_PyInterp::initContext()
187 PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context)
192 _global_context = PyModule_GetDict(m); // get interpreter global variable context
193 Py_INCREF(_global_context);
194 _local_context = PyDict_New();
195 Py_INCREF(_local_context);
197 return PyRun_SimpleString("from math import *") == 0;
200 void InitializationPlugin_PyInterp::closeContext()
202 Py_XDECREF(_local_context);
203 PyInterp_Interp::closeContext();