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