Salome HOME
CCAR (EDF-RD):
authorcaremoli <caremoli>
Thu, 5 Jun 2003 17:54:20 +0000 (17:54 +0000)
committercaremoli <caremoli>
Thu, 5 Jun 2003 17:54:20 +0000 (17:54 +0000)
- First modification : runSalome.py can be imported or exec'ed. I'm not sure
      it's really possible to use startSalome or startGUI from another Python module
      but it's a first step.
- Second modification : new import mechanism for shared python modules (CORBA, qt,..)
      This mechanism implemented in the new module import_hook replaces the
   standard import mechanism. New module kernel_shared_modules helps to define those modules
   that must be imported only once. Other modules can have their own <module>_shared_modules
- 3rd : some minor improvments in Python interpretor (more error trace) and link to new import
      mechanism.
- 4th : modification of check_sip and check_pyqt to recognize different versions 3.3, ..., 3.5

src/SALOME_SWIG/import_hook.py [new file with mode: 0644]
src/SALOME_SWIG/kernel_shared_modules.py [new file with mode: 0644]

diff --git a/src/SALOME_SWIG/import_hook.py b/src/SALOME_SWIG/import_hook.py
new file mode 100644 (file)
index 0000000..b67812f
--- /dev/null
@@ -0,0 +1,106 @@
+"""
+This module replaces the standard import mechanism with one
+that filters some imports that can't be done more than once.
+
+This is related to the multi study feature that is implemented
+by using the Python multi interpreter feature.
+Some modules register objects or classes by calling modules
+implemented in C. These operations can't be done multiple times.
+So it's very important to control these imports.
+
+Examples:
+  - PyQt : import qt calls a C module to register classes
+  - OmniORB : import *_idl calls a C module to register CORBA interfaces
+
+Usage:
+  - First import the module : import import_hook. This module will
+    replace the original importer mechanism
+
+  - Next register the module names or pattern names to filter out::
+     import_hook.register_name("a")
+     import_hook.register_pattern(pattern)
+
+    where pattern is a function with one parameter, the module name
+    to be imported, that returns true or false depending if this module is
+    to be filtered or not.
+
+  - Then it's done
+
+IMPORTANT : Every subinterpretor has its own import_hook module. import_hook is not shared among subinterpretors.
+The mechanism only works if shared_imported and pattern are shared between all subinterpretors.
+This is done by calling init_shared_modules().
+  
+"""
+import sys, imp, __builtin__
+
+# Keep in shared_imported a copy of dictionnary modules
+# that need to be imported only once in multi-study context
+shared_imported={}
+
+# patterns contains functions that returns 1 or 0 depending if 
+# the module name (argument) must be filtered out or not
+# These functions are added by calling register_pattern
+patterns=[]
+
+original_import=__builtin__.__import__
+
+def register_name(name):
+    if shared_imported.has_key(name):return
+    shared_imported[name]=None
+
+def register_pattern(pattern):
+    patterns.append(pattern)
+
+def is_shared(name):
+    if shared_imported.has_key(name):return 1
+    for pattern in patterns:
+        if pattern(name) : return 1
+    return 0
+
+def get_shared_imported(name):
+    return shared_imported.get(name)
+def set_shared_imported(name,module):
+    shared_imported[name]=module
+    #print "Module %s shared registered" % name
+
+def get_shared_imported_with_copy(name):
+    module_dict= shared_imported.get(name)
+    m=imp.new_module(name)
+    m.__dict__.update(module_dict)
+    return m
+def set_shared_imported_with_copy(name,module):
+    shared_imported[name]=module.__dict__.copy()
+    #print "Module %s shared registered" % name
+
+def import_hook(name, globals=None, locals=None, fromlist=None):
+    module=get_shared_imported(name)
+    if module:
+       sys.modules[name]=module
+       return module
+
+    module= original_import(name, globals, locals, fromlist)
+
+    if is_shared(name):
+       set_shared_imported(name,module)
+    return module
+
+original_reload=__builtin__.reload
+
+def reload_hook(module):
+    if is_shared(module.__name__):
+       return module
+    return original_reload(module)
+
+__builtin__.__import__=import_hook
+# Reload is not replaced 
+#__builtin__.reload=reload_hook
+
+def init_shared_modules(shared_module):
+    global shared_imported, patterns
+    shared_imported=shared_module.shared_imported
+    patterns=       shared_module.patterns
+    shared_imported["salome_shared_modules"]=shared_module
+    import salome_shared_modules
+    for m in salome_shared_modules.list_modules:
+        m.init_shared_modules()
+
diff --git a/src/SALOME_SWIG/kernel_shared_modules.py b/src/SALOME_SWIG/kernel_shared_modules.py
new file mode 100644 (file)
index 0000000..dc4811a
--- /dev/null
@@ -0,0 +1,80 @@
+"""
+
+"""
+import glob,os,sys
+
+import import_hook
+from import_hook import register_name
+from import_hook import register_pattern
+
+register_name("qt")
+register_pattern(lambda(x):x.endswith("_idl"))
+
+register_name("omniORB")
+register_name("CosNaming")
+
+register_name("Engines")
+register_name("SALOME")
+register_name("SALOMEDS")
+register_name("SALOME_ModuleCatalog")
+
+# BE CAREFUL
+# Engines, SALOME, SALOMEDS must be imported in that order because :
+# Engines imports SALOME_Component_idl
+# SALOME imports SALOME_Session_idl and SALOME_Exception_idl which imports SALOME_Component_idl
+# and SALOMEDS imports SALOMEDS_idl and SALOMEDS_Attributes_idl which imports SALOME_Exception_idl
+# If SALOME is imported before Engines, that module would not be completely imported
+import Engines
+import SALOME
+import SALOMEDS
+
+import SALOME_ModuleCatalog
+from SALOME_utilities import MESSAGE
+#
+# We search all Python CORBA (omniorb) modules.
+# A Python CORBA module has 2 associated Python packages 
+# These packages are named : <module_name> and <module_name>__POA
+#
+# That module is normally installed in shared_modules
+# So we should find CORBA shared modules in ..
+repertoire=os.path.join(os.path.dirname(__file__),'..')
+path=[repertoire,]
+#
+for rep in path:
+   # Add rep directory in the Python path to be able to import modules 
+   listdir=glob.glob(os.path.join(rep,"*__POA"))
+   for elem in listdir:
+      if os.path.isdir(elem):
+         # Found a directory (Python package) named *__POA 
+         module__POA=os.path.basename(elem)
+         module=module__POA[:-5]
+         MESSAGE( "Import CORBA module: " + module + ".\n Directory: " + os.path.abspath(elem)[:-5] )
+         register_name(module)
+
+   # Now we import modules found in shared_modules directory
+   r=os.path.join(rep,"shared_modules")
+   if os.path.isdir(r):
+      listfich=glob.glob(os.path.join(r,"*.py"))
+      MESSAGE( str(listfich) )
+      for m in listfich:
+         module=os.path.basename(m)[:-3]
+         MESSAGE( "Import module: " + module + ".\n Location: " + os.path.abspath(m) )
+         register_name(module)
+
+
+def init_shared_modules():
+   """
+      This function initializes shared modules that need to be
+   """
+   # EDF-CCAR:
+   # Problem with omniORB : omniORB creates a C Python module named  _omnipy
+   # this module has sub-modules : omni_func, ...
+   # _omnipy is quite a package but import with Python sub-interpreters does not seem to work
+   # To make it work we need to add those sub-modules in sys.modules
+   import sys
+   import _omnipy
+   sys.modules["_omnipy.omni_func"]=_omnipy.omni_func
+   sys.modules["_omnipy.poa_func"]=_omnipy.poa_func
+   sys.modules["_omnipy.poamanager_func"]=_omnipy.poamanager_func
+   sys.modules["_omnipy.orb_func"]=_omnipy.orb_func
+