Salome HOME
08990e6e5559658968c07892cc0ceea050e9097c
[modules/yacs.git] / src / SALOMEGUI / PyInterp_base.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : PyInterp_base.cxx
8 //  Author : Christian CAREMOLI, Paul RASCLE, EDF
9 //  Module : SALOME
10 //  $Header$
11
12
13 #include <string>
14 #include <vector>
15
16 #include <Python.h>
17 #include <cStringIO.h>
18
19 #include <qmutex.h>
20
21 #include "PyInterp_base.h"
22 #include "utilities.h"
23
24
25 using namespace std;
26
27
28 #ifdef _DEBUG_
29 static int MYDEBUG = 0;
30 static int MYPYDEBUG = 0;
31 #else
32 static int MYDEBUG = 0;
33 static int MYPYDEBUG = 0;
34 #endif
35
36
37 static QMutex myMutex(false);
38
39
40 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
41   myThreadState(theThreadState),
42   mySaveThreadState(PyInterp_base::_gtstate)
43 {
44   PyEval_AcquireLock();
45   mySaveThreadState = PyThreadState_Swap(myThreadState);
46 }
47
48
49 PyLockWrapper::~PyLockWrapper(){
50   PyThreadState_Swap(mySaveThreadState);
51   PyEval_ReleaseLock();
52 }
53
54
55 ThreadLock::ThreadLock(QMutex* theMutex, const char* theComment):
56   myMutex(theMutex),
57   myComment(theComment)
58 {
59   if(MYDEBUG && myComment != "") MESSAGE(" ThreadLock "<<this<<"::"<<myMutex<<" - "<<myComment<<" - "<<myMutex->locked());
60   myMutex->lock();
61 }
62
63
64 ThreadLock::~ThreadLock(){
65   if(MYDEBUG && myComment != "") MESSAGE("~ThreadLock "<<this<<"::"<<myMutex<<" - "<<myComment);
66   myMutex->unlock();
67 }
68
69
70 bool IsPyLocked(){
71   return myMutex.locked();
72 }
73
74
75 ThreadLock GetPyThreadLock(const char* theComment){
76   return ThreadLock(&myMutex,theComment);
77 }
78
79
80 class PyReleaseLock{
81 public:
82   ~PyReleaseLock(){
83     if(MYPYDEBUG) MESSAGE("~PyReleaseLock()");
84     PyEval_ReleaseLock();
85   }
86 };
87
88
89 PyLockWrapper PyInterp_base::GetLockWrapper(){
90   return _tstate;
91 }
92
93
94 // main python interpreter
95
96 PyThreadState *PyInterp_base::_gtstate = 0; // force 0 before execution
97 int PyInterp_base::_argc = 1;
98 char* PyInterp_base::_argv[] = {""};
99
100 PyObject *PyInterp_base::builtinmodule = NULL;
101 PyObject *PyInterp_base::salome_shared_modules_module = NULL;
102
103
104 /*!
105  * basic constructor here : herited classes constructors must call initalize() method
106  * defined here.
107  */
108 PyInterp_base::PyInterp_base(): _tstate(0), _vout(0), _verr(0), _g(0), _atFirst(true)
109 {
110   if(MYPYDEBUG) MESSAGE("PyInterp_base::PyInterp_base() - this = "<<this);
111 }
112
113 PyInterp_base::~PyInterp_base()
114 {
115   if(MYPYDEBUG) MESSAGE("PyInterp_base::~PyInterp_base() - this = "<<this);
116   PyLockWrapper aLock(_tstate);
117   //Py_EndInterpreter(_tstate);
118 }
119
120
121 /*!
122  * Must be called by herited classes constructors. initialize() calls virtuals methods
123  * initstate & initcontext, not defined here in base class. initstate & initcontext methods
124  * must be implemented in herited classes, following the Python interpreter policy
125  * (mono or multi interpreter...).
126  */
127 void PyInterp_base::initialize()
128 {
129   _history.clear();       // start a new list of user's commands 
130   _ith = _history.begin();
131
132   if(!_gtstate){
133     PyReleaseLock aReleaseLock;
134     Py_Initialize(); // Initialize the interpreter
135     PyEval_InitThreads(); // Initialize and acquire the global interpreter lock
136     PySys_SetArgv(_argc,_argv); // initialize sys.argv
137     _gtstate = PyThreadState_Get();
138     
139     /*
140      * salome_shared_modules should be imported only once
141      */
142     salome_shared_modules_module = PyImport_ImportModule("salome_shared_modules");
143     if(!salome_shared_modules_module)
144       {
145         INFOS("PyInterp_base::initialize() - salome_shared_modules_module == NULL");
146         PyErr_Print();
147         PyErr_Clear();
148       }
149   }
150   // Here the global lock is released
151   if(MYPYDEBUG) MESSAGE("PyInterp_base::initialize() - this = "<<this<<"; _gtstate = "<<_gtstate);
152
153   // The lock will be acquired in initState. Make provision to release it on exit
154   PyReleaseLock aReleaseLock;
155
156   initState();
157   initContext();
158
159   // used to interpret & compile commands
160   PyObjWrapper m(PyImport_ImportModule("codeop"));
161   if(!m){
162     INFOS("PyInterp_base::initialize() - PyImport_ImportModule('codeop') failed");
163     PyErr_Print();
164     ASSERT(0);
165     return;
166   }   
167   
168   // Create cStringIO to capture stdout and stderr
169   //PycString_IMPORT;
170   PycStringIO = (PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
171   _vout = PycStringIO->NewOutput(128);
172   _verr = PycStringIO->NewOutput(128);
173   
174   // All the initRun outputs are redirected to the standard output (console)
175   initRun();
176 }
177
178
179 string PyInterp_base::getbanner()
180 {
181   string aBanner("Python ");
182   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
183   aBanner = aBanner + "\ntype help to get general information on environment\n";
184   return aBanner;
185 }
186
187
188 int PyInterp_base::initRun()
189 {
190   PySys_SetObject("stderr",_verr);
191   PySys_SetObject("stdout",_vout);
192
193   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
194   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
195
196   PyObject *m = PyImport_GetModuleDict();
197   
198   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
199   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
200
201   if(MYPYDEBUG) MESSAGE("PyInterp_base::initRun() - this = "<<this<<"; _verr = "<<_verr<<"; _vout = "<<_vout);
202   return 0;
203 }
204
205
206 /*!
207  * This function compiles a string (command) and then evaluates it in the dictionnary
208  * context if possible.
209  * Returns :
210  * -1 : fatal error 
211  *  1 : incomplete text
212  *  0 : complete text executed with success
213  */
214 int compile_command(const char *command,PyObject *context)
215 {
216   PyObject *m = PyImport_AddModule("codeop");
217   if(!m){ // Fatal error. No way to go on.
218     PyErr_Print();
219     return -1;
220   }
221   PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
222   if(!v){
223     // Error encountered. It should be SyntaxError,
224     //so we don't write out traceback
225     PyObjWrapper exception, value, tb;
226     PyErr_Fetch(&exception, &value, &tb);
227     PyErr_NormalizeException(&exception, &value, &tb);
228     PyErr_Display(exception, value, NULL);
229     return -1;
230   }else if (v == Py_None){
231     // Incomplete text we return 1 : we need a complete text to execute
232     return 1;
233   }else{
234     // Complete and correct text. We evaluate it.
235     PyObjWrapper r(PyEval_EvalCode(v,context,context));
236     if(!r){
237       // Execution error. We return -1
238       PyErr_Print();
239       return -1;
240     }
241     // The command has been successfully executed. Return 0
242     return 0;
243   }
244 }
245
246
247 int PyInterp_base::run(const char *command)
248 {
249   if(_atFirst){
250     int ret = 0;
251     _atFirst = false;
252     ret = simpleRun("from Help import *");
253     if (ret) return ret;
254     ret = simpleRun("import salome");
255     if (ret) return ret;
256   }
257   return simpleRun(command);
258 }
259
260
261 int PyInterp_base::simpleRun(const char *command)
262 {
263   if(strcmp(command,"") != 0){
264     _history.push_back(command);
265     _ith = _history.end();
266   }
267
268   // We come from C++ to enter Python world
269   // We need to acquire the Python global lock
270   PyLockWrapper aLock(_tstate);
271
272   // Reset redirected outputs before treatment
273   PySys_SetObject("stderr",_verr);
274   PySys_SetObject("stdout",_vout);
275     
276   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
277   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
278   
279   int ier = compile_command(command,_g);
280
281   // Outputs are redirected on standards outputs (console)
282   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
283   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
284   return ier;
285 }
286
287
288 const char * PyInterp_base::getPrevious()
289 {
290   if(_ith != _history.begin()){
291     _ith--;
292     return (*_ith).c_str();
293   }
294   else
295     return BEGIN_HISTORY_PY;
296 }
297
298
299 const char * PyInterp_base::getNext()
300 {
301   if(_ith != _history.end()){
302     _ith++;
303   }
304   if (_ith == _history.end())
305     return TOP_HISTORY_PY;
306   else
307     return (*_ith).c_str();
308 }
309
310
311 string PyInterp_base::getverr(){ 
312   PyLockWrapper aLock(_tstate);
313   PyObjWrapper v(PycStringIO->cgetvalue(_verr));
314   string aRet(PyString_AsString(v));
315   return aRet;
316 }
317
318
319 string PyInterp_base::getvout(){  
320   PyLockWrapper aLock(_tstate);
321   PyObjWrapper v(PycStringIO->cgetvalue(_vout));
322   string aRet(PyString_AsString(v));
323   return aRet;
324 }
325