1 // Copyright (C) 2007-2013 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.
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
23 // File : PyInterp_Interp.cxx
24 // Author : Christian CAREMOLI, Paul RASCLE, EDF
27 #include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
30 #include <cStringIO.h>
31 #include <structmember.h>
39 #define TOP_HISTORY_PY "--- top of history ---"
40 #define BEGIN_HISTORY_PY "--- begin of history ---"
42 // a map to store python thread states that have been created for a given system thread (key=thread id,value=thread state)
43 std::map<long,PyThreadState*> currentThreadMap;
47 \brief Python GIL wrapper.
51 \brief Constructor. Automatically acquires GIL.
52 \param theThreadState python thread state
54 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState):
55 myThreadState(theThreadState),
58 if (myThreadState->interp == PyInterp_Interp::_interp)
59 _savestate = PyGILState_Ensure();
61 PyEval_AcquireThread(myThreadState);
65 \brief Destructor. Automatically releases GIL.
67 PyLockWrapper::~PyLockWrapper()
69 if (myThreadState->interp == PyInterp_Interp::_interp)
70 PyGILState_Release(_savestate);
72 PyEval_ReleaseThread(myThreadState);
76 \brief Get Python GIL wrapper.
77 \return GIL lock wrapper (GIL is automatically acquired here)
79 PyLockWrapper PyInterp_Interp::GetLockWrapper()
81 if (_tstate->interp == PyInterp_Interp::_interp)
84 // If we are here, we have a secondary python interpreter. Try to get a thread state synchronized with the system thread
85 long currentThreadid=PyThread_get_thread_ident(); // the system thread id
86 PyThreadState* theThreadState;
87 if(currentThreadMap.count(currentThreadid) != 0)
89 //a thread state exists for this thread id
90 PyThreadState* oldThreadState=currentThreadMap[currentThreadid];
91 if(_tstate->interp ==oldThreadState->interp)
93 //The old thread state has the same python interpreter as this one : reuse the threadstate
94 theThreadState=oldThreadState;
98 //The old thread state has not the same python interpreter as this one : delete the old threadstate and create a new one
100 PyThreadState_Clear(oldThreadState);
101 PyThreadState_Delete(oldThreadState);
102 PyEval_ReleaseLock();
103 theThreadState=PyThreadState_New(_tstate->interp);
104 currentThreadMap[currentThreadid]=theThreadState;
109 // no old thread state for this thread id : create a new one
110 theThreadState=PyThreadState_New(_tstate->interp);
111 currentThreadMap[currentThreadid]=theThreadState;
113 return theThreadState;
117 The following functions are used to hook the Python
122 PyStdOut_dealloc(PyStdOut *self)
128 PyStdOut_write(PyStdOut *self, PyObject *args)
132 if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
134 if(self->_cb==NULL) {
141 self->_cb(self->_data,c);
148 PyStdOut_flush(PyStdOut *self)
154 static PyMethodDef PyStdOut_methods[] = {
155 {"write", (PyCFunction)PyStdOut_write, METH_VARARGS, PyDoc_STR("write(string) -> None")},
156 {"flush", (PyCFunction)PyStdOut_flush, METH_NOARGS, PyDoc_STR("flush() -> None")},
157 {NULL, NULL} /* sentinel */
160 static PyMemberDef PyStdOut_memberlist[] = {
161 {(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
162 (char*)"flag indicating that a space needs to be printed; used by print"},
163 {NULL} /* Sentinel */
166 static PyTypeObject PyStdOut_Type = {
167 /* The ob_type field must be initialized in the module init function
168 * to be portable to Windows without using C++. */
169 PyObject_HEAD_INIT(NULL)
172 sizeof(PyStdOut), /*tp_basicsize*/
175 (destructor)PyStdOut_dealloc, /*tp_dealloc*/
182 0, /*tp_as_sequence*/
187 PyObject_GenericGetAttr, /*tp_getattro*/
188 /* softspace is writable: we must supply tp_setattro */
189 PyObject_GenericSetAttr, /* tp_setattro */
191 Py_TPFLAGS_DEFAULT, /*tp_flags*/
195 0, /*tp_richcompare*/
196 0, /*tp_weaklistoffset*/
199 PyStdOut_methods, /*tp_methods*/
200 PyStdOut_memberlist, /*tp_members*/
214 #define PyStdOut_Check(v) ((v)->ob_type == &PyStdOut_Type)
216 static PyStdOut* newPyStdOut( bool iscerr )
219 self = PyObject_New(PyStdOut, &PyStdOut_Type);
224 self->_iscerr = iscerr;
229 \class PyInterp_Interp
230 \brief Generic embedded Python interpreter.
233 int PyInterp_Interp::_argc = 1;
234 char* PyInterp_Interp::_argv[] = {(char*)""};
235 PyObject* PyInterp_Interp::builtinmodule = NULL;
236 PyThreadState* PyInterp_Interp::_gtstate = NULL;
237 PyInterpreterState* PyInterp_Interp::_interp = NULL;
240 \brief Basic constructor.
242 After construction the interpreter instance successor classes
243 must call virtual method initalize().
245 PyInterp_Interp::PyInterp_Interp():
246 _tstate(0), _vout(0), _verr(0), _g(0)
253 PyInterp_Interp::~PyInterp_Interp()
258 \brief Initialize embedded interpreter.
260 This method shoud be called after construction of the interpreter.
261 The method initialize() calls virtuals methods
262 - initPython() to initialize global Python interpreter
263 - initState() to initialize embedded interpreter state
264 - initContext() to initialize interpreter internal context
265 - initRun() to prepare interpreter for running commands
266 which should be implemented in the successor classes, according to the
267 embedded Python interpreter policy (mono or multi interpreter, etc).
269 void PyInterp_Interp::initialize()
271 _history.clear(); // start a new list of user's commands
272 _ith = _history.begin();
275 // Here the global lock is released
279 PyEval_AcquireThread(_tstate);
283 // used to interpret & compile commands
284 PyObjWrapper m(PyImport_ImportModule("codeop"));
287 PyEval_ReleaseThread(_tstate);
291 // Create python objects to capture stdout and stderr
292 _vout=(PyObject*)newPyStdOut( false ); // stdout
293 _verr=(PyObject*)newPyStdOut( true ); // stderr
295 // All the initRun outputs are redirected to the standard output (console)
297 PyEval_ReleaseThread(_tstate);
301 \brief Initialize Python interpreter.
303 In case if Python is not initialized, it sets program name, initializes the interpreter, sets program arguments,
305 Otherwise, it just obtains the global interpreter and thread states. This is important for light SALOME configuration,
306 as in full SALOME this is done at SalomeApp level.
307 \sa SalomeApp_PyInterp class
309 void PyInterp_Interp::initPython()
311 if (!Py_IsInitialized()){
312 // Python is not initialized
313 Py_SetProgramName(_argv[0]);
314 Py_Initialize(); // Initialize the interpreter
315 PySys_SetArgv(_argc, _argv);
316 PyEval_InitThreads(); // Create (and acquire) the interpreter lock
319 if ( _interp == NULL )
320 _interp = PyThreadState_Get()->interp;
321 if (PyType_Ready(&PyStdOut_Type) < 0) {
324 if ( _gtstate == NULL )
325 _gtstate = PyEval_SaveThread(); // Release global thread state
329 \brief Get embedded Python interpreter banner.
330 \return banner string
332 std::string PyInterp_Interp::getbanner()
334 // Should we take the lock ?
335 // PyEval_RestoreThread(_tstate);
336 std::string aBanner("Python ");
337 aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
338 aBanner = aBanner + "\ntype help to get general information on environment\n";
339 //PyEval_SaveThread();
344 \brief Initialize run command.
346 This method is used to prepare interpreter for running
349 \return \c true on success and \c false on error
351 bool PyInterp_Interp::initRun()
354 // probably all below code isn't required
357 PySys_SetObject("stderr",_verr);
358 PySys_SetObject("stdout",_vout);
360 //PyObject *m = PyImport_GetModuleDict();
362 PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
363 PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
369 \brief Compile Python command and evaluate it in the
370 python dictionary context if possible.
372 \param command Python command string
373 \param context Python context (dictionary)
374 \return -1 on fatal error, 1 if command is incomplete and 0
375 if command is executed successfully
377 static int run_command(const char *command, PyObject *context)
379 PyObject *m = PyImport_AddModule("codeop");
380 if(!m) { // Fatal error. No way to go on.
384 PyObjWrapper v(PyObject_CallMethod(m,(char*)"compile_command",(char*)"s",command));
386 // Error encountered. It should be SyntaxError,
387 //so we don't write out traceback
388 PyObjWrapper exception, value, tb;
389 PyErr_Fetch(&exception, &value, &tb);
390 PyErr_NormalizeException(&exception, &value, &tb);
391 PyErr_Display(exception, value, NULL);
394 else if (v == Py_None) {
395 // Incomplete text we return 1 : we need a complete text to execute
399 // Complete and correct text. We evaluate it.
400 //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
401 // PyObjWrapper r(PyEval_EvalCode(v,context,context));
403 PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
406 // Execution error. We return -1
410 // The command has been successfully executed. Return 0
415 void replaceAll(std::string& str, const std::string& from, const std::string& to) {
418 size_t start_pos = 0;
419 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
420 str.replace(start_pos, from.length(), to);
421 start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
425 \brief Compile Python command and evaluate it in the
426 python dictionary context if possible. Command might correspond to
427 the execution of a script with optional arguments.
428 In this case, command is:
429 execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
431 \param command Python command string
432 \param context Python context (dictionary)
433 \return -1 on fatal error, 1 if command is incomplete and 0
434 if command is executed successfully
436 static int compile_command(const char *command,PyObject *context)
438 // First guess if command is execution of a script with args, or a simple Python command
439 std::string singleCommand = command;
440 std::string commandArgs = "";
442 std::size_t pos = std::string(command).find("args:");
443 if (pos != std::string::npos) {
444 commandArgs = singleCommand.substr(pos+5);
445 commandArgs = commandArgs.substr(0, commandArgs.length()-3);
446 singleCommand = singleCommand.substr(0, pos-1)+"\")";
449 if (commandArgs.empty()) {
450 // process command: expression
451 // process command: execfile(r"/absolute/path/to/script.py") (no args)
452 return run_command(singleCommand.c_str(), context);
455 // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
456 std::string script = singleCommand.substr(11); // remove leading execfile(r"
457 script = script.substr(0, script.length()-2); // remove trailing ")
459 std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
460 std::string preCommandEnd = "];";
461 replaceAll(commandArgs, ",", "\",\"");
462 commandArgs = "\""+commandArgs+"\"";
463 std::string completeCommand = preCommandBegin+"\""+script+"\","+commandArgs+preCommandEnd+singleCommand+";sys.argv=save_argv";
464 return run_command(completeCommand.c_str(), context);
469 \brief Run Python command.
470 \param command Python command
471 \return command status
473 int PyInterp_Interp::run(const char *command)
476 return simpleRun(command);
480 \brief Run Python command (used internally).
481 \param command Python command
482 \param addToHistory if \c true (default), the command is added to the commands history
483 \return command status
485 int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
487 if( addToHistory && strcmp(command,"") != 0 ) {
488 _history.push_back(command);
489 _ith = _history.end();
492 // We come from C++ to enter Python world
493 // We need to acquire the Python global lock
494 //PyLockWrapper aLock(_tstate); // san - lock is centralized now
496 // Reset redirected outputs before treatment
497 PySys_SetObject((char*)"stderr",_verr);
498 PySys_SetObject((char*)"stdout",_vout);
500 int ier = compile_command(command,_g);
502 // Outputs are redirected on standards outputs (console)
503 PySys_SetObject((char*)"stdout",PySys_GetObject((char*)"__stdout__"));
504 PySys_SetObject((char*)"stderr",PySys_GetObject((char*)"__stderr__"));
510 \brief Get previous command in the commands history.
511 \return previous command
513 const char * PyInterp_Interp::getPrevious()
515 if(_ith != _history.begin()){
517 return (*_ith).c_str();
520 return BEGIN_HISTORY_PY;
524 \brief Get next command in the commands history.
527 const char * PyInterp_Interp::getNext()
529 if(_ith != _history.end()){
532 if (_ith == _history.end())
533 return TOP_HISTORY_PY;
535 return (*_ith).c_str();
539 \brief Set Python standard output device hook.
540 \param cb callback function
541 \param data callback function parameters
543 void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
545 ((PyStdOut*)_vout)->_cb=cb;
546 ((PyStdOut*)_vout)->_data=data;
550 \brief Set Python standard error device hook.
551 \param cb callback function
552 \param data callback function parameters
554 void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
556 ((PyStdOut*)_verr)->_cb=cb;
557 ((PyStdOut*)_verr)->_data=data;