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