Salome HOME
Merge remote-tracking branch 'remotes/origin/master' into SketchSolver
[modules/shaper.git] / src / PyConsole / PyConsole_Interp.cpp
1
2 #include "PyConsole_Interp.h"
3
4 /*!
5   \class PyConsole_Interp
6   \brief Python interpreter to be embedded to the SALOME study's GUI.
7
8   Python interpreter is created one per SALOME study.
9
10   Call initialize method defined in the base class PyInterp_Interp,
11   to intialize interpreter after instance creation.
12
13   The method initialize() calls virtuals methods
14   - initPython()  to initialize global Python interpreter
15   - initState()   to initialize embedded interpreter state
16   - initContext() to initialize interpreter internal context
17   - initRun()     to prepare interpreter for running commands
18
19   /EDF-CCAR/
20   When SALOME uses multi Python interpreter feature, 
21   every study has its own interpreter and thread state (_tstate = Py_NewInterpreter()).
22   This is fine because every study has its own modules (sys.modules) stdout and stderr.
23
24   <b>But</b> some Python modules must be imported only once. In multi interpreter 
25   context Python modules (*.py) are imported several times.
26   For example, the PyQt module must be imported only once because 
27   it registers classes in a C module.
28
29   It's quite the same with omniorb modules (internals and generated with omniidl).
30
31   This problem is handled with "shared modules" defined in salome_shared_modules.py.
32   These "shared modules" are imported only once and only copied in all 
33   the other interpreters.
34
35   <b>But</b> it's not the only problem. Every interpreter has its own 
36   __builtin__ module. That's fine but if we have copied some modules 
37   and imported others problems may arise with operations that are not allowed
38   in restricted execution environment. So we must impose that all interpreters
39   have identical __builtin__ module.
40 */
41
42 /*!
43   \brief Constructor.
44
45   Creates new python interpreter.
46 */
47 PyConsole_Interp::PyConsole_Interp(): PyInterp_Interp()
48 {
49 }
50
51 /*!
52   \brief Destructor.
53
54   Does nothing for the moment.
55 */
56 PyConsole_Interp::~PyConsole_Interp()
57 {
58 }
59  
60 /*!
61   \brief Initialize internal Python interpreter state.
62
63   When calling initState the GIL is not held
64   It must not be held on exit
65
66   \return \c true on success
67 */
68 bool PyConsole_Interp::initState()
69 {
70   PyEval_AcquireLock();
71   _tstate = Py_NewInterpreter(); // create an interpreter and save current state
72   PySys_SetArgv(PyInterp_Interp::_argc,PyInterp_Interp::_argv); // initialize sys.argv
73   
74   if(!builtinmodule) // PAL18041: deepcopy function don't work in Salome
75   {
76     //builtinmodule is static member of PyInterp class
77     //If it is not NULL (initialized to the builtin module of the main interpreter
78     //all the sub interpreters will have the same builtin
79     //_interp is a static member and is the main interpreter
80     //The first time we initialized it to the builtin of main interpreter
81     builtinmodule=PyDict_GetItemString(_interp->modules, "__builtin__");
82   }
83
84   //If builtinmodule has been initialized all the sub interpreters
85   // will have the same __builtin__ module
86   if(builtinmodule){ 
87     PyObject *m = PyImport_GetModuleDict();
88     PyDict_SetItemString(m, "__builtin__", builtinmodule);
89     _tstate->interp->builtins = PyModule_GetDict(builtinmodule);
90     Py_INCREF(_tstate->interp->builtins);
91   }
92   PyEval_ReleaseThread(_tstate);
93   return true;
94 }
95
96 /*!
97   \brief Initialize python interpeter context.
98
99   The GIL is assumed to be held.
100   It is the caller responsability to acquire the GIL.
101   It must still be held on initContext() exit.
102
103   \return \c true on success
104 */
105 bool PyConsole_Interp::initContext()
106 {
107   PyObject *m = PyImport_AddModule("__main__");  // interpreter main module (module context)
108   if(!m){
109     PyErr_Print();
110     return false;
111   }  
112   _g = PyModule_GetDict(m);          // get interpreter dictionnary context
113
114   if(builtinmodule){
115     PyDict_SetItemString(_g, "__builtins__", builtinmodule); // assign singleton __builtin__ module
116   }
117   return true;
118 }