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___')
27 cfgDb.msg.info(
"Read module info for %d configurables from %d genConfDb files",
30 if 0 < len( cfgDb.duplicates() ):
31 cfgDb.msg.warning(
"Found %d duplicates among the %d genConfDb files :",
32 len(cfgDb.duplicates()), nFiles )
33 cfgDb.msg.warning(
"--------------------------------------------------" )
34 cfgDb.msg.warning(
" -%s: %s - %s",
35 "<component name>",
"<module>",
"[ <duplicates> ]" )
36 cfgDb.msg.warning(
"--------------------------------------------------" )
38 dups = cfgDb.duplicates()
39 for cfgName
in dups.keys():
40 cfgDb.msg.warning(
" -%s: %s - %s",
42 cfgDb[cfgName][
'module'],
43 str([ d[
'module']
for d
in dups[cfgName]]) )
47 cfgDb.msg.info(
"No duplicates have been found: that's good !" )
53 A singleton class holding informations about automatically generated
55 --> package holding that Configurable
56 --> library holding the components related to that Configurable
57 --> python module holding the Configurable
58 --> a dictionary of duplicates
67 object.__init__( self )
76 self.
_msg = Logging.logging.getLogger(
'ConfigurableDb' )
79 def add( self, configurable, package, module, lib ):
80 """Method to populate the Db.
81 It is called from the auto-generated Xyz_confDb.py files (genconf.cpp)
82 @param configurable: the name of the configurable being added
83 @param package: the name of the package which holds this Configurable
84 @param module: the name of the python module holding the Configurable
85 @param lib: the name of the library holding the component(s) (ie: the
86 C++ Gaudi component which is mapped by the Configurable)
89 cfg = {
'package' : package,
93 if configurable
in self:
95 if cfg[
'lib'] != self[configurable][
'lib']:
96 self.
msg.
verbose(
"dup!! [%s] p=%s m=%s lib=%s",
97 configurable, package, module, lib )
104 self.
msg.
verbose(
"added [%s] p=%s m=%s lib=%s",
105 configurable, package, module, lib )
106 self[configurable] = cfg
114 for i,ll
in enumerate(f):
116 if l.startswith(
'#')
or len(l) <= 0:
121 pkg = line[0].
split(
'.')[0]
124 self.
add(cname, pkg, module, lib)
128 "invalid line format: %s:%d: %r" %
135 """Load all ConfigurableDb files (modules) holding informations about
136 Configurables available in the release
140 from os.path
import join
as path_join
142 cfgDb.msg.debug(
"loading confDb files..." )
144 pathlist = os.getenv(
"LD_LIBRARY_PATH",
"").
split(os.pathsep)
145 for path
in pathlist:
146 if not os.path.isdir(path):
148 cfgDb.msg.verbose(
"walking in [%s]..." % path )
149 confDbFiles = [f
for f
in [path_join(path, f)
for f
in os.listdir(path)
150 if f.endswith(
'.confdb')]
151 if os.path.isfile(f)]
154 mergedConfDbFiles = [f
for f
in confDbFiles
155 if f.endswith(
'_merged.confdb')]
156 if mergedConfDbFiles:
158 confDbFiles = mergedConfDbFiles
160 for confDb
in confDbFiles:
161 cfgDb.msg.debug(
"\t-loading [%s]...", confDb )
163 cfgDb._loadModule( confDb )
164 except Exception
as err:
166 traceback.print_exc()
167 cfgDb.msg.warning(
"Could not load file [%s] !", confDb )
168 cfgDb.msg.warning(
"Reason: %s", err )
170 cfgDb.msg.debug(
"loading confDb files... [DONE]" )
171 nPkgs = len(
set([k[
'package']
for k
in cfgDb.values()]) )
172 cfgDb.msg.debug(
"loaded %i confDb packages", nPkgs )
178 """UNload all ConfigurableDb files (modules) holding informations about
179 Configurables available in the release:
180 - remove imported modules from sys.modules
181 - clear the configurable Db
184 confModules =
set( [ cfgDb.get(k).
get(
'module')
for k
in cfgDb ] +
185 [ cfgDb.get(k).
get(
'package')
for k
in cfgDb ] )
188 for m
in sys.modules.keys():
189 if m
in confModules
or \
190 m.count(
"_merged_confDb") > 0
or \
191 m.count(
".GaudiHandles" ) > 0
or \
192 m.count(
"ConfigurableDb") > 0
or \
193 m.count(
"AthenaPython") > 0:
195 if hasattr(sys.modules[m],
'__dict__'):
196 for i
in sys.modules[m].__dict__.keys():
197 del sys.modules[m].__dict__[i]
203 """Localize and load a Configurable class based on the (C++) class name.
214 confClass = className
217 confClass = str.translate( confClass, _transtable )
220 confClassInfo = cfgDb.get( confClass )
223 confMod = confClassInfo
and confClassInfo.get(
'module' )
225 cfgDb.msg.warning(
"%s: Class %s not in database", requester, className )
230 mod = __import__( confMod, globals(), locals(), confClass, level=0 )
232 cfgDb.msg.warning(
"%s: Module %s not found (needed for configurable %s)",
233 requester, confMod, className )
238 confClass = getattr( mod, confClass )
239 except AttributeError:
240 cfgDb.msg.warning(
"%s: Configurable %s not found in module %s",
241 requester, confClass, confMod )
245 cfgDb.msg.debug(
"%s: Found configurable %s in module %s",
246 requester, confClass, confMod )
263 del _CfgDb, _Singleton
267 if __name__ ==
'__main__':
270 sys.modules[
'AthenaCommon.ConfigurableDb' ] = __main__
271 sys.modules[
'ConfigurableDb' ] = __main__
277 from StoreGate.StoreGateConf
import StoreGateSvc
278 assert( conf
is StoreGateSvc )