Salome HOME
Rolling back incorrect integration
[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 #ifndef WNT
209     PyObjWrapper r(PyEval_EvalCode(v,context,context));
210 #else
211     PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
212 #endif
213     if(!r){
214       // Execution error. We return -1
215       PyErr_Print();
216       return -1;
217     }
218     // The command has been successfully executed. Return 0
219     return 0;
220   }
221 }
222
223
224 int PyInterp_base::run(const char *command)
225 {
226   if(_atFirst){
227     int ret = 0;
228     ret = simpleRun("from Help import *");
229     if (ret) { 
230       _atFirst = false;
231       return ret;
232     }
233     ret = simpleRun("import salome");
234     if (ret) { 
235       _atFirst = false;
236       return ret;
237     }
238     ret = simpleRun("salome.salome_init()");
239     if (ret) { 
240       _atFirst = false;
241       return ret;
242     }
243     _atFirst = false;
244   }
245   return simpleRun(command);
246 }
247
248
249 int PyInterp_base::simpleRun(const char *command)
250 {
251   if( !_atFirst && strcmp(command,"") != 0 ) {
252     _history.push_back(command);
253     _ith = _history.end();
254   }
255
256   // We come from C++ to enter Python world
257   // We need to acquire the Python global lock
258   //PyLockWrapper aLock(_tstate); // san - lock is centralized now
259
260   // Reset redirected outputs before treatment
261   PySys_SetObject("stderr",_verr);
262   PySys_SetObject("stdout",_vout);
263     
264   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
265   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
266   
267   int ier = compile_command(command,_g);
268
269   // Outputs are redirected on standards outputs (console)
270   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
271   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
272   return ier;
273 }
274
275
276 const char * PyInterp_base::getPrevious()
277 {
278   if(_ith != _history.begin()){
279     _ith--;
280     return (*_ith).c_str();
281   }
282   else
283     return BEGIN_HISTORY_PY;
284 }
285
286
287 const char * PyInterp_base::getNext()
288 {
289   if(_ith != _history.end()){
290     _ith++;
291   }
292   if (_ith == _history.end())
293     return TOP_HISTORY_PY;
294   else
295     return (*_ith).c_str();
296 }
297
298
299 string PyInterp_base::getverr(){ 
300   //PyLockWrapper aLock(_tstate);
301   PyObjWrapper v(PycStringIO->cgetvalue(_verr));
302   string aRet(PyString_AsString(v));
303   return aRet;
304 }
305
306
307 string PyInterp_base::getvout(){  
308   //PyLockWrapper aLock(_tstate);
309   PyObjWrapper v(PycStringIO->cgetvalue(_vout));
310   string aRet(PyString_AsString(v));
311   return aRet;
312 }
313