Salome HOME
Modifying build procedure to expose PyConsole and PyInterp as tools.
[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_ReleaseLock();
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   int ret = PyRun_SimpleString("import salome_iapp;salome_iapp.IN_SALOME_GUI=True");
299
300   return ret == 0;
301 }
302
303 /*!
304  * Destroy context dictionaries. GIL is held already.
305  */
306 void PyInterp_Interp::closeContext()
307 {
308   Py_XDECREF(_global_context);
309   // both _global_context and _local_context may point to the same Python object
310   if ( _global_context != _local_context)
311     Py_XDECREF(_local_context);
312 }
313
314 /*!
315   \brief Compile Python command and evaluate it in the
316          python dictionary contexts if possible. This is not thread-safe.
317          This is the caller's responsability to make this thread-safe.
318   \internal
319   \param command Python command string
320   \return -1 on fatal error, 1 if command is incomplete and 0
321          if command is executed successfully
322  */
323 static int run_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
324 {
325   PyObject *m = PyImport_AddModule("codeop");
326   if(!m) {
327     // Fatal error. No way to go on.
328     PyErr_Print();
329     return -1;
330   }
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,global_ctxt, local_ctxt));
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 std::vector<std::string>
369 __split(const std::string& str, char delimiter)
370 {
371   std::vector<std::string> internal;
372   std::stringstream ss(str); // Turn the string into a stream.
373   std::string tok;
374
375   while (getline(ss, tok, delimiter)) {
376     internal.push_back(tok);
377   }
378
379   return internal;
380 }
381
382 std::string
383 __join(const std::vector<std::string>& v, int begin=0, int end=-1)
384 {
385   if (end == -1)
386     end = v.size();
387   std::stringstream ss;
388   for (size_t i = begin; i < end; ++i) {
389     if (i != begin)
390       ss << ",";
391     ss << v[i];
392   }
393   return ss.str();
394 }
395
396 std::vector<std::string>
397 __getArgsList(std::string argsString)
398 {
399   // Special process if some items of 'args:' list are themselves lists
400   // Note that an item can be a list, but not a list of lists...
401   // So we can have something like this:
402   // myscript.py args:[\'file1\',\'file2\'],\'val1\',\"done\",[1,2,3],[True,False],\"ok\",kwarg1=\'kwarg1\',kwarg2=\'kwarg2\',\'fin\'
403   // 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'
404   // We have to split argsString to obtain a 9 string elements list
405   std::vector<std::string> x = __split(argsString, ',');
406   bool containsList = (argsString.find('[') != std::string::npos);
407   if (containsList) {
408     std::vector<int> listBeginIndices, listEndIndices;
409     for (int pos = 0; pos < x.size(); ++pos) {
410       if (x[pos][0] == '[')
411         listBeginIndices.push_back(pos);
412       else if (x[pos][x[pos].size()-1] == ']')
413         listEndIndices.push_back(pos);
414     }
415     std::vector<std::string> extractedArgs;
416     int start = 0;
417     for (int pos = 0; pos < listBeginIndices.size(); ++pos) {
418       int lbeg = listBeginIndices[pos];
419       int lend = listEndIndices[pos];
420       if (lbeg > start)
421         for (int k = start; k < lbeg; ++k)
422           extractedArgs.push_back(x[k]);
423       extractedArgs.push_back(__join(x, lbeg, lend+1));
424       start = lend+1;
425     }
426     if (start < x.size())
427       for (int k = start; k < x.size(); ++k)
428         extractedArgs.push_back(x[k]);
429     return extractedArgs;
430   }
431   else {
432     return x;
433   }
434 }
435
436 /*!
437   \brief Compile Python command and evaluate it in the
438          python dictionary context if possible. Command might correspond to
439          the execution of a script with optional arguments.
440          In this case, command is:
441          execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
442   \internal
443   \param command Python command string
444   \param context Python context (dictionary)
445   \return -1 on fatal error, 1 if command is incomplete and 0
446          if command is executed successfully
447  */
448 static int compile_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
449 {
450   // First guess if command is execution of a script with args, or a simple Python command
451   std::string singleCommand = command;
452   std::string commandArgs = "";
453
454   QRegExp rx("execfile\\s*\\(.*(args:.*)\"\\s*\\)");
455   if (rx.indexIn(command) != -1) {
456     commandArgs = rx.cap(1).remove(0,5).toStdString(); // arguments of command
457     singleCommand = rx.cap().remove(rx.cap(1)).remove(" ").toStdString(); // command for execution without arguments
458   }
459
460   if (commandArgs.empty()) {
461     // process command: expression
462     // process command: execfile(r"/absolute/path/to/script.py") (no args)
463     return run_command(singleCommand.c_str(), global_ctxt, local_ctxt);
464   }
465   else {
466     // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
467     std::string script = singleCommand.substr(11); // remove leading execfile(r"
468     script = script.substr(0, script.length()-2); // remove trailing ")
469     std::vector<std::string> argList = __getArgsList(commandArgs);
470
471     std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
472     std::string preCommandEnd = "];";
473     std::string completeCommand = preCommandBegin+"\""+script+"\",";
474     for (std::vector<std::string>::iterator itr = argList.begin(); itr != argList.end(); ++itr) {
475       if (itr != argList.begin())
476         completeCommand += ",";
477       completeCommand = completeCommand + "\"" + *itr + "\"";
478     }
479     completeCommand = completeCommand+preCommandEnd+singleCommand+";sys.argv=save_argv";
480     return run_command(completeCommand.c_str(), global_ctxt, local_ctxt);
481   }
482 }
483
484 /*!
485   \brief Run Python command - the command has to fit on a single line (no \n!).
486   Use ';' if you need multiple statements evaluated at once.
487   \param command Python command
488   \return command status
489 */
490 int PyInterp_Interp::run(const char *command)
491 {
492   beforeRun();
493   int ret = simpleRun(command);
494   afterRun();
495   return ret;
496 }
497
498 /**
499  * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsability
500  * to acquire GIL if needed.
501  */
502 int PyInterp_Interp::beforeRun()
503 {
504   return 0;
505 }
506
507 /**
508  * Called after a command is run (when calling run() method). Not thread-safe. Caller's responsability
509  * to acquire GIL if needed.
510  */
511 int PyInterp_Interp::afterRun()
512 {
513   return 0;
514 }
515
516 /*!
517   \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsability.
518   \param command Python command
519   \param addToHistory if \c true (default), the command is added to the commands history
520   \return command status
521 */
522 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
523 {
524   if( addToHistory && strcmp(command,"") != 0 ) {
525     _history.push_back(command);
526     _ith = _history.end();
527   }
528
529   // Current stdout and stderr are saved
530   PyObject * oldOut = PySys_GetObject((char*)"stdout");
531   PyObject * oldErr = PySys_GetObject((char*)"stderr");
532   // Keep them alive (PySys_GetObject returned a *borrowed* ref!)
533   Py_INCREF(oldOut);
534   Py_INCREF(oldErr);
535
536   // Redirect outputs to SALOME Python console before treatment
537   PySys_SetObject((char*)"stderr",_verr);
538   PySys_SetObject((char*)"stdout",_vout);
539
540   int ier = compile_command(command, _global_context, _local_context);
541
542   // Outputs are redirected to what they were before
543   PySys_SetObject((char*)"stdout",oldOut);
544   PySys_SetObject((char*)"stderr",oldErr);
545
546   return ier;
547 }
548
549 /*!
550   \brief Get previous command in the commands history.
551   \return previous command
552 */
553 const char * PyInterp_Interp::getPrevious()
554 {
555   if(_ith != _history.begin()){
556     _ith--;
557     return (*_ith).c_str();
558   }
559   else
560     return BEGIN_HISTORY_PY;
561 }
562
563 /*!
564   \brief Get next command in the commands history.
565   \return next command
566 */
567 const char * PyInterp_Interp::getNext()
568 {
569   if(_ith != _history.end()){
570     _ith++;
571   }
572   if (_ith == _history.end())
573     return TOP_HISTORY_PY;
574   else
575     return (*_ith).c_str();
576 }
577
578 /*!
579   \brief Set Python standard output device hook.
580   \param cb callback function
581   \param data callback function parameters
582 */
583 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
584 {
585   ((PyStdOut*)_vout)->_cb=cb;
586   ((PyStdOut*)_vout)->_data=data;
587 }
588
589 /*!
590   \brief Set Python standard error device hook.
591   \param cb callback function
592   \param data callback function parameters
593 */
594 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
595 {
596   ((PyStdOut*)_verr)->_cb=cb;
597   ((PyStdOut*)_verr)->_data=data;
598 }
599
600 /*!
601   \bried Check if the interpreter is initialized
602   \internal
603 */
604 bool PyInterp_Interp::initialized() const
605 {
606   return _initialized;
607 }