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