Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[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   std::list<std::string>::const_iterator it = theParameters.begin();
88   for ( ; it != theParameters.cend(); it++) {
89     std::string aParamValue = *it;
90     simpleRun(aParamValue.c_str(), false);
91   }
92 }
93
94
95 double ParametersPlugin_PyInterp::_evaluate(const std::string& theExpression, std::string& theError)
96 {
97   PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileString(theExpression.c_str(),
98                                                                "<string>", Py_eval_input);
99   if(!anExprCode) {
100     theError = errorMessage();
101     Py_XDECREF(anExprCode);
102     return 0.;
103   }
104
105   PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
106   if(!anEvalResult) {
107     theError = errorMessage();
108     Py_XDECREF(anExprCode);
109     Py_XDECREF(anEvalResult);
110     return 0.;
111   }
112
113   PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
114   std::string anEvalStr(PyString_AsString(anEvalStrObj));
115   Py_XDECREF(anExprCode);
116   Py_XDECREF(anEvalResult);
117   Py_XDECREF(anEvalStrObj);
118   return std::stod(anEvalStr);
119 }
120
121 std::string ParametersPlugin_PyInterp::errorMessage()
122 {
123   std::string aPyError;
124   if (PyErr_Occurred()) {
125     PyObject *pstr, *ptype, *pvalue, *ptraceback;
126     PyErr_Fetch(&ptype, &pvalue, &ptraceback);
127     PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
128     pstr = PyObject_Str(pvalue);
129     aPyError = std::string(PyString_AsString(pstr));
130     Py_XDECREF(pstr);
131     Py_XDECREF(ptype);
132     Py_XDECREF(pvalue);
133     Py_XDECREF(ptraceback);
134   }
135   return aPyError;
136 }