1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : PyInterp_Interp.cxx
23 // Author : Christian CAREMOLI, Paul RASCLE, Adrien BRUNETON
25 #include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
26 #include "PyInterp_Utils.h"
29 //#include <cStringIO.h>
30 #include <structmember.h>
40 #define TOP_HISTORY_PY "--- top of history ---"
41 #define BEGIN_HISTORY_PY "--- begin of history ---"
43 #if PY_VERSION_HEX < 0x03050000
45 Py_DecodeLocale(const char *arg, size_t *size)
50 size_t argsize = strlen(arg) + 1;
52 if (argsize > PY_SSIZE_T_MAX/sizeof(wchar_t))
54 res = (wchar_t*) PyMem_RawMalloc(argsize*sizeof(wchar_t));
58 in = (unsigned char*)arg;
64 *out++ = 0xdc00 + *in++;
73 The following functions are used to hook the Python
78 PyStdOut_dealloc(PyStdOut *self)
84 PyStdOut_write(PyStdOut *self, PyObject *args)
88 if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
97 self->_cb(self->_data,c);
104 PyStdOut_flush(PyStdOut *self)
110 static PyMethodDef PyStdOut_methods[] = {
111 {"write", (PyCFunction)PyStdOut_write, METH_VARARGS, PyDoc_STR("write(string) -> None")},
112 {"flush", (PyCFunction)PyStdOut_flush, METH_NOARGS, PyDoc_STR("flush() -> None")},
113 {NULL, NULL} /* sentinel */
116 static PyMemberDef PyStdOut_memberlist[] = {
117 {(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
118 (char*)"flag indicating that a space needs to be printed; used by print"},
119 {NULL} /* Sentinel */
122 static PyTypeObject PyStdOut_Type = {
123 /* The ob_type field must be initialized in the module init function
124 * to be portable to Windows without using C++. */
125 PyVarObject_HEAD_INIT(NULL, 0)
128 sizeof(PyStdOut), /*tp_basicsize*/
131 (destructor)PyStdOut_dealloc, /*tp_dealloc*/
138 0, /*tp_as_sequence*/
143 PyObject_GenericGetAttr, /*tp_getattro*/
144 /* softspace is writable: we must supply tp_setattro */
145 PyObject_GenericSetAttr, /* tp_setattro */
147 Py_TPFLAGS_DEFAULT, /*tp_flags*/
151 0, /*tp_richcompare*/
152 0, /*tp_weaklistoffset*/
155 PyStdOut_methods, /*tp_methods*/
156 PyStdOut_memberlist, /*tp_members*/
170 #define PyStdOut_Check(v) ((v)->ob_type == &PyStdOut_Type)
172 static PyStdOut* newPyStdOut( bool iscerr )
175 self = PyObject_New(PyStdOut, &PyStdOut_Type);
180 self->_iscerr = iscerr;
185 \class PyInterp_Interp
186 \brief Generic embedded Python interpreter.
189 int PyInterp_Interp::_argc = 1;
190 char* PyInterp_Interp::_argv[] = {(char*)""};
193 \brief Basic constructor.
195 After construction the interpreter instance successor classes
196 must call virtual method initalize().
198 PyInterp_Interp::PyInterp_Interp():
199 _vout(0), _verr(0), _local_context(0), _global_context(0), _initialized(false)
206 PyInterp_Interp::~PyInterp_Interp()
212 \brief Initialize embedded interpreter.
214 This method shoud be called after construction of the interpreter.
215 The method initialize() calls virtuals methods
216 - initPython() to initialize global Python interpreter
217 - initContext() to initialize interpreter internal context
218 - initRun() to prepare interpreter for running commands
219 which should be implemented in the successor classes, according to the
220 embedded Python interpreter policy (mono or multi interpreter, etc).
222 void PyInterp_Interp::initialize()
225 return; // prevent repeating intitialization
229 _history.clear(); // start a new list of user's commands
230 _ith = _history.begin();
232 initPython(); // This also inits the multi-threading for Python (but w/o acquiring GIL)
234 // ---- The rest of the initialisation process is done hodling the GIL
239 // used to interpret & compile commands - this is really imported here
240 // and only added again (with PyImport_AddModule) later on
241 PyObjWrapper m(PyImport_ImportModule("codeop"));
247 // Create python objects to capture stdout and stderr
248 _vout=(PyObject*)newPyStdOut( false ); // stdout
249 _verr=(PyObject*)newPyStdOut( true ); // stderr
251 // All the initRun outputs are redirected to the standard output (console)
255 void PyInterp_Interp::destroy()
262 \brief Initialize Python interpreter.
264 In case if Python is not initialized, it sets program name, initializes the single true Python
265 interpreter, sets program arguments, and initializes threads.
266 Otherwise, does nothing. This is important for light SALOME configuration,
267 as in full SALOME this is done at SalomeApp level.
268 \sa SalomeApp_PyInterp class and main() in SALOME_Session_Server
270 void PyInterp_Interp::initPython()
272 if (!Py_IsInitialized()){
273 // Python is not initialized
274 wchar_t **changed_argv = new wchar_t*[_argc]; // Setting arguments
276 for (int i = 0; i < _argc; i++)
278 changed_argv[i] = Py_DecodeLocale(_argv[i], NULL);
281 Py_SetProgramName(changed_argv[0]);
282 Py_Initialize(); // Initialize the interpreter
283 PySys_SetArgv(_argc, changed_argv);
285 PyEval_InitThreads(); // Create (and acquire) the Python global interpreter lock (GIL)
286 PyEval_ReleaseLock();
291 \brief Get embedded Python interpreter banner.
292 \return banner string
294 std::string PyInterp_Interp::getBanner() const
297 std::string aBanner("Python ");
298 aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
299 aBanner = aBanner + "\ntype help to get general information on environment\n";
304 \brief Initialize run command.
306 This method is used to prepare interpreter for running
309 \return \c true on success and \c false on error
311 bool PyInterp_Interp::initRun()
317 * Initialize context dictionaries. GIL is held already.
318 * The code executed in an embedded interpreter is expected to be run at the module
319 * level, in which case local and global context have to be the same dictionary.
320 * See: http://stackoverflow.com/questions/12265756/c-python-running-python-code-within-a-context
321 * for an explanation.
323 bool PyInterp_Interp::initContext()
325 PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context)
330 _global_context = PyModule_GetDict(m); // get interpreter global variable context
331 Py_INCREF(_global_context);
332 _local_context = _global_context;
338 * Destroy context dictionaries. GIL is held already.
340 void PyInterp_Interp::closeContext()
342 Py_XDECREF(_global_context);
343 // both _global_context and _local_context may point to the same Python object
344 if ( _global_context != _local_context)
345 Py_XDECREF(_local_context);
349 \brief Compile Python command and evaluate it in the
350 python dictionary contexts if possible. This is not thread-safe.
351 This is the caller's responsability to make this thread-safe.
353 \param command Python command string
354 \return -1 on fatal error, 1 if command is incomplete and 0
355 if command is executed successfully
357 static int run_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
359 PyObject *m = PyImport_AddModule("codeop");
361 // Fatal error. No way to go on.
366 PyObjWrapper v(PyObject_CallMethod(m,(char*)"compile_command",(char*)"s",command));
368 // Error encountered. It should be SyntaxError,
369 //so we don't write out traceback
370 PyObjWrapper exception, value, tb;
371 PyErr_Fetch(&exception, &value, &tb);
372 PyErr_NormalizeException(&exception, &value, &tb);
373 PyErr_Display(exception, value, NULL);
376 else if (v == Py_None) {
377 // Incomplete text we return 1 : we need a complete text to execute
381 PyObjWrapper r(PyEval_EvalCode((PyObject *)(void *)v,global_ctxt, local_ctxt));
383 // Execution error. We return -1
387 // The command has been successfully executed. Return 0
392 void replaceAll(std::string& str, const std::string& from, const std::string& to) {
395 size_t start_pos = 0;
396 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
397 str.replace(start_pos, from.length(), to);
398 start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
402 std::vector<std::string>
403 __split(const std::string& str, char delimiter)
405 std::vector<std::string> internal;
406 std::stringstream ss(str); // Turn the string into a stream.
409 while (getline(ss, tok, delimiter)) {
410 internal.push_back(tok);
417 __join(const std::vector<std::string>& v, int begin=0, int end=-1)
421 std::stringstream ss;
422 for (size_t i = begin; i < end; ++i) {
430 std::vector<std::string>
431 __getArgsList(std::string argsString)
433 // Special process if some items of 'args:' list are themselves lists
434 // Note that an item can be a list, but not a list of lists...
435 // So we can have something like this:
436 // myscript.py args:[\'file1\',\'file2\'],\'val1\',\"done\",[1,2,3],[True,False],\"ok\",kwarg1=\'kwarg1\',kwarg2=\'kwarg2\',\'fin\'
437 // 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'
438 // We have to split argsString to obtain a 9 string elements list
439 std::vector<std::string> x = __split(argsString, ',');
440 bool containsList = (argsString.find('[') != std::string::npos);
442 std::vector<int> listBeginIndices, listEndIndices;
443 for (int pos = 0; pos < x.size(); ++pos) {
444 if (x[pos][0] == '[')
445 listBeginIndices.push_back(pos);
446 else if (x[pos][x[pos].size()-1] == ']')
447 listEndIndices.push_back(pos);
449 std::vector<std::string> extractedArgs;
451 for (int pos = 0; pos < listBeginIndices.size(); ++pos) {
452 int lbeg = listBeginIndices[pos];
453 int lend = listEndIndices[pos];
455 for (int k = start; k < lbeg; ++k)
456 extractedArgs.push_back(x[k]);
457 extractedArgs.push_back(__join(x, lbeg, lend+1));
460 if (start < x.size())
461 for (int k = start; k < x.size(); ++k)
462 extractedArgs.push_back(x[k]);
463 return extractedArgs;
471 \brief Compile Python command and evaluate it in the
472 python dictionary context if possible. Command might correspond to
473 the execution of a script with optional arguments.
474 In this case, command is:
475 execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
477 \param command Python command string
478 \param context Python context (dictionary)
479 \return -1 on fatal error, 1 if command is incomplete and 0
480 if command is executed successfully
482 static int compile_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt)
484 // First guess if command is execution of a script with args, or a simple Python command
485 std::string singleCommand = command;
486 std::string commandArgs = "";
488 QRegExp rx("execfile\\s*\\(.*(args:.*)\"\\s*\\)");
489 if (rx.indexIn(command) != -1) {
490 commandArgs = rx.cap(1).remove(0,5).toStdString(); // arguments of command
491 singleCommand = rx.cap().remove(rx.cap(1)).remove(" ").toStdString(); // command for execution without arguments
494 if (commandArgs.empty()) {
495 // process command: expression
496 // process command: execfile(r"/absolute/path/to/script.py") (no args)
497 return run_command(singleCommand.c_str(), global_ctxt, local_ctxt);
500 // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
501 std::string script = singleCommand.substr(11); // remove leading execfile(r"
502 script = script.substr(0, script.length()-2); // remove trailing ")
503 std::vector<std::string> argList = __getArgsList(commandArgs);
505 std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
506 std::string preCommandEnd = "];";
507 std::string completeCommand = preCommandBegin+"\""+script+"\",";
508 for (std::vector<std::string>::iterator itr = argList.begin(); itr != argList.end(); ++itr) {
509 if (itr != argList.begin())
510 completeCommand += ",";
511 completeCommand = completeCommand + "\"" + *itr + "\"";
513 completeCommand = completeCommand+preCommandEnd+singleCommand+";sys.argv=save_argv";
514 return run_command(completeCommand.c_str(), global_ctxt, local_ctxt);
519 \brief Run Python command - the command has to fit on a single line (no \n!).
520 Use ';' if you need multiple statements evaluated at once.
521 \param command Python command
522 \return command status
524 int PyInterp_Interp::run(const char *command)
527 int ret = simpleRun(command);
533 * Called before a command is run (when calling run() method). Not thread-safe. Caller's responsability
534 * to acquire GIL if needed.
536 int PyInterp_Interp::beforeRun()
542 * Called after a command is run (when calling run() method). Not thread-safe. Caller's responsability
543 * to acquire GIL if needed.
545 int PyInterp_Interp::afterRun()
551 \brief Run Python command (used internally). Not thread-safe. GIL acquisition is caller's responsability.
552 \param command Python command
553 \param addToHistory if \c true (default), the command is added to the commands history
554 \return command status
556 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
558 if( addToHistory && strcmp(command,"") != 0 ) {
559 _history.push_back(command);
560 _ith = _history.end();
563 // Current stdout and stderr are saved
564 PyObject * oldOut = PySys_GetObject((char*)"stdout");
565 PyObject * oldErr = PySys_GetObject((char*)"stderr");
566 // Keep them alive (PySys_GetObject returned a *borrowed* ref!)
570 // Redirect outputs to SALOME Python console before treatment
571 PySys_SetObject((char*)"stderr",_verr);
572 PySys_SetObject((char*)"stdout",_vout);
574 int ier = compile_command(command, _global_context, _local_context);
576 // Outputs are redirected to what they were before
577 PySys_SetObject((char*)"stdout",oldOut);
578 PySys_SetObject((char*)"stderr",oldErr);
584 \brief Get previous command in the commands history.
585 \return previous command
587 const char * PyInterp_Interp::getPrevious()
589 if(_ith != _history.begin()){
591 return (*_ith).c_str();
594 return BEGIN_HISTORY_PY;
598 \brief Get next command in the commands history.
601 const char * PyInterp_Interp::getNext()
603 if(_ith != _history.end()){
606 if (_ith == _history.end())
607 return TOP_HISTORY_PY;
609 return (*_ith).c_str();
613 \brief Set Python standard output device hook.
614 \param cb callback function
615 \param data callback function parameters
617 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
619 ((PyStdOut*)_vout)->_cb=cb;
620 ((PyStdOut*)_vout)->_data=data;
624 \brief Set Python standard error device hook.
625 \param cb callback function
626 \param data callback function parameters
628 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
630 ((PyStdOut*)_verr)->_cb=cb;
631 ((PyStdOut*)_verr)->_data=data;
635 \bried Check if the interpreter is initialized
638 bool PyInterp_Interp::initialized() const