]> SALOME platform Git repositories - modules/gui.git/blob - src/PyInterp/PyInterp_base.cxx
Salome HOME
69ccefc9d671a8cc6f36f3a2fdf7281157810acc
[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   _vout = PycStringIO->NewOutput(128);
116   _verr = PycStringIO->NewOutput(128);
117
118   // All the initRun outputs are redirected to the standard output (console)
119   initRun();
120 }
121
122 void PyInterp_base::init_python()
123 {
124   _atFirst = false;
125   if (Py_IsInitialized())
126     return;
127
128   // Python is not initialized
129   Py_SetProgramName(_argv[0]);
130   Py_Initialize(); // Initialize the interpreter
131   PySys_SetArgv(_argc, _argv);
132   PyEval_InitThreads(); // Create (and acquire) the interpreter lock
133   _interp = PyThreadState_Get()->interp;
134   _gtstate = PyEval_SaveThread(); // Release global thread state
135 }
136
137 string PyInterp_base::getbanner()
138 {
139  // Should we take the lock ?
140  // PyEval_RestoreThread(_tstate);
141   string aBanner("Python ");
142   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
143   aBanner = aBanner + "\ntype help to get general information on environment\n";
144   //PyEval_SaveThread();
145   return aBanner;
146 }
147
148
149 int PyInterp_base::initRun()
150 {
151   PySys_SetObject("stderr",_verr);
152   PySys_SetObject("stdout",_vout);
153
154   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
155   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
156
157   //PyObject *m = PyImport_GetModuleDict();
158   
159   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
160   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
161
162   return 0;
163 }
164
165
166 /*!
167  * This function compiles a string (command) and then evaluates it in the dictionnary
168  * context if possible.
169  * Returns :
170  * -1 : fatal error 
171  *  1 : incomplete text
172  *  0 : complete text executed with success
173  */
174 int compile_command(const char *command,PyObject *context)
175 {
176   PyObject *m = PyImport_AddModule("codeop");
177   if(!m){ // Fatal error. No way to go on.
178     PyErr_Print();
179     return -1;
180   }
181   PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
182   if(!v){
183     // Error encountered. It should be SyntaxError,
184     //so we don't write out traceback
185     PyObjWrapper exception, value, tb;
186     PyErr_Fetch(&exception, &value, &tb);
187     PyErr_NormalizeException(&exception, &value, &tb);
188     PyErr_Display(exception, value, NULL);
189     return -1;
190   }else if (v == Py_None){
191     // Incomplete text we return 1 : we need a complete text to execute
192     return 1;
193   }else{
194     // Complete and correct text. We evaluate it.
195     //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
196     //    PyObjWrapper r(PyEval_EvalCode(v,context,context));
197     //#else
198     PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
199     //#endif
200     if(!r){
201       // Execution error. We return -1
202       PyErr_Print();
203       return -1;
204     }
205     // The command has been successfully executed. Return 0
206     return 0;
207   }
208 }
209
210
211 int PyInterp_base::run(const char *command)
212 {
213   if(_atFirst){
214     int ret = 0;
215     ret = simpleRun("from Help import *");
216     if (ret) { 
217       _atFirst = false;
218       return ret;
219     }
220     ret = simpleRun("import salome");
221     if (ret) { 
222       _atFirst = false;
223       return ret;
224     }
225     ret = simpleRun("salome.salome_init()");
226     if (ret) { 
227       _atFirst = false;
228       return ret;
229     }
230     _atFirst = false;
231   }
232   return simpleRun(command);
233 }
234
235
236 int PyInterp_base::simpleRun(const char *command)
237 {
238   if( !_atFirst && strcmp(command,"") != 0 ) {
239     _history.push_back(command);
240     _ith = _history.end();
241   }
242
243   // We come from C++ to enter Python world
244   // We need to acquire the Python global lock
245   //PyLockWrapper aLock(_tstate); // san - lock is centralized now
246
247   // Reset redirected outputs before treatment
248   PySys_SetObject("stderr",_verr);
249   PySys_SetObject("stdout",_vout);
250
251   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
252   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
253
254   int ier = compile_command(command,_g);
255
256   // Outputs are redirected on standards outputs (console)
257   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
258   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
259
260   return ier;
261 }
262
263
264 const char * PyInterp_base::getPrevious()
265 {
266   if(_ith != _history.begin()){
267     _ith--;
268     return (*_ith).c_str();
269   }
270   else
271     return BEGIN_HISTORY_PY;
272 }
273
274
275 const char * PyInterp_base::getNext()
276 {
277   if(_ith != _history.end()){
278     _ith++;
279   }
280   if (_ith == _history.end())
281     return TOP_HISTORY_PY;
282   else
283     return (*_ith).c_str();
284 }
285
286
287 string PyInterp_base::getverr(){ 
288   //PyLockWrapper aLock(_tstate);
289   PyObjWrapper v(PycStringIO->cgetvalue(_verr));
290   string aRet(PyString_AsString(v));
291   return aRet;
292 }
293
294
295 string PyInterp_base::getvout(){  
296   //PyLockWrapper aLock(_tstate);
297   PyObjWrapper v(PycStringIO->cgetvalue(_vout));
298   string aRet(PyString_AsString(v));
299   return aRet;
300 }