Salome HOME
CCAR (EDF-RD):
[modules/kernel.git] / src / SALOMEGUI / PyInterp_base.cxx
1 using namespace std;
2 //=============================================================================
3 // File      : PyInterp_base.cxx
4 // Created   : ven fév  7 10:01:36 CET 2003
5 // Author    : Christian CAREMOLI, Paul RASCLE, EDF
6 // Project   : SALOME
7 // Copyright : EDF 2003
8 // $Header$
9 //=============================================================================
10
11 #include "PyInterp_base.h"
12 #include "utilities.h"
13 #include <string>
14 #include <vector>
15 #include <cStringIO.h>
16
17 using namespace std;
18
19 extern "C" PyObject * PyEval_EvalCode(PyObject *co, PyObject *g, PyObject *l);
20
21 static PyThreadState *savedThreadState = NULL;
22
23 /*!
24  * We have our own routines which are identical to the SIP routines
25  * to not depend from SIP software evolutions
26  */
27
28 extern "C" void salomeAcquireLock()
29 {
30   MESSAGE("salomeAcquireLock");
31   PyEval_RestoreThread(savedThreadState);
32   savedThreadState = NULL;
33 }
34
35 extern "C" void salomeReleaseLock()
36 {
37   MESSAGE("salomeReleaseLock");
38   savedThreadState = PyEval_SaveThread();
39 }
40
41 extern "C" int salomeCondAcquireLock()
42 {
43   MESSAGE("salomeCondAcquireLock");
44   if(savedThreadState != NULL)
45     {
46       /*
47        * If savedThreadState is not NULL, Python global lock is not already acquired
48        * We acquire it
49        * and return 1 to the caller
50        */
51       salomeAcquireLock();
52       //MESSAGE("We got it (the lock)");
53       return 1;
54     }
55   /*
56    * If savedThreadState is NULL, Python global lock is already acquired
57    * We don't acquire or release it
58    * We return 0 to the caller
59    * CAUTION : it's only true when there is no event programming running (Tkinter, PyQt)
60    */
61   return 0;
62 }
63
64 extern "C" void salomeCondReleaseLock(int rellock)
65 {
66   MESSAGE("salomeCondReleaseLock");
67   if(rellock )
68     salomeReleaseLock();
69 }
70
71 // main python interpreter
72
73 PyThreadState *PyInterp_base::_gtstate=0; // force 0 before execution
74 int PyInterp_base::_argc=1;
75 char* PyInterp_base::_argv[] = {""};
76
77 PyObject *PyInterp_base::builtinmodule=NULL;
78 PyObject *PyInterp_base::salome_shared_modules_module=NULL;
79
80 void init_python()
81 {
82   SCRUTE(PyInterp_base::_gtstate);
83   if (PyInterp_base::_gtstate) return;
84   Py_Initialize();               // Initialize the interpreter
85   PyEval_InitThreads();          // Create (and acquire) the interpreter lock
86   PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv);      // initialize sys.argv
87   PyInterp_base::_gtstate = PyThreadState_Get();
88   SCRUTE(PyInterp_base::_gtstate);
89
90   //   /*
91   //    * Import __builtin__ module and store it to use it with all sub-interpreters
92   //    * This hack could be used with event programming (PyQt) to avoid errors 
93   //    * encountered with incoherent builtins
94   //    */
95
96   //   PyInterp_base::builtinmodule =PyImport_ImportModule("__builtin__");
97   //   SCRUTE(PyInterp_base::builtinmodule->ob_refcnt);
98
99   /*
100    * Import salome_shared_modules module and store it to use it with all sub-interpreters
101    */
102
103   PyInterp_base::salome_shared_modules_module =PyImport_ImportModule("salome_shared_modules");
104   if(PyInterp_base::salome_shared_modules_module == NULL){
105       MESSAGE("init_python: problem with salome_shared_modules import");
106       PyErr_Print();
107       PyErr_Clear();
108       salomeReleaseLock();
109       return;
110   }
111   SCRUTE(PyInterp_base::salome_shared_modules_module->ob_refcnt);
112   salomeReleaseLock();
113 }
114
115 /*!
116  * This function compiles a string (command) and then evaluates it in the dictionnary
117  * context if possible.
118  * Returns :
119  * -1 : fatal error 
120  *  1 : incomplete text
121  *  0 : complete text executed with success
122  */
123
124 int compile_command(const char *command,PyObject *context)
125 {
126   SCRUTE(command);
127   PyObject *m,*v,*r;
128
129   m=PyImport_AddModule("codeop");
130   if(m == NULL)
131     {
132       /*
133        * Fatal error. No way to go on.
134        */
135       PyErr_Print();
136       return -1;
137     }
138   v= PyObject_CallMethod(m,"compile_command","s",command);
139   if (v == NULL)
140     {
141       /*
142        * Error encountered. It should be SyntaxError
143        * so we don't write out traceback
144        */
145       PyObject *exception,*value,*tb;
146       PyErr_Fetch(&exception, &value, &tb);
147       PyErr_NormalizeException(&exception, &value, &tb);
148       PyErr_Display(exception, value, NULL);
149       Py_XDECREF(exception);
150       Py_XDECREF(value);
151       Py_XDECREF(tb);
152
153       return -1;
154     }
155   else if (v == Py_None)
156     {
157       /*
158        *  Incomplete text we return 1 : we need a complete text to execute
159        */
160       return 1;
161     }
162   else
163     {
164       /*
165        * Complete and correct text. We evaluate it.
166        */
167       r  = PyEval_EvalCode(v,context,context);
168       Py_DECREF(v);
169       if (r==NULL)
170         {
171           /*
172            * Execution error. We return -1
173            */
174           PyErr_Print();
175           return -1;
176         }
177       Py_DECREF(r);
178       /*
179        * The command has been successfully executed. Return 0
180        */
181       return 0;
182     }
183 }
184
185 /*!
186  * basic constructor here : herited classes constructors must call initalize() method
187  * defined here.
188  */
189
190 PyInterp_base::PyInterp_base():_tstate(0),_vout(0),_verr(0),_g(0),_atFirst(true)
191 {
192   MESSAGE("PyInterp_base::PyInterp_base()");
193 }
194
195 PyInterp_base::~PyInterp_base()
196 {
197   MESSAGE("PyInterp_base::~PyInterp_base()");
198   salomeAcquireLock();
199   PyThreadState_Swap(_tstate);
200   Py_EndInterpreter(_tstate);
201   salomeReleaseLock();
202 }
203
204 /*!
205  * Must be called by herited classes constructors. initialize() calls virtuals methods
206  * initstate & initcontext, not defined here in base class. initstate & initcontext methods
207  * must be implemented in herited classes, following the Python interpreter policy
208  * (mono or multi interpreter...).
209  */
210 void PyInterp_base::initialize()
211 {
212   MESSAGE("PyInterp_base::initialize()");
213   PyObject *m,*v,*c;
214
215   _history.clear();       // start a new list of user's commands 
216   _ith = _history.begin();
217
218   init_python();
219
220   initState();
221
222   initContext();
223
224   m=PyImport_ImportModule("codeop"); // used to interpret & compile commands
225   if(m == NULL)
226     {
227       MESSAGE("Problem...");
228       PyErr_Print();
229       ASSERT(0);
230       salomeReleaseLock(); 
231       return;
232     }   
233   Py_DECREF(m);   
234   
235   /*
236    *  Create cStringIO to capture stdout and stderr
237    */
238   //PycString_IMPORT;
239   PycStringIO=(PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
240   _vout=PycStringIO->NewOutput(128);
241   _verr=PycStringIO->NewOutput(128);
242   
243   // All the initRun outputs are redirected to the standard output (console)
244   this->initRun();
245
246   // We go out of Python world to enter the C++ world. Release the Python global lock 
247   salomeReleaseLock();
248   SCRUTE(_tstate);
249   SCRUTE(this);
250 }
251
252 string PyInterp_base::getbanner()
253 {
254   MESSAGE("PyInterp_base::getbanner()");
255   string banner = "Python ";
256   banner = banner + Py_GetVersion() + " on " + Py_GetPlatform() ;
257   banner = banner + "\ntype help to get general information on environment\n";
258   return banner.c_str();
259 }
260
261 int PyInterp_base::initRun()
262 {
263   MESSAGE("PyInterp_base::initRun()");
264   PySys_SetObject("stderr",_verr);
265   PySys_SetObject("stdout",_vout);
266
267   PyObject *v = PyObject_CallMethod(_verr,"reset","");
268   Py_XDECREF(v);
269   v = PyObject_CallMethod(_vout,"reset","");
270   Py_XDECREF(v);
271
272
273   PyObject *m;
274   m = PyImport_GetModuleDict();
275   
276   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
277   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
278
279   MESSAGE(this->getvout());
280   MESSAGE(this->getverr());
281     
282   return 0;
283 }
284
285 void PyInterp_base::enter()
286 {
287   MESSAGE("PyInterp_base::enter()");
288   salomeAcquireLock();
289   PyThreadState_Swap(_tstate);
290 }
291
292 void PyInterp_base::quit()
293 {
294   MESSAGE("PyInterp_base::quit()");
295   salomeReleaseLock();
296 }
297
298 void PyInterp_base::basicRun(const char *command)
299 {
300   SCRUTE(command);
301   PyObject *code,*r;
302   enter();
303   code=Py_CompileString((char *)command,"PyInterp_base",Py_file_input);
304   if (code == NULL)
305     {
306       /*
307        * Caught an error : SyntaxError
308        * Print it and quit
309        */
310       PyErr_Print();
311       quit();
312       return;
313     }
314   r = PyEval_EvalCode(code,_g,_g);
315   Py_DECREF(code);
316   if (r==NULL)
317     {
318       /*
319        * Caught an error during execution
320        * Print it and quit
321        */
322       PyErr_Print();
323       quit();
324       return;
325     }
326   Py_DECREF(r);
327   quit();
328 }
329
330 int PyInterp_base::run(const char *command)
331 {
332   SCRUTE(command);
333   int ret = 0;
334   if (_atFirst)
335     {
336       _atFirst = false;
337       ret = this->simpleRun("from Help import *");
338       MESSAGE(this->getvout())
339         MESSAGE(this->getverr())
340         if (ret != 0) return ret;
341       ret = this->simpleRun("import salome");
342       MESSAGE(this->getvout());
343       MESSAGE(this->getverr())
344         if (ret != 0) return ret;
345     }
346   ret = this->simpleRun(command);
347   return ret;
348 }
349
350 int PyInterp_base::simpleRun(const char *command)
351 {
352   SCRUTE(command);
353   PyObject *v,*m,*r,*g;
354   char *output;
355   int ier=0;
356   string s_com = command;
357
358   if (s_com.size() > 0)
359     {
360       _history.push_back(s_com);
361       _ith = _history.end();
362       SCRUTE(_history.back());
363     }
364
365   //   SCRUTE(this);
366   //   SCRUTE(_tstate);
367   // We come from C++ to enter Python world
368   // We need to acquire the Python global lock
369   salomeAcquireLock();
370   // Restore the sub interpreter thread state : this._tstate
371   PyThreadState_Swap(_tstate);
372
373   /*
374     Reset redirected outputs before treatment
375   */
376   PySys_SetObject("stderr",_verr);
377   PySys_SetObject("stdout",_vout);
378
379   v = PyObject_CallMethod(_verr,"reset","");
380   Py_XDECREF(v);
381   v = PyObject_CallMethod(_vout,"reset","");
382   Py_XDECREF(v);
383   
384   ier=compile_command(command,_g);
385
386   // Outputs are redirected on standards outputs (console)
387   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
388   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
389
390   // We go back to the C++ world. Release the lock.
391   salomeReleaseLock();
392   return ier;
393 }
394
395 static string vout_buffer;
396 static string verr_buffer;
397
398 char * PyInterp_base::getverr()
399
400   MESSAGE("PyInterp_base::getverr"); 
401   PyObject *v;
402   v=PycStringIO->cgetvalue(_verr);
403   verr_buffer=PyString_AsString(v);
404   Py_DECREF(v);
405   return (char *)verr_buffer.c_str();
406 }
407
408 char * PyInterp_base::getvout()
409 {  
410   MESSAGE("PyInterp_base::getvout"); 
411   PyObject *v;
412   v=PycStringIO->cgetvalue(_vout);
413   vout_buffer=PyString_AsString(v);
414   Py_DECREF(v);
415   return (char *)vout_buffer.c_str();
416 }
417  
418 const char * PyInterp_base::getPrevious()
419 {
420   MESSAGE("PyInterp_base::getPrevious"); 
421   if (_ith != _history.begin())
422     {
423       _ith--;
424       return (*_ith).c_str();
425     }
426   else
427     return BEGIN_HISTORY_PY;
428 }
429
430 const char * PyInterp_base::getNext()
431 {
432   MESSAGE("PyInterp_base::getNext"); 
433   if (_ith != _history.end())
434     {
435       _ith++;
436     }
437   if (_ith == _history.end())
438     return TOP_HISTORY_PY;
439   else
440     return (*_ith).c_str();
441 }