00001
00002
00003
00004 """A singleton holding informations on the whereabouts of all the automatically
00005 generated Configurables.
00006 This repository of (informations on) Configurables is used by the PropertyProxy
00007 class to locate Configurables and feed the JobOptionsSvc. It could also be used
00008 to feed the AthenaEmacs module..."""
00009
00010 __all__ = [ 'CfgDb', 'cfgDb', 'loadConfigurableDb', 'getConfigurable' ]
00011
00012 import string
00013 _transtable = string.maketrans('<>&*,: ().', '__rp__s___')
00014
00015 import logging
00016 log = logging.getLogger( 'ConfigurableDb' )
00017
00018 class _CfgDb( dict ):
00019 """
00020 A singleton class holding informations about automatically generated
00021 Configurables.
00022 --> package holding that Configurable
00023 --> library holding the components related to that Configurable
00024 --> python module holding the Configurable
00025 --> a dictionary of duplicates
00026 """
00027
00028 __slots__ = {
00029 '_duplicates' : { },
00030 }
00031
00032 def __init__(self):
00033 object.__init__(self)
00034 self._duplicates = {}
00035 return
00036
00037 def add( self, configurable, package, module, lib ):
00038 """Method to populate the Db.
00039 It is called from the auto-generated Xyz_confDb.py files (genconf.cpp)
00040 @param configurable: the name of the configurable being added
00041 @param package: the name of the package which holds this Configurable
00042 @param module: the name of the python module holding the Configurable
00043 @param lib: the name of the library holding the component(s) (ie: the
00044 C++ Gaudi component which is mapped by the Configurable)
00045 """
00046 cfg = { 'package' : package,
00047 'module' : module,
00048 'lib' : lib }
00049 if self.has_key( configurable ):
00050
00051 if cfg['lib'] != self[configurable]['lib']:
00052 log.debug( "dup!! [%s] p=%s m=%s lib=%s",
00053 configurable, package, module, lib )
00054 if self._duplicates.has_key(configurable):
00055 self._duplicates[configurable] += [ cfg ]
00056 else:
00057 self._duplicates[configurable] = [ cfg ]
00058 pass
00059 else:
00060 log.debug( "added [%s] p=%s m=%s lib=%s",
00061 configurable, package, module, lib )
00062 self[configurable] = cfg
00063 pass
00064 return
00065
00066 def duplicates(self):
00067 return self._duplicates
00068
00069 pass
00070
00071 class _Singleton( object ):
00072
00073
00074
00075 __obj = _CfgDb()
00076
00077 def __call__( self ):
00078 return self.__obj
00079
00080 pass
00081
00082 CfgDb = _Singleton()
00083
00084
00085 del _Singleton
00086 del _CfgDb
00087
00088
00089 cfgDb = CfgDb()
00090
00091
00092 def loadConfigurableDb():
00093 """Helper function to load all ConfigurableDb files (modules) holding
00094 informations about Configurables
00095 """
00096 import os
00097 import sys
00098 from zipfile import is_zipfile, ZipFile
00099 from glob import glob
00100 from os.path import join as path_join
00101 log.debug( "importing confDb packages..." )
00102 nFiles = 0
00103 for path in sys.path:
00104 log.debug( "walking in [%s]..." % path )
00105 if not os.path.exists(path):
00106 continue
00107
00108
00109
00110 if "InstallArea" in path:
00111 if is_zipfile(path):
00112
00113 confDbModules = [ os.path.splitext(f)[0].replace('/','.')
00114 for f in ZipFile(path).namelist()
00115 if f.endswith("_merged_confDb.py") or f.endswith("_merged_confDb.pyc") ]
00116 else:
00117
00118 confDbModules = [ os.path.splitext( f[len(path)+1:] )[0].replace(os.sep,'.')
00119 for f in glob(path_join(path, "*_merged_confDb.py"))
00120 if os.path.isfile(f) ]
00121 else:
00122 continue
00123 for confDbModule in confDbModules:
00124 nFiles += 1
00125 log.debug( "\t-importing [%s]..." % confDbModule )
00126 try:
00127 mod = __import__( confDbModule )
00128 except ImportError, err:
00129 log.warning( "Could not import module [%s] !", confDbModule )
00130 log.warning( "Reason: %s", err )
00131 pass
00132 else:
00133
00134 del mod
00135 pass
00136 pass
00137 log.debug( "importing confDb packages... [DONE]" )
00138 nPkgs = len( set([k['package'] for k in cfgDb.values()]) )
00139 log.debug( "imported %i confDb packages" % nPkgs )
00140 return nFiles
00141
00142
00143 def getConfigurable( className, requester='', assumeCxxClass=True ):
00144 confClass=className
00145 if assumeCxxClass:
00146
00147 confClass = string.translate( confClass, _transtable )
00148
00149 confClassInfo = cfgDb.get(confClass)
00150 if not confClassInfo:
00151 confClassInfo = cfgDb.get(confClass)
00152
00153 confMod = confClassInfo and confClassInfo.get('module')
00154 if not confMod:
00155 log.warning( "%s: Class %s not in database", requester, className )
00156 return None
00157
00158 try:
00159 mod = __import__(confMod,globals(),locals(),confClass)
00160 except ImportError:
00161 log.warning( "%s: Module %s not found (needed for configurable %s)",
00162 requester, confMod, className )
00163 return None
00164
00165 try:
00166 confClass = getattr(mod,confClass)
00167 except AttributeError:
00168 log.warning( "%s: Configurable %s not found in module %s",
00169 requester, confClass, confMod )
00170 return None
00171
00172 log.debug( "%s: Found configurable %s in module %s",
00173 requester, confClass, confMod )
00174
00175 return confClass