1 # Copyright (C) 2005 OPEN CASCADE, CEA, EDF R&D, LEG
2 # PRINCIPIA R&D, EADS CCR, Lip6, BV, CEDRAT
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License.
8 # This library is distributed in the hope that it will be useful
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 This module replaces the standard import mechanism with one
21 that filters some imports that can't be done more than once.
23 This is related to the multi study feature that is implemented
24 by using the Python multi interpreter feature.
25 Some modules register objects or classes by calling modules
26 implemented in C. These operations can't be done multiple times.
27 So it's very important to control these imports.
30 - PyQt : import qt calls a C module to register classes
31 - OmniORB : import *_idl calls a C module to register CORBA interfaces
34 - First import the module : import import_hook. This module will
35 replace the original importer mechanism
37 - Next register the module names or pattern names to filter out::
38 import_hook.register_name("a")
39 import_hook.register_pattern(pattern)
41 where pattern is a function with one parameter, the module name
42 to be imported, that returns true or false depending if this module is
43 to be filtered or not.
47 IMPORTANT : Every subinterpretor has its own import_hook module. import_hook is not shared among subinterpretors.
48 The mechanism only works if shared_imported and pattern are shared between all subinterpretors.
49 This is done by calling init_shared_modules().
52 import sys, imp, __builtin__
54 # Keep in shared_imported a copy of dictionnary modules
55 # that need to be imported only once in multi-study context
58 # patterns contains functions that returns 1 or 0 depending if
59 # the module name (argument) must be filtered out or not
60 # These functions are added by calling register_pattern
63 original_import=__builtin__.__import__
65 def register_name(name):
66 if shared_imported.has_key(name):return
67 shared_imported[name]=None
69 def register_pattern(pattern):
70 patterns.append(pattern)
73 """ Indicate if module name is a shared module
74 among multiple interpreters (return value=1)
76 if shared_imported.has_key(name):return 1
77 for pattern in patterns:
78 if pattern(name) : return 1
81 def get_shared_imported(name,fromlist):
82 """ If the module is registered in shared_imported
83 update the sys.modules dict
84 Let the real import be done by original_import
86 module= shared_imported.get(name)
88 #module name is not shared or not already imported
89 #let original_import do the job
92 # module is already imported and shared. Put it in sys.modules and
93 # let original_import finish the job
94 sys.modules[name]=module
96 def get_real_module(mod,name):
97 """Return effective module on import
98 Standard import returns module A on import A.B
99 To get module A.B use get_real_module with name "A.B"
101 components = name.split('.')
102 for comp in components[1:]:
103 mod = getattr(mod, comp)
106 def set_shared_imported(name,module):
107 """ Register a shared module
108 Name can be a dotted name : package
110 shared_imported[name]=module
111 #print "Module %s shared registered" % name,module
113 def ensure_fromlist(m, fromlist, recursive=0):
114 """ Return the real modules list to be imported
122 except AttributeError:
125 l.extend(ensure_fromlist(m, all, 1))
127 submod=getattr(m,sub)
128 if type(submod) == type(sys):
129 l.append(("%s.%s" % (m.__name__, sub),submod))
132 def import_hook(name, globals=None, locals=None, fromlist=None):
133 """ Import replacement for sharing modules among multiple interpreters
134 Mostly update sys.modules before doing real import
136 #print "import_hook",name,fromlist
137 m=get_shared_imported(name,fromlist)
139 module= original_import(name, globals, locals, fromlist)
142 #when fromlist is specified, module is the real module
143 #fromlist is a list of possibly dotted name
145 for nam,mod in ensure_fromlist(m, fromlist):
147 set_shared_imported(nam,mod)
149 #when fromlist is not specified and name is a dotted name,
150 # module is the root package not the real module
151 #so we need to retrieve it
152 m=get_real_module(module,name)
154 if type(m) == type(sys) and is_shared(m.__name__):
155 set_shared_imported(m.__name__,m)
159 original_reload=__builtin__.reload
161 def reload_hook(module):
162 if is_shared(module.__name__):
164 return original_reload(module)
166 __builtin__.__import__=import_hook
167 # Reload is not replaced
168 #__builtin__.reload=reload_hook
170 def init_shared_modules(shared_module):
171 global shared_imported, patterns
172 shared_imported=shared_module.shared_imported
173 patterns= shared_module.patterns
174 for k,v in shared_imported.items():
175 if v is not None:sys.modules[k]=v
176 shared_imported["salome_shared_modules"]=shared_module
177 import salome_shared_modules
178 for m in salome_shared_modules.list_modules:
179 m.init_shared_modules()