Salome HOME
Merge tag 'V8_3_0a2' into ngr/python3_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   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   PyVarObject_HEAD_INIT(NULL, 0)
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     wchar_t **changed_argv = new wchar_t*[_argc]; // Setting arguments
246     size_t mbslen;
247     for (int i = 0; i < _argc; i++)
248     {
249       changed_argv[i] = Py_DecodeLocale(_argv[i], NULL);
250     }
251    
252     Py_SetProgramName(changed_argv[0]);
253     Py_Initialize(); // Initialize the interpreter
254     PySys_SetArgv(_argc, changed_argv);
255
256     PyEval_InitThreads(); // Create (and acquire) the Python global interpreter lock (GIL)
257     PyEval_ReleaseLock();
258   }
259 }
260
261 /*!
262   \brief Get embedded Python interpreter banner.
263   \return banner string
264  */
265 std::string PyInterp_Interp::getBanner() const
266 {
267   PyLockWrapper lck;
268   std::string aBanner("Python ");
269   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
270   aBanner = aBanner + "\ntype help to get general information on environment\n";
271   return aBanner;
272 }
273
274 /*!
275   \brief Initialize run command.
276
277   This method is used to prepare interpreter for running
278   Python commands.
279
280   \return \c true on success and \c false on error
281 */
282 bool PyInterp_Interp::initRun()
283 {
284   return true;
285 }
286
287 /*!
288  * Initialize context dictionaries. GIL is held already.
289  * The code executed in an embedded interpreter is expected to be run at the module
290  * level, in which case local and global context have to be the same dictionary.
291  * See: http://stackoverflow.com/questions/12265756/c-python-running-python-code-within-a-context
292  * for an explanation.
293  */
294 bool PyInterp_Interp::initContext()
295 {
296   PyObject *m = PyImport_AddModule("__main__");  // interpreter main module (module context)
297   if(!m){
298     PyErr_Print();
299     return false;
300   }
301   _global_context = PyModule_GetDict(m);          // get interpreter global variable context
302   Py_INCREF(_global_context);
303   _local_context = _global_context;
304
305   return true;
306 }
307
308 /*!
309  * Destroy context dictionaries. GIL is held already.
310  */
311 void PyInterp_Interp::closeContext()
312 {
313   Py_XDECREF(_global_context);
314   // both _global_context and _local_context may point to the same Python object
315   if ( _global_context != _local_context)
316     Py_XDECREF(_local_context);
317 }
318
319 /*!
320   \brief Compile Python command and evaluate it in the
321          python dictionary contexts if possible. This is not thread-safe.
322          This is the caller's responsability to make this thread-safe.
323   \internal
324   \param command Python command string
325   \return -1 on fatal error, 1 if command is incomplete and 0
326          if command is executed successfully
327  */
328 static int run_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
329 {
330   PyObject *m = PyImport_AddModule("codeop");
331   if(!m) {
332     // Fatal error. No way to go on.
333     PyErr_Print();
334     return -1;
335   }
336
337   PyObjWrapper v(PyObject_CallMethod(m,(char*)"compile_command",(char*)"s",command));
338   if(!v) {
339     // Error encountered. It should be SyntaxError,
340     //so we don't write out traceback
341     PyObjWrapper exception, value, tb;
342     PyErr_Fetch(&exception, &value, &tb);
343     PyErr_NormalizeException(&exception, &value, &tb);
344     PyErr_Display(exception, value, NULL);
345     return -1;
346   }
347   else if (v == Py_None) {
348     // Incomplete text we return 1 : we need a complete text to execute
349     return 1;
350   }
351   else {
352     PyObjWrapper r(PyEval_EvalCode((PyObject *)(void *)v,global_ctxt, local_ctxt));
353     if(!r) {
354       // Execution error. We return -1
355       PyErr_Print();
356       return -1;
357     }
358     // The command has been successfully executed. Return 0
359     return 0;
360   }
361 }
362
363 void replaceAll(std::string& str, const std::string& from, const std::string& to) {
364     if(from.empty())
365         return;
366     size_t start_pos = 0;
367     while((start_pos = str.find(from, start_pos)) != std::string::npos) {
368         str.replace(start_pos, from.length(), to);
369         start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
370     }
371 }
372
373 std::vector<std::string>
374 __split(const std::string& str, char delimiter)
375 {
376   std::vector<std::string> internal;
377   std::stringstream ss(str); // Turn the string into a stream.
378   std::string tok;
379
380   while (getline(ss, tok, delimiter)) {
381     internal.push_back(tok);
382   }
383
384   return internal;
385 }
386
387 std::string
388 __join(const std::vector<std::string>& v, int begin=0, int end=-1)
389 {
390   if (end == -1)
391     end = v.size();
392   std::stringstream ss;
393   for (size_t i = begin; i < end; ++i) {
394     if (i != begin)
395       ss << ",";
396     ss << v[i];
397   }
398   return ss.str();
399 }
400
401 std::vector<std::string>
402 __getArgsList(std::string argsString)
403 {
404   // Special process if some items of 'args:' list are themselves lists
405   // Note that an item can be a list, but not a list of lists...
406   // So we can have something like this:
407   // myscript.py args:[\'file1\',\'file2\'],\'val1\',\"done\",[1,2,3],[True,False],\"ok\",kwarg1=\'kwarg1\',kwarg2=\'kwarg2\',\'fin\'
408   // 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'
409   // We have to split argsString to obtain a 9 string elements list
410   std::vector<std::string> x = __split(argsString, ',');
411   bool containsList = (argsString.find('[') != std::string::npos);
412   if (containsList) {
413     std::vector<int> listBeginIndices, listEndIndices;
414     for (int pos = 0; pos < x.size(); ++pos) {
415       if (x[pos][0] == '[')
416         listBeginIndices.push_back(pos);
417       else if (x[pos][x[pos].size()-1] == ']')
418         listEndIndices.push_back(pos);
419     }
420     std::vector<std::string> extractedArgs;
421     int start = 0;
422     for (int pos = 0; pos < listBeginIndices.size(); ++pos) {
423       int lbeg = listBeginIndices[pos];
424       int lend = listEndIndices[pos];
425       if (lbeg > start)
426         for (int k = start; k < lbeg; ++k)
427           extractedArgs.push_back(x[k]);
428       extractedArgs.push_back(__join(x, lbeg, lend+1));
429       start = lend+1;
430     }
431     if (start < x.size())
432       for (int k = start; k < x.size(); ++k)
433         extractedArgs.push_back(x[k]);
434     return extractedArgs;
435   }
436   else {
437     return x;
438   }
439 }
440
441 /*!
442   \brief Compile Python command and evaluate it in the
443          python dictionary context if possible. Command might correspond to
444          the execution of a script with optional arguments.
445          In this case, command is:
446          execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
447   \internal
448   \param command Python command string
449   \param context Python context (dictionary)
450   \return -1 on fatal error, 1 if command is incomplete and 0
451          if command is executed successfully
452  */
453 static int compile_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
454 {
455   // First guess if command is execution of a script with args, or a simple Python command
456   std::string singleCommand = command;
457   std::string commandArgs = "";
458
459   QRegExp rx("execfile\\s*\\(.*(args:.*)\"\\s*\\)");
460   if (rx.indexIn(command) != -1) {
461     commandArgs = rx.cap(1).remove(0,5).toStdString(); // arguments of command
462     singleCommand = rx.cap().remove(rx.cap(1)).remove(" ").toStdString(); // command for execution without arguments
463   }
464
465   if (commandArgs.empty()) {
466     // process command: expression
467     // process command: execfile(r"/absolute/path/to/script.py") (no args)
468     return run_command(singleCommand.c_str(), global_ctxt, local_ctxt);
469   }
470   else {
471     // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
472     std::string script = singleCommand.substr(11); // remove leading execfile(r"
473     script = script.substr(0, script.length()-2); // remove trailing ")
474     std::vector<std::string> argList = __getArgsList(commandArgs);
475
476     std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
477     std::string preCommandEnd = "];";
478     std::string completeCommand = preCommandBegin+"\""+script+"\",";
479     for (std::vector<std::string>::iterator itr = argList.begin(); itr != argList.end(); ++itr) {
480       if (itr != argList.begin())
481         completeCommand += ",";
482       completeCommand = completeCommand + "\"" + *itr + "\"";
483     }
484     completeCommand = completeCommand+preCommandEnd+singleCommand+";sys.argv=save_argv";
485     return run_command(completeCommand.c_str(), global_ctxt, local_ctxt);
486   }
487 }
488
489 /*!
490   \brief Run Python command - the command has to fit on a single line (no \n!).
491   Use ';' if you need multiple statements evaluated at once.
492   \param command Python command
493   \return command status
494 */
495 int PyInterp_Interp::run(const char *command)
496 {
497   beforeRun();
498   int ret = simpleRun(command);
499   afterRun();
500   return ret;
501 }
502
503 /**
504  * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsability
505  * to acquire GIL if needed.
506  */
507 int PyInterp_Interp::beforeRun()
508 {
509   return 0;
510 }
511
512 /**
513  * Called after a command is run (when calling run() method). Not thread-safe. Caller's responsability
514  * to acquire GIL if needed.
515  */
516 int PyInterp_Interp::afterRun()
517 {
518   return 0;
519 }
520
521 /*!
522   \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsability.
523   \param command Python command
524   \param addToHistory if \c true (default), the command is added to the commands history
525   \return command status
526 */
527 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
528 {
529   if( addToHistory && strcmp(command,"") != 0 ) {
530     _history.push_back(command);
531     _ith = _history.end();
532   }
533
534   // Current stdout and stderr are saved
535   PyObject * oldOut = PySys_GetObject((char*)"stdout");
536   PyObject * oldErr = PySys_GetObject((char*)"stderr");
537   // Keep them alive (PySys_GetObject returned a *borrowed* ref!)
538   Py_INCREF(oldOut);
539   Py_INCREF(oldErr);
540
541   // Redirect outputs to SALOME Python console before treatment
542   PySys_SetObject((char*)"stderr",_verr);
543   PySys_SetObject((char*)"stdout",_vout);
544
545   int ier = compile_command(command, _global_context, _local_context);
546
547   // Outputs are redirected to what they were before
548   PySys_SetObject((char*)"stdout",oldOut);
549   PySys_SetObject((char*)"stderr",oldErr);
550
551   return ier;
552 }
553
554 /*!
555   \brief Get previous command in the commands history.
556   \return previous command
557 */
558 const char * PyInterp_Interp::getPrevious()
559 {
560   if(_ith != _history.begin()){
561     _ith--;
562     return (*_ith).c_str();
563   }
564   else
565     return BEGIN_HISTORY_PY;
566 }
567
568 /*!
569   \brief Get next command in the commands history.
570   \return next command
571 */
572 const char * PyInterp_Interp::getNext()
573 {
574   if(_ith != _history.end()){
575     _ith++;
576   }
577   if (_ith == _history.end())
578     return TOP_HISTORY_PY;
579   else
580     return (*_ith).c_str();
581 }
582
583 /*!
584   \brief Set Python standard output device hook.
585   \param cb callback function
586   \param data callback function parameters
587 */
588 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
589 {
590   ((PyStdOut*)_vout)->_cb=cb;
591   ((PyStdOut*)_vout)->_data=data;
592 }
593
594 /*!
595   \brief Set Python standard error device hook.
596   \param cb callback function
597   \param data callback function parameters
598 */
599 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
600 {
601   ((PyStdOut*)_verr)->_cb=cb;
602   ((PyStdOut*)_verr)->_data=data;
603 }
604
605 /*!
606   \bried Check if the interpreter is initialized
607   \internal
608 */
609 bool PyInterp_Interp::initialized() const
610 {
611   return _initialized;
612 }