Salome HOME
- Patch for recent Debian distrib:
[modules/kernel.git] / src / KERNEL_PY / import_hook.py
index 42b23daa208cc011400bb14f62f3c64b5feca850..56322e56ebfdacfad8678b0e7ac64071a085bd33 100755 (executable)
@@ -1,21 +1,24 @@
-# Copyright (C) 2005  OPEN CASCADE, CEA, EDF R&D, LEG
-#           PRINCIPIA R&D, EADS CCR, Lip6, BV, CEDRAT
-# 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.salome-platform.org/ or email : webmaster.salome@opencascade.com
-# 
+#  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+#  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.
+#
+#  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
+#
 """
 This module replaces the standard import mechanism with one
 that filters some imports that can't be done more than once.
@@ -70,38 +73,112 @@ def register_pattern(pattern):
     patterns.append(pattern)
 
 def is_shared(name):
+    """ Indicate if module name is a shared module
+        among multiple interpreters (return value=1)
+    """
     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 get_shared_imported(name,fromlist):
+    """ If the module is registered in shared_imported
+        update the sys.modules dict
+        Let the real import be done by original_import
+    """
+    module= shared_imported.get(name)
+    if module is None :
+       #module name is not shared or not already imported
+       #let original_import do the job
+       return None
+
+    # module is already imported and shared. Put it in sys.modules and 
+    # let original_import finish the job
+    sys.modules[name]=module
+
+def get_real_module(mod,name):
+    """Return effective module on import
+       Standard import returns module A on import A.B
+       To get module A.B use get_real_module with name "A.B"
+    """
+    components = name.split('.')
+    for comp in components[1:]:
+        mod = getattr(mod, comp)
+    return mod
 
 def set_shared_imported(name,module):
+    """ Register a shared module
+        Name can be a dotted name : package
+    """
     shared_imported[name]=module
     #print "Module %s shared registered" % name,module
 
-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):
+def import_module(partname, fqname, parent):
+    """ Try to import module fqname
+        It's parent is module parent and has name partname
+    """
+    try:
+       m = sys.modules[fqname]
+    except KeyError:
+       pass
+    else:
+       return m
+
+def ensure_fromlist(m, fromlist, recursive=0):
+    """ Return the real modules list to be imported
+    """
+    l=[]
+    for sub in fromlist:
+        if sub == "*":
+            if not recursive:
+                try:
+                    all = m.__all__
+                except AttributeError:
+                    pass
+                else:
+                    l.extend(ensure_fromlist(m, all, 1))
+        elif hasattr(m,sub):
+            submod=getattr(m,sub)
+            if type(submod) == type(sys):
+               l.append(("%s.%s" % (m.__name__, sub),submod))
+        else:
+            subname="%s.%s" % (m.__name__, sub)
+            submod = import_module(sub, subname, m)
+            if not submod:
+               raise ImportError, "No module named " + subname
+            l.append((subname,submod))
+    return l
+
+def import_hook(name, globals=None, locals=None, fromlist=None, *args):
+    """ Import replacement for sharing modules among multiple interpreters
+        Mostly update sys.modules before doing real import
+    """
     #print "import_hook",name,fromlist
-    module=get_shared_imported(name)
-    if module:
-       sys.modules[name]=module
-       return module
-
-    module= original_import(name, globals, locals, fromlist)
+    m=get_shared_imported(name,fromlist)
+
+    module= original_import(name, globals, locals, fromlist, *args)
+
+    if fromlist:
+       #when fromlist is specified, module is the real module
+       #fromlist is a list of possibly dotted name
+       m=module
+       for nam,mod in ensure_fromlist(m, fromlist):
+           if is_shared(nam):
+              set_shared_imported(nam,mod)
+    else: 
+       #when fromlist is not specified and name is a dotted name,
+       # module is the root package not the real module
+       #so we need to retrieve it
+       # note: some modules like xml.dom do not play the rule
+       # (import xml: no attribute dom, but import xml.dom OK)
+       try:
+           m=get_real_module(module,name)
+       except AttributeError:
+           m=None
+
+    if type(m) == type(sys) and is_shared(m.__name__):
+       set_shared_imported(m.__name__,m)
 
-    if is_shared(name):
-       set_shared_imported(name,module)
     return module
 
 original_reload=__builtin__.reload