Salome HOME
92812f50a4c1b9ec1921d3676f61f58953e9bb48
[modules/shaper.git] / src / ParametersPlugin / ParametersPlugin_PyInterp.cpp
1 /*
2  * ParametersPlugin_PyInterp.cpp
3  *
4  *  Created on: Apr 2, 2015
5  *      Author: sbh
6  */
7
8 #include <ParametersPlugin_PyInterp.h>
9
10 #include <string>
11
12 ParametersPlugin_PyInterp::ParametersPlugin_PyInterp()
13 : PyInterp_Interp()
14 {
15 }
16
17 ParametersPlugin_PyInterp::~ParametersPlugin_PyInterp()
18 {
19 }
20
21 std::list<std::string> ParametersPlugin_PyInterp::compile(const std::string& theExpression)
22 {
23   PyGILState_STATE aGilState = PyGILState_Ensure();
24   std::list<std::string>  res = this->_compile(theExpression);
25   PyGILState_Release(aGilState);
26   return res;
27 }
28
29 void ParametersPlugin_PyInterp::extendLocalContext(const std::list<std::string>& theParameters)
30 {
31   PyGILState_STATE aGilState = PyGILState_Ensure();
32   this->_extendLocalContext(theParameters);
33   PyGILState_Release(aGilState);
34 }
35
36 double ParametersPlugin_PyInterp::evaluate(const std::string& theExpression,
37                                            std::string& theError)
38 {
39   PyGILState_STATE aGilState = PyGILState_Ensure();
40   double res = this->_evaluate(theExpression, theError);
41   PyGILState_Release(aGilState);
42   return res;
43 }
44
45
46 std::list<std::string> ParametersPlugin_PyInterp::_compile(const std::string& theExpression)
47 {
48
49   std::list<std::string> aResult;
50   PyObject *aCodeopModule = PyImport_AddModule("codeop");
51   if(!aCodeopModule) { // Fatal error. No way to go on.
52     PyErr_Print();
53     return aResult;
54   }
55
56   PyObject *aCodePyObj =
57       PyObject_CallMethod(aCodeopModule, "compile_command", "(s)", theExpression.c_str());
58
59   if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) {
60     Py_XDECREF(aCodePyObj);
61     return aResult;
62   }
63
64   PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj;
65   // co_names should be tuple, but can be changed in modern versions of python (>2.7.3)
66   if(!PyTuple_Check(aCodeObj->co_names))
67     return aResult;
68   
69   int params_size = PyTuple_Size(aCodeObj->co_names);
70   if (params_size > 0) {
71     for (int i = 0; i < params_size; i++) {
72       PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i);
73       PyObject* aParamObjStr = PyObject_Str(aParamObj);
74       std::string aParamName(PyString_AsString(aParamObjStr));
75       aResult.push_back(aParamName);
76       Py_XDECREF(aParamObjStr);
77     }
78   }
79   Py_XDECREF(aCodeObj);
80   return aResult;
81 }
82
83 void ParametersPlugin_PyInterp::_extendLocalContext(const std::list<std::string>& theParameters)
84 {
85   if (theParameters.empty())
86     return;
87 }
88
89
90 double ParametersPlugin_PyInterp::_evaluate(const std::string& theExpression, std::string& theError)
91 {
92   PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileString(theExpression.c_str(),
93                                                                "<string>", Py_eval_input);
94   if(!anExprCode) {
95     theError = errorMessage();
96     Py_XDECREF(anExprCode);
97     return 0.;
98   }
99
100   PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
101   if(!anEvalResult) {
102     theError = errorMessage();
103     Py_XDECREF(anExprCode);
104     Py_XDECREF(anEvalResult);
105     return 0.;
106   }
107
108   PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
109   std::string anEvalStr(PyString_AsString(anEvalStrObj));
110   double result = std::stod(anEvalStr);
111
112   return result;
113 }
114
115 std::string ParametersPlugin_PyInterp::errorMessage()
116 {
117   std::string aPyError;
118   if (PyErr_Occurred()) {
119     PyObject *pstr, *ptype, *pvalue, *ptraceback;
120     PyErr_Fetch(&ptype, &pvalue, &ptraceback);
121     PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
122     pstr = PyObject_Str(pvalue);
123     aPyError = std::string(PyString_AsString(pstr));
124     Py_XDECREF(pstr);
125     Py_XDECREF(ptype);
126     Py_XDECREF(pvalue);
127     Py_XDECREF(ptraceback);
128   }
129   return aPyError;
130 }