8 """Provides cfgDb, a Singleton that holds the information on the whereabouts
9 of all the accessible, automatically generated, Configurables.
10 This repository of (informations on) Configurables is used by the PropertyProxy
11 class to locate Configurables and feed the JobOptionsSvc. It could also be used
12 to feed the AthenaEmacs module..."""
16 __author__ =
'Sebastien Binet (binet@cern.ch)'
18 __all__ = [
'CfgDb',
'cfgDb',
19 'loadConfigurableDb',
'unloadConfigurableDb',
22 _transtable = str.maketrans(
'<>&*,: ().',
'__rp__s___')
29 cfgDb.msg.info(
"Read module info for %d configurables from %d genConfDb files",
32 if 0 < len( cfgDb.duplicates() ):
33 cfgDb.msg.warning(
"Found %d duplicates among the %d genConfDb files :",
34 len(cfgDb.duplicates()), nFiles )
35 cfgDb.msg.warning(
"--------------------------------------------------" )
36 cfgDb.msg.warning(
" -%s: %s - %s",
37 "<component name>",
"<module>",
"[ <duplicates> ]" )
38 cfgDb.msg.warning(
"--------------------------------------------------" )
40 dups = cfgDb.duplicates()
41 for cfgName
in dups.keys():
42 cfgDb.msg.warning(
" -%s: %s - %s",
44 cfgDb[cfgName][
'module'],
45 str([ d[
'module']
for d
in dups[cfgName]]) )
49 cfgDb.msg.info(
"No duplicates have been found: that's good !" )
55 A singleton class holding informations about automatically generated
57 --> package holding that Configurable
58 --> library holding the components related to that Configurable
59 --> python module holding the Configurable
60 --> a dictionary of duplicates
69 object.__init__( self )
78 self.
_msg = Logging.logging.getLogger(
'ConfigurableDb' )
81 def add( self, configurable, package, module, lib ):
82 """Method to populate the Db.
83 It is called from the auto-generated Xyz_confDb.py files (genconf.cpp)
84 @param configurable: the name of the configurable being added
85 @param package: the name of the package which holds this Configurable
86 @param module: the name of the python module holding the Configurable
87 @param lib: the name of the library holding the component(s) (ie: the
88 C++ Gaudi component which is mapped by the Configurable)
91 cfg = {
'package' : package,
95 if configurable
in self:
97 if cfg[
'lib'] != self[configurable][
'lib']:
98 self.
msg.
verbose(
"dup!! [%s] p=%s m=%s lib=%s",
99 configurable, package, module, lib )
106 self.
msg.
verbose(
"added [%s] p=%s m=%s lib=%s",
107 configurable, package, module, lib )
108 self[configurable] = cfg
116 for i,ll
in enumerate(f):
118 if l.startswith(
'#')
or len(l) <= 0:
123 pkg = line[0].
split(
'.')[0]
126 self.
add(cname, pkg, module, lib)
130 "invalid line format: %s:%d: %r" %
137 """Load all ConfigurableDb files (modules) holding informations about
138 Configurables available in the release
142 from os.path
import join
as path_join
146 cfgDb.msg.debug(
"loading confDb files..." )
148 pathlist = os.getenv(
"LD_LIBRARY_PATH",
"").
split(os.pathsep)
149 for path
in pathlist:
150 if not os.path.isdir(path):
152 cfgDb.msg.verbose(
"walking in [%s]..." % path )
153 confDbFiles = [f
for f
in [path_join(path, f)
for f
in os.listdir(path)
154 if f.endswith(
'.confdb')]
155 if os.path.isfile(f)]
158 mergedConfDbFiles = [f
for f
in confDbFiles
159 if f.endswith(
'_merged.confdb')]
160 if mergedConfDbFiles:
162 confDbFiles = mergedConfDbFiles
164 for confDb
in confDbFiles:
165 cfgDb.msg.debug(
"\t-loading [%s]...", confDb )
167 cfgDb._loadModule( confDb )
168 except Exception
as err:
170 traceback.print_exc()
171 cfgDb.msg.warning(
"Could not load file [%s] !", confDb )
172 cfgDb.msg.warning(
"Reason: %s", err )
174 cfgDb.msg.debug(
"loading confDb files... [DONE]" )
175 nPkgs = len(
set([k[
'package']
for k
in cfgDb.values()]) )
176 cfgDb.msg.debug(
"loaded %i confDb packages", nPkgs )
182 """UNload all ConfigurableDb files (modules) holding informations about
183 Configurables available in the release:
184 - remove imported modules from sys.modules
185 - clear the configurable Db
190 confModules =
set( [ cfgDb.get(k).
get(
'module')
for k
in cfgDb ] +
191 [ cfgDb.get(k).
get(
'package')
for k
in cfgDb ] )
194 for m
in sys.modules.keys():
195 if m
in confModules
or \
196 m.count(
"_merged_confDb") > 0
or \
197 m.count(
".GaudiHandles" ) > 0
or \
198 m.count(
"ConfigurableDb") > 0
or \
199 m.count(
"AthenaPython") > 0:
201 if hasattr(sys.modules[m],
'__dict__'):
202 for i
in sys.modules[m].__dict__.keys():
203 del sys.modules[m].__dict__[i]
209 """Localize and load a Configurable class based on the (C++) class name.
222 confClass = className
225 confClass = str.translate( confClass, _transtable )
228 confClassInfo = cfgDb.get( confClass )
231 confMod = confClassInfo
and confClassInfo.get(
'module' )
233 cfgDb.msg.warning(
"%s: Class %s not in database", requester, className )
238 mod = __import__( confMod, globals(), locals(), confClass, level=0 )
240 cfgDb.msg.warning(
"%s: Module %s not found (needed for configurable %s)",
241 requester, confMod, className )
246 confClass = getattr( mod, confClass )
247 except AttributeError:
248 cfgDb.msg.warning(
"%s: Configurable %s not found in module %s",
249 requester, confClass, confMod )
253 cfgDb.msg.debug(
"%s: Found configurable %s in module %s",
254 requester, confClass, confMod )
271 del _CfgDb, _Singleton
275 if __name__ ==
'__main__':
278 sys.modules[
'AthenaCommon.ConfigurableDb' ] = __main__
279 sys.modules[
'ConfigurableDb' ] = __main__
285 from StoreGate.StoreGateConf
import StoreGateSvc
286 assert( conf
is StoreGateSvc )