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