Salome HOME
Merge branch 'ASL_TREE_STATE' into asl/hydro_porting_741
[modules/gui.git] / src / PyInterp / PyInterp_Interp.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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
23 //  File   : PyInterp_Interp.cxx
24 //  Author : Christian CAREMOLI, Paul RASCLE, EDF
25 //  Module : SALOME
26 //
27 #include "PyInterp_Interp.h"  // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
28 #include <pythread.h>
29
30 #include <cStringIO.h>
31 #include <structmember.h>
32
33 #include <string>
34 #include <vector>
35 #include <map>
36 #include <iostream>
37 #include <algorithm>
38
39 #define TOP_HISTORY_PY   "--- top of history ---"
40 #define BEGIN_HISTORY_PY "--- begin of history ---"
41
42 /*!
43   \class PyLockWrapper
44   \brief Python GIL wrapper.
45 */
46
47 /*!
48   \brief Constructor. Automatically acquires GIL.
49 */
50 PyLockWrapper::PyLockWrapper()
51 {
52   _gil_state = PyGILState_Ensure();
53 }
54
55 /*!
56   \brief Destructor. Automatically releases GIL.
57 */
58 PyLockWrapper::~PyLockWrapper()
59 {
60 //  if (myThreadState->interp == PyInterp_Interp::_interp)
61 //    PyGILState_Release(_savestate);
62 //  else
63 //    PyEval_ReleaseThread(myThreadState);
64
65   /* The destructor can never be called concurrently by two threads since it is called
66    * when the GIL is held - the below test should never run concurrently in two threads.
67    */
68   PyGILState_Release(_gil_state);
69 }
70
71 /*
72   The following functions are used to hook the Python
73   interpreter output.
74 */
75
76 static void
77 PyStdOut_dealloc(PyStdOut *self)
78 {
79   PyObject_Del(self);
80 }
81
82 static PyObject*
83 PyStdOut_write(PyStdOut *self, PyObject *args)
84 {
85   char *c;
86   int l;
87   if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
88     return NULL;
89   if(self->_cb==NULL) {
90     if ( self->_iscerr )
91       std::cerr << c ;
92     else
93       std::cout << c ;
94   }
95   else {
96     self->_cb(self->_data,c);
97   }
98   Py_INCREF(Py_None);
99   return Py_None;
100 }
101
102 static PyObject*
103 PyStdOut_flush(PyStdOut *self)
104 {
105   Py_INCREF(Py_None);
106   return Py_None;
107 }
108
109 static PyMethodDef PyStdOut_methods[] = {
110   {"write",  (PyCFunction)PyStdOut_write,  METH_VARARGS, PyDoc_STR("write(string) -> None")},
111   {"flush",  (PyCFunction)PyStdOut_flush,  METH_NOARGS,  PyDoc_STR("flush() -> None")},
112   {NULL,    NULL}   /* sentinel */
113 };
114
115 static PyMemberDef PyStdOut_memberlist[] = {
116   {(char*)"softspace", T_INT,  offsetof(PyStdOut, softspace), 0,
117    (char*)"flag indicating that a space needs to be printed; used by print"},
118   {NULL} /* Sentinel */
119 };
120
121 static PyTypeObject PyStdOut_Type = {
122   /* The ob_type field must be initialized in the module init function
123    * to be portable to Windows without using C++. */
124   PyObject_HEAD_INIT(NULL)
125   0,                            /*ob_size*/
126   "PyOut",                      /*tp_name*/
127   sizeof(PyStdOut),             /*tp_basicsize*/
128   0,                            /*tp_itemsize*/
129   /* methods */
130   (destructor)PyStdOut_dealloc, /*tp_dealloc*/
131   0,                            /*tp_print*/
132   0,                            /*tp_getattr*/
133   0,                            /*tp_setattr*/
134   0,                            /*tp_compare*/
135   0,                            /*tp_repr*/
136   0,                            /*tp_as_number*/
137   0,                            /*tp_as_sequence*/
138   0,                            /*tp_as_mapping*/
139   0,                            /*tp_hash*/
140   0,                            /*tp_call*/
141   0,                            /*tp_str*/
142   PyObject_GenericGetAttr,      /*tp_getattro*/
143   /* softspace is writable:  we must supply tp_setattro */
144   PyObject_GenericSetAttr,      /* tp_setattro */
145   0,                            /*tp_as_buffer*/
146   Py_TPFLAGS_DEFAULT,           /*tp_flags*/
147   0,                            /*tp_doc*/
148   0,                            /*tp_traverse*/
149   0,                            /*tp_clear*/
150   0,                            /*tp_richcompare*/
151   0,                            /*tp_weaklistoffset*/
152   0,                            /*tp_iter*/
153   0,                            /*tp_iternext*/
154   PyStdOut_methods,             /*tp_methods*/
155   PyStdOut_memberlist,          /*tp_members*/
156   0,                            /*tp_getset*/
157   0,                            /*tp_base*/
158   0,                            /*tp_dict*/
159   0,                            /*tp_descr_get*/
160   0,                            /*tp_descr_set*/
161   0,                            /*tp_dictoffset*/
162   0,                            /*tp_init*/
163   0,                            /*tp_alloc*/
164   0,                            /*tp_new*/
165   0,                            /*tp_free*/
166   0,                            /*tp_is_gc*/
167 };
168
169 #define PyStdOut_Check(v)  ((v)->ob_type == &PyStdOut_Type)
170
171 static PyStdOut* newPyStdOut( bool iscerr )
172 {
173   PyStdOut *self;
174   self = PyObject_New(PyStdOut, &PyStdOut_Type);
175   if (self == NULL)
176     return NULL;
177   self->softspace = 0;
178   self->_cb = NULL;
179   self->_iscerr = iscerr;
180   return self;
181 }
182
183 /*!
184   \class PyInterp_Interp
185   \brief Generic embedded Python interpreter.
186 */
187
188 int   PyInterp_Interp::_argc   = 1;
189 char* PyInterp_Interp::_argv[] = {(char*)""};
190 //PyObject*           PyInterp_Interp::builtinmodule = NULL;
191 //PyThreadState*      PyInterp_Interp::_gtstate      = NULL;
192 //PyInterpreterState* PyInterp_Interp::_interp       = NULL;
193
194 /*!
195   \brief Basic constructor.
196
197   After construction the interpreter instance successor classes
198   must call virtual method initalize().
199 */
200 PyInterp_Interp::PyInterp_Interp():
201   _vout(0), _verr(0), _context(0)
202 {
203 }
204
205
206
207 /*!
208   \brief Destructor.
209 */
210 PyInterp_Interp::~PyInterp_Interp()
211 {
212 }
213
214 /*!
215   \brief Initialize embedded interpreter.
216
217   This method shoud be called after construction of the interpreter.
218   The method initialize() calls virtuals methods
219   - initPython()  to initialize global Python interpreter
220   - initState()   to initialize embedded interpreter state
221   - initContext() to initialize interpreter internal context
222   - initRun()     to prepare interpreter for running commands
223   which should be implemented in the successor classes, according to the
224   embedded Python interpreter policy (mono or multi interpreter, etc).
225 */
226 void PyInterp_Interp::initialize()
227 {
228   _history.clear();       // start a new list of user's commands
229   _ith = _history.begin();
230
231   initPython();  // This also inits the multi-threading for Python (but w/o acquiring GIL)
232
233   //initState(); // [ABN] OBSOLETE
234
235   // ---- The rest of the initialisation process is done hodling the GIL
236   PyLockWrapper lck;
237
238   initContext();
239
240   // used to interpret & compile commands - this is really imported here
241   // and only added again (with PyImport_AddModule) later on
242   PyObjWrapper m(PyImport_ImportModule("codeop"));
243   if(!m) {
244     PyErr_Print();
245     PyEval_ReleaseLock();
246     return;
247   }
248
249   // Create python objects to capture stdout and stderr
250   _vout=(PyObject*)newPyStdOut( false ); // stdout
251   _verr=(PyObject*)newPyStdOut( true );  // stderr
252
253   // All the initRun outputs are redirected to the standard output (console)
254   initRun();
255 }
256
257 void PyInterp_Interp::destroy()
258 {
259   PyLockWrapper lck;
260   closeContext();
261 }
262
263 /*!
264   \brief Initialize Python interpreter.
265
266   In case if Python is not initialized, it sets program name, initializes the single true Python
267   interpreter, sets program arguments, and initializes threads.
268   Otherwise, does nothing. This is important for light SALOME configuration,
269   as in full SALOME this is done at SalomeApp level.
270   \sa SalomeApp_PyInterp class and main() in SALOME_Session_Server
271  */
272 void PyInterp_Interp::initPython()
273 {
274   if (!Py_IsInitialized()){
275     // Python is not initialized
276     Py_SetProgramName(_argv[0]);
277     Py_Initialize(); // Initialize the interpreter
278     PySys_SetArgv(_argc, _argv);
279
280     PyEval_InitThreads(); // Create (and acquire) the Python global interpreter lock (GIL)
281     PyEval_ReleaseLock();
282   }
283 }
284
285 /*!
286   \brief Get embedded Python interpreter banner.
287   \return banner string
288  */
289 std::string PyInterp_Interp::getbanner() const
290 {
291   PyLockWrapper lck;
292   std::string aBanner("Python ");
293   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
294   aBanner = aBanner + "\ntype help to get general information on environment\n";
295   return aBanner;
296 }
297
298 /*!
299   \brief Initialize run command.
300
301   This method is used to prepare interpreter for running
302   Python commands.
303
304   \return \c true on success and \c false on error
305 */
306 bool PyInterp_Interp::initRun()
307 {
308   return true;
309 }
310
311 void PyInterp_Interp::closeContext()
312 {
313 }
314
315 /*!
316   \brief Compile Python command and evaluate it in the
317          python dictionary context if possible. This is not thread-safe.
318          This is the caller's responsability to make this thread-safe.
319   \internal
320   \param command Python command string
321   \param context Python context (dictionary)
322   \return -1 on fatal error, 1 if command is incomplete and 0
323          if command is executed successfully
324  */
325 static int run_command(const char *command, PyObject *context)
326 {
327   PyObject *m = PyImport_AddModule("codeop");
328   if(!m) { // Fatal error. No way to go on.
329     PyErr_Print();
330     return -1;
331   }
332   PyObjWrapper v(PyObject_CallMethod(m,(char*)"compile_command",(char*)"s",command));
333   if(!v) {
334     // Error encountered. It should be SyntaxError,
335     //so we don't write out traceback
336     PyObjWrapper exception, value, tb;
337     PyErr_Fetch(&exception, &value, &tb);
338     PyErr_NormalizeException(&exception, &value, &tb);
339     PyErr_Display(exception, value, NULL);
340     return -1;
341   }
342   else if (v == Py_None) {
343     // Incomplete text we return 1 : we need a complete text to execute
344     return 1;
345   }
346   else {
347     PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
348     if(!r) {
349       // Execution error. We return -1
350       PyErr_Print();
351       return -1;
352     }
353     // The command has been successfully executed. Return 0
354     return 0;
355   }
356 }
357
358 void replaceAll(std::string& str, const std::string& from, const std::string& to) {
359     if(from.empty())
360         return;
361     size_t start_pos = 0;
362     while((start_pos = str.find(from, start_pos)) != std::string::npos) {
363         str.replace(start_pos, from.length(), to);
364         start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
365     }
366 }
367 /*!
368   \brief Compile Python command and evaluate it in the
369          python dictionary context if possible. Command might correspond to
370          the execution of a script with optional arguments.
371          In this case, command is:
372          execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
373   \internal
374   \param command Python command string
375   \param context Python context (dictionary)
376   \return -1 on fatal error, 1 if command is incomplete and 0
377          if command is executed successfully
378  */
379 static int compile_command(const char *command, PyObject *context)
380 {
381   // First guess if command is execution of a script with args, or a simple Python command
382   std::string singleCommand = command;
383   std::string commandArgs = "";
384
385   std::size_t pos = std::string(command).find("args:");
386   if (pos != std::string::npos) {
387     commandArgs = singleCommand.substr(pos+5);
388     commandArgs = commandArgs.substr(0, commandArgs.length()-3);
389     singleCommand = singleCommand.substr(0, pos-1)+"\")";
390   }
391
392   if (commandArgs.empty()) {
393     // process command: expression
394     // process command: execfile(r"/absolute/path/to/script.py") (no args)
395     return run_command(singleCommand.c_str(), context);
396   }
397   else {
398     // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
399     std::string script = singleCommand.substr(11); // remove leading execfile(r"
400     script = script.substr(0, script.length()-2); // remove trailing ")
401
402     std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
403     std::string preCommandEnd = "];";
404     replaceAll(commandArgs, ",", "\",\"");
405     commandArgs = "\""+commandArgs+"\"";
406     std::string completeCommand = preCommandBegin+"\""+script+"\","+commandArgs+preCommandEnd+singleCommand+";sys.argv=save_argv";
407     return run_command(completeCommand.c_str(), context);
408   }
409 }
410
411 /*!
412   \brief Run Python command - the command has to fit on a single line (no \n!).
413   Use ';' if you need multiple statements evaluated at once.
414   \param command Python command
415   \return command status
416 */
417 int PyInterp_Interp::run(const char *command)
418 {
419   beforeRun();
420   return simpleRun(command);
421 }
422
423 /**
424  * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsability
425  * to acquire GIL if needed.
426  */
427 int PyInterp_Interp::beforeRun()
428 {
429   return 0;
430 }
431
432 /*!
433   \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsability.
434   \param command Python command
435   \param addToHistory if \c true (default), the command is added to the commands history
436   \return command status
437 */
438 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
439 {
440   if( addToHistory && strcmp(command,"") != 0 ) {
441     _history.push_back(command);
442     _ith = _history.end();
443   }
444
445   // Current stdout and stderr are saved
446   PyObject * oldOut = PySys_GetObject((char*)"stdout");
447   PyObject * oldErr = PySys_GetObject((char*)"stderr");
448   // Keep them alive (PySys_GetObject returned a *borrowed* ref!)
449   Py_INCREF(oldOut);
450   Py_INCREF(oldErr);
451
452   // Redirect outputs to SALOME Python console before treatment
453   PySys_SetObject((char*)"stderr",_verr);
454   PySys_SetObject((char*)"stdout",_vout);
455
456   int ier = compile_command(command,_context);
457
458   // Outputs are redirected to what they were before
459   PySys_SetObject((char*)"stdout",oldOut);
460   PySys_SetObject((char*)"stderr",oldErr);
461
462   return ier;
463 }
464
465 /*!
466   \brief Get previous command in the commands history.
467   \return previous command
468 */
469 const char * PyInterp_Interp::getPrevious()
470 {
471   if(_ith != _history.begin()){
472     _ith--;
473     return (*_ith).c_str();
474   }
475   else
476     return BEGIN_HISTORY_PY;
477 }
478
479 /*!
480   \brief Get next command in the commands history.
481   \return next command
482 */
483 const char * PyInterp_Interp::getNext()
484 {
485   if(_ith != _history.end()){
486     _ith++;
487   }
488   if (_ith == _history.end())
489     return TOP_HISTORY_PY;
490   else
491     return (*_ith).c_str();
492 }
493
494 /*!
495   \brief Set Python standard output device hook.
496   \param cb callback function
497   \param data callback function parameters
498 */
499 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
500 {
501   ((PyStdOut*)_vout)->_cb=cb;
502   ((PyStdOut*)_vout)->_data=data;
503 }
504
505 /*!
506   \brief Set Python standard error device hook.
507   \param cb callback function
508   \param data callback function parameters
509 */
510 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
511 {
512   ((PyStdOut*)_verr)->_cb=cb;
513   ((PyStdOut*)_verr)->_data=data;
514 }