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