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