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