Salome HOME
3960bb8d9c405e8eee848f0e157b2c92c06e5a3e
[modules/gui.git] / src / PyInterp / PyInterp_Interp.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : PyInterp_Interp.cxx
23 //  Author : Christian CAREMOLI, Paul RASCLE, EDF
24 //  Module : SALOME
25 //
26 #include "PyInterp_Interp.h"  // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
27
28 #include <cStringIO.h>
29 #include <structmember.h>
30
31 #include <string>
32 #include <vector>
33 #include <iostream>
34
35 #define TOP_HISTORY_PY   "--- top of history ---"
36 #define BEGIN_HISTORY_PY "--- begin of history ---"
37
38 /*!
39   \class PyLockWrapper
40   \brief Python GIL wrapper.
41 */
42
43 /*!
44   \brief Constructor. Automatically acquires GIL.
45   \param theThreadState python thread state
46 */
47 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
48   myThreadState(theThreadState),
49   mySaveThreadState(0)
50 {
51   if (myThreadState->interp == PyInterp_Interp::_interp)
52     _savestate = PyGILState_Ensure();
53   else
54     PyEval_AcquireThread(myThreadState);
55 }
56
57 /*!
58   \brief Desstructor. Automatically releases GIL.
59 */
60 PyLockWrapper::~PyLockWrapper()
61 {
62   if (myThreadState->interp == PyInterp_Interp::_interp)
63     PyGILState_Release(_savestate);
64   else
65     PyEval_ReleaseThread(myThreadState);
66 }
67
68 /*!
69   \brief Get Python GIL wrapper.
70   \return GIL lock wrapper (GIL is automatically acquired here)
71 */
72 PyLockWrapper PyInterp_Interp::GetLockWrapper()
73 {
74   return _tstate;
75 }
76
77 /*
78   The following functions are used to hook the Python 
79   interpreter output.
80 */
81
82 static void
83 PyStdOut_dealloc(PyStdOut *self)
84 {
85   PyObject_Del(self);
86 }
87
88 static PyObject*
89 PyStdOut_write(PyStdOut *self, PyObject *args)
90 {
91   char *c;
92   int l;
93   if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
94     return NULL;
95   if(self->_cb==NULL) {
96     if ( self->_iscerr )
97       std::cerr << c ;
98     else
99       std::cout << c ;
100   }
101   else {
102     self->_cb(self->_data,c);
103   }
104   Py_INCREF(Py_None);
105   return Py_None;
106 }
107
108 static PyMethodDef PyStdOut_methods[] = {
109   {"write",  (PyCFunction)PyStdOut_write,  METH_VARARGS,
110     PyDoc_STR("write(string) -> None")},
111   {NULL,    NULL}   /* sentinel */
112 };
113
114 static PyMemberDef PyStdOut_memberlist[] = {
115   {"softspace", T_INT,  offsetof(PyStdOut, softspace), 0,
116    "flag indicating that a space needs to be printed; used by print"},
117   {NULL} /* Sentinel */
118 };
119
120 static PyTypeObject PyStdOut_Type = {
121   /* The ob_type field must be initialized in the module init function
122    * to be portable to Windows without using C++. */
123   PyObject_HEAD_INIT(NULL)
124   0,                            /*ob_size*/
125   "PyOut",                      /*tp_name*/
126   sizeof(PyStdOut),             /*tp_basicsize*/
127   0,                            /*tp_itemsize*/
128   /* methods */
129   (destructor)PyStdOut_dealloc, /*tp_dealloc*/
130   0,                            /*tp_print*/
131   0,                            /*tp_getattr*/
132   0,                            /*tp_setattr*/
133   0,                            /*tp_compare*/
134   0,                            /*tp_repr*/
135   0,                            /*tp_as_number*/
136   0,                            /*tp_as_sequence*/
137   0,                            /*tp_as_mapping*/
138   0,                            /*tp_hash*/
139   0,                            /*tp_call*/
140   0,                            /*tp_str*/
141   PyObject_GenericGetAttr,      /*tp_getattro*/
142   /* softspace is writable:  we must supply tp_setattro */
143   PyObject_GenericSetAttr,      /* tp_setattro */
144   0,                            /*tp_as_buffer*/
145   Py_TPFLAGS_DEFAULT,           /*tp_flags*/
146   0,                            /*tp_doc*/
147   0,                            /*tp_traverse*/
148   0,                            /*tp_clear*/
149   0,                            /*tp_richcompare*/
150   0,                            /*tp_weaklistoffset*/
151   0,                            /*tp_iter*/
152   0,                            /*tp_iternext*/
153   PyStdOut_methods,             /*tp_methods*/
154   PyStdOut_memberlist,          /*tp_members*/
155   0,                            /*tp_getset*/
156   0,                            /*tp_base*/
157   0,                            /*tp_dict*/
158   0,                            /*tp_descr_get*/
159   0,                            /*tp_descr_set*/
160   0,                            /*tp_dictoffset*/
161   0,                            /*tp_init*/
162   0,                            /*tp_alloc*/
163   0,                            /*tp_new*/
164   0,                            /*tp_free*/
165   0,                            /*tp_is_gc*/
166 };
167
168 #define PyStdOut_Check(v)  ((v)->ob_type == &PyStdOut_Type)
169
170 static PyStdOut* newPyStdOut( bool iscerr )
171 {
172   PyStdOut *self;
173   self = PyObject_New(PyStdOut, &PyStdOut_Type);
174   if (self == NULL)
175     return NULL;
176   self->softspace = 0;
177   self->_cb = NULL;
178   self->_iscerr = iscerr;
179   return self;
180 }
181
182 /*!
183   \class PyInterp_Interp
184   \brief Generic embedded Python interpreter.
185 */
186
187 int   PyInterp_Interp::_argc   = 1;
188 char* PyInterp_Interp::_argv[] = {""};
189 PyObject*           PyInterp_Interp::builtinmodule = NULL;
190 PyThreadState*      PyInterp_Interp::_gtstate      = NULL;
191 PyInterpreterState* PyInterp_Interp::_interp       = NULL;
192
193 /*!
194   \brief Basic constructor.
195   
196   After construction the interpreter instance successor classes 
197   must call virtual method initalize().
198 */
199 PyInterp_Interp::PyInterp_Interp(): 
200   _tstate(0), _vout(0), _verr(0), _g(0)
201 {
202 }
203
204 /*!
205   \brief Destructor.
206 */
207 PyInterp_Interp::~PyInterp_Interp()
208 {
209 }
210
211 /*!
212   \brief Initialize embedded interpreter.
213   
214   This method shoud be called after construction of the interpreter.
215   The method initialize() calls virtuals methods
216   - initPython()  to initialize global Python interpreter
217   - initState()   to initialize embedded interpreter state
218   - initContext() to initialize interpreter internal context
219   - initRun()     to prepare interpreter for running commands
220   which should be implemented in the successor classes, according to the
221   embedded Python interpreter policy (mono or multi interpreter, etc).
222 */
223 void PyInterp_Interp::initialize()
224 {
225   _history.clear();       // start a new list of user's commands 
226   _ith = _history.begin();
227
228   initPython();
229   // Here the global lock is released
230
231   initState();
232
233   PyLockWrapper aLock = GetLockWrapper();
234
235   initContext();
236
237   // used to interpret & compile commands
238   PyObjWrapper m(PyImport_ImportModule("codeop"));
239   if(!m) {
240     PyErr_Print();
241     return;
242   }
243
244   // Create python objects to capture stdout and stderr
245   _vout=(PyObject*)newPyStdOut( false ); // stdout 
246   _verr=(PyObject*)newPyStdOut( true );  // stderr
247
248   // All the initRun outputs are redirected to the standard output (console)
249   initRun();
250 }
251
252 /*!
253   \brief Initialize Python interpreter.
254
255   In case if Python is not initialized, it sets program name, initializes the interpreter, sets program arguments,
256   initializes threads. 
257   Otherwise, it just obtains the global interpreter and thread states. This is important for light SALOME configuration, 
258   as in full SALOME this is done at SalomeApp level.
259   \sa SalomeApp_PyInterp class
260  */
261 void PyInterp_Interp::initPython()
262 {
263   if (!Py_IsInitialized()){
264     // Python is not initialized
265     Py_SetProgramName(_argv[0]);
266     Py_Initialize(); // Initialize the interpreter
267     PySys_SetArgv(_argc, _argv);
268     PyEval_InitThreads(); // Create (and acquire) the interpreter lock
269   }
270
271   if ( _interp == NULL )
272     _interp = PyThreadState_Get()->interp;
273   if (PyType_Ready(&PyStdOut_Type) < 0) {
274     PyErr_Print();
275   }
276   if ( _gtstate == NULL )
277     _gtstate = PyEval_SaveThread(); // Release global thread state
278 }
279
280 /*!
281   \brief Get embedded Python interpreter banner.
282   \return banner string
283  */
284 std::string PyInterp_Interp::getbanner()
285 {
286  // Should we take the lock ?
287  // PyEval_RestoreThread(_tstate);
288   std::string aBanner("Python ");
289   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
290   aBanner = aBanner + "\ntype help to get general information on environment\n";
291   //PyEval_SaveThread();
292   return aBanner;
293 }
294
295 /*!
296   \brief Initialize run command.
297  
298   This method is used to prepare interpreter for running 
299   Python commands.
300   
301   \return \c true on success and \c false on error
302 */
303 bool PyInterp_Interp::initRun()
304 {
305   // 
306   // probably all below code isn't required
307   //
308   /*
309   PySys_SetObject("stderr",_verr);
310   PySys_SetObject("stdout",_vout);
311
312   //PyObject *m = PyImport_GetModuleDict();
313   
314   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
315   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
316   */
317   return true;
318 }
319
320 /*!
321   \brief Compile Python command and evaluate it in the 
322          python dictionary context if possible.
323   \internal
324   \param command Python command string
325   \param context Python context (dictionary)
326   \return -1 on fatal error, 1 if command is incomplete and 0
327          if command is executed successfully
328  */
329 static int compile_command(const char *command,PyObject *context)
330 {
331   PyObject *m = PyImport_AddModule("codeop");
332   if(!m) { // Fatal error. No way to go on.
333     PyErr_Print();
334     return -1;
335   }
336   PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
337   if(!v) {
338     // Error encountered. It should be SyntaxError,
339     //so we don't write out traceback
340     PyObjWrapper exception, value, tb;
341     PyErr_Fetch(&exception, &value, &tb);
342     PyErr_NormalizeException(&exception, &value, &tb);
343     PyErr_Display(exception, value, NULL);
344     return -1;
345   }
346   else if (v == Py_None) {
347     // Incomplete text we return 1 : we need a complete text to execute
348     return 1;
349   }
350   else {
351     // Complete and correct text. We evaluate it.
352     //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
353     //    PyObjWrapper r(PyEval_EvalCode(v,context,context));
354     //#else
355     PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
356     //#endif
357     if(!r) {
358       // Execution error. We return -1
359       PyErr_Print();
360       return -1;
361     }
362     // The command has been successfully executed. Return 0
363     return 0;
364   }
365 }
366
367 /*!
368   \brief Run Python command.
369   \param command Python command
370   \return command status
371 */
372 int PyInterp_Interp::run(const char *command)
373 {
374   beforeRun();
375   return simpleRun(command);
376 }
377
378 /*!
379   \brief Run Python command (used internally).
380   \param command Python command
381   \param addToHistory if \c true (default), the command is added to the commands history
382   \return command status
383 */
384 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
385 {
386   if( addToHistory && strcmp(command,"") != 0 ) {
387     _history.push_back(command);
388     _ith = _history.end();
389   }
390
391   // We come from C++ to enter Python world
392   // We need to acquire the Python global lock
393   //PyLockWrapper aLock(_tstate); // san - lock is centralized now
394
395   // Reset redirected outputs before treatment
396   PySys_SetObject("stderr",_verr);
397   PySys_SetObject("stdout",_vout);
398
399   int ier = compile_command(command,_g);
400
401   // Outputs are redirected on standards outputs (console)
402   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
403   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
404
405   return ier;
406 }
407
408 /*!
409   \brief Get previous command in the commands history.
410   \return previous command
411 */
412 const char * PyInterp_Interp::getPrevious()
413 {
414   if(_ith != _history.begin()){
415     _ith--;
416     return (*_ith).c_str();
417   }
418   else
419     return BEGIN_HISTORY_PY;
420 }
421
422 /*!
423   \brief Get next command in the commands history.
424   \return next command
425 */
426 const char * PyInterp_Interp::getNext()
427 {
428   if(_ith != _history.end()){
429     _ith++;
430   }
431   if (_ith == _history.end())
432     return TOP_HISTORY_PY;
433   else
434     return (*_ith).c_str();
435 }
436
437 /*!
438   \brief Set Python standard output device hook.
439   \param cb callback function
440   \param data callback function parameters
441 */
442 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
443 {  
444   ((PyStdOut*)_vout)->_cb=cb;
445   ((PyStdOut*)_vout)->_data=data;
446 }
447
448 /*!
449   \brief Set Python standard error device hook.
450   \param cb callback function
451   \param data callback function parameters
452 */
453 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
454 {  
455   ((PyStdOut*)_verr)->_cb=cb;
456   ((PyStdOut*)_verr)->_data=data;
457 }