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