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