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