Salome HOME
updated copyright message
[modules/gui.git] / src / SalomeApp / SalomeApp_PyInterp.cxx
old mode 100755 (executable)
new mode 100644 (file)
index a6549f6..9c73a22
-//  SALOME SALOMEGUI : implementation of desktop and GUI kernel
+// Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
 //
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 //  File   : SalomeApp_PyInterp.cxx
 //  Author : Nicolas REJNERI
-//  Module : SALOME
-//  $Header$
 
 #include "SalomeApp_PyInterp.h"
-
-#include <utilities.h>
-#include <Container_init_python.hxx>
-
-#include <string>
-#include <vector>
-
-#include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)!
-
-#include <cStringIO.h>
+#include "SUIT_ResourceMgr.h"
 
 /*!
- * constructor : multi Python interpreter, one per SALOME study.
- * calls initialize method defined in base class, which calls virtual methods
- * initstate & initcontext redefined here.
- */
-SalomeApp_PyInterp::SalomeApp_PyInterp(): PythonConsole_PyInterp()
+  \brief Constructor
+*/
+SalomeApp_PyInterp::SalomeApp_PyInterp( SUIT_ResourceMgr* resMgr )
+  : myFirstRun( true ), myFirstInitStudy( false ), myResourceMgr( resMgr )
 {
 }
 
 /*!
* Destructor.
- */
 \brief Destructor.
+*/
 SalomeApp_PyInterp::~SalomeApp_PyInterp()
 {
 }
  
-/*!\class SalomeApp_PyInterp
- * EDF-CCAR
- * Wasashen SALOME uses multi Python interpreter feature,
- * Every study has its own interpreter and thread state (_tstate = Py_NewInterpreter())
- * This is fine because every study has its own modules (sys.modules) stdout and stderr
- * BUT some Python modules must be imported only once. In multi interpreter context Python
- * modules (*.py) are imported several times.
- * The pyqt module must be imported only once because it registers classes in a C module.
- * It's quite the same with omniorb modules (internals and generated with omniidl)
- * This problem is handled with "shared modules" defined in salome_shared_modules.py
- * These "shared modules" are imported only once and only copied in all the other interpreters
- * BUT it's not the only problem. Every interpreter has its own __builtin__ module. That's fine
- * but if we have copied some modules and imported others problems may arise with operations that
- * are not allowed in restricted execution environment. So we must impose that all interpreters
- * have identical __builtin__ module.
- * That's all, for the moment ...
+/*!
+ * Initialize context dictionaries. GIL is held already.
+ * The code executed in an embedded interpreter is expected to be run at the module
+ * level, in which case local and global context have to be the same dictionary.
+ * See: http://stackoverflow.com/questions/12265756/c-python-running-python-code-within-a-context
+ * for an explanation.
  */
-
-
 bool SalomeApp_PyInterp::initContext()
 {
-  /*!
-   * The GIL is assumed to be held
-   * It is the caller responsability caller to acquire the GIL
-   * It will still be held on initContext output
-   */
-  if ( !PythonConsole_PyInterp::initContext() )
-    return false;
-
-  // Debut modif CCAR
-  // Import special module to change the import mechanism
-  PyObjWrapper m1( PyImport_ImportModule( "import_hook" ) );
-  if ( !m1 )
-  {
-    MESSAGE( "initContext: problem with import_hook import" );
-    PyErr_Print();
-    PyErr_Clear();
-    ASSERT( 0 );
-    return false;
+  bool ok = PyConsole_Interp::initContext();
+  if ( ok ) {
+    int ret = PyRun_SimpleString( "import salome_iapp; salome_iapp.IN_SALOME_GUI = True" );
+    ok = ok && (ret == 0);
   }
+  return ok;
+}
 
-  // Call init_shared_modules to initialize the shared import mechanism for modules 
-  //that must not be imported twice
-  PyObjWrapper m2( PyObject_CallMethod( m1, "init_shared_modules", "O", KERNEL_PYTHON::salome_shared_modules_module ) );
-  if ( !m2 )
-  {
-         MESSAGE( "initContext: problem with init_shared_modules call" );
-         PyErr_Print();
-         PyErr_Clear();
-         ASSERT( 0 );
-    return false;
+/*!
+  \brief Called before each Python command running.
+*/
+int SalomeApp_PyInterp::beforeRun()
+{
+  if ( myFirstRun ) {
+    myFirstRun = false;
+    QStringList parameters = myResourceMgr->parameters( "pythonpath" );
+    foreach ( QString parameter, parameters ) {
+      QStringList paths = myResourceMgr->stringValue( "pythonpath", parameter ).split( ";;" );
+      foreach( QString path, paths )
+        simpleRun( QString( "import sys; sys.path.append('%1')" ).arg( path ).toUtf8().constData(), false );
+    }
+    int ret = simpleRun( "from Help import *", false );
+    if ( ret )
+      return ret;
   }
-
-  return true;
+  if ( myFirstInitStudy ) {
+    myFirstInitStudy = false;
+    int ret = simpleRun( "import salome", false );
+    if ( ret )
+      return ret;
+    ret = simpleRun( "salome.salome_init(embedded=True)", false );
+    if ( ret )
+      return ret;
+  }
+  return PyConsole_Interp::beforeRun();
 }
 
-void SalomeApp_PyInterp::init_python()
+/*!
+  \brief Called when study is initialized
+ */
+void SalomeApp_PyInterp::initStudy()
 {
-  /*
-   * Initialize the main state (_gtstate) if not already done
-   * The lock is released on init_python output
-   * It is the caller responsability to acquire it if needed
-   */
-  MESSAGE("PyInterp_base::init_python");
-  ASSERT(KERNEL_PYTHON::_gtstate); // initialisation in main
-  SCRUTE(KERNEL_PYTHON::_gtstate);
-//  if(!_gtstate){
-//  PyReleaseLock aReleaseLock;
-//  Py_Initialize(); // Initialize the interpreter
-//  PyEval_InitThreads(); // Initialize and acquire the global interpreter lock
-//  PySys_SetArgv(_argc,_argv); // initialize sys.argv
-//    _gtstate = PyThreadState_Get();
-//  }
+  myFirstInitStudy = true;
 }
 
+/*!
+  \brief Called when study is closed
+*/
+void SalomeApp_PyInterp::closeContext()
+{
+  myFirstInitStudy = false;
+  simpleRun( "import salome", false );
+  simpleRun( "salome.salome_close()", false );
+}