![]() |
|
|
Generated: 8 Jan 2009 |
00001 # File: AthenaCommon/python/ConfigurableDb.py 00002 # Author: Sebastien Binet (binet@cern.ch) 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 ## check if it comes from the same library... 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 # class _CfgDb 00070 00071 class _Singleton( object ): 00072 00073 ## the object this singleton is holding 00074 ## No other object will be created... 00075 __obj = _CfgDb() 00076 00077 def __call__( self ): 00078 return self.__obj 00079 00080 pass # class _Singleton 00081 00082 CfgDb = _Singleton() 00083 00084 # clean-up 00085 del _Singleton 00086 del _CfgDb 00087 00088 ## default name for CfgDb instance 00089 cfgDb = CfgDb() 00090 00091 ## Helper function to load all ConfigurableDb files holding informations 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 glob import glob 00099 from os.path import join as path_join 00100 log.debug( "importing confDb packages..." ) 00101 nFiles = 0 00102 for path in sys.path: 00103 log.debug( "walking in [%s]..." % path ) 00104 if not os.path.exists(path): 00105 continue 00106 # speed-up: <project>_merged_confDb.py files are installed as : 00107 # "/some/path/InstallArea/python/<project>_merged_confDb.py 00108 # so why bother wandering in other directories ? 00109 if not path.endswith("InstallArea"+os.sep+"python"): 00110 continue 00111 confDbFiles = [ f for f in glob(path_join(path, "*_merged_confDb.py")) 00112 if os.path.isfile(f) ] 00113 for confDb in confDbFiles: 00114 nFiles += 1 00115 # turn filename syntax into module syntax: remove path+extension and replace / with . (dot) 00116 confDbModule = os.path.splitext(confDb[len(path)+1:])[0].replace(os.sep,'.') 00117 log.debug( "\t-importing [%s]..." % confDbModule ) 00118 try: 00119 mod = __import__( confDbModule ) 00120 except ImportError, err: 00121 log.warning( "Could not import module [%s] !", confDbModule ) 00122 log.warning( "Reason: %s", err ) 00123 pass 00124 else: 00125 # don't need to keep the module 00126 del mod 00127 pass 00128 pass # loop over sys.path 00129 log.debug( "importing confDb packages... [DONE]" ) 00130 nPkgs = len( set([k['package'] for k in cfgDb.values()]) ) 00131 log.debug( "imported %i confDb packages" % nPkgs ) 00132 return nFiles 00133 00134 00135 def getConfigurable( className, requester='', assumeCxxClass=True ): 00136 confClass=className 00137 if assumeCxxClass: 00138 # assume className is C++: --> translate to python 00139 confClass = string.translate( confClass, _transtable ) 00140 # see if I have it in my dictionary 00141 confClassInfo = cfgDb.get(confClass) 00142 if not confClassInfo: 00143 confClassInfo = cfgDb.get(confClass) 00144 # get the python module 00145 confMod = confClassInfo and confClassInfo.get('module') 00146 if not confMod: 00147 log.warning( "%s: Class %s not in database", requester, className ) 00148 return None 00149 # load the module 00150 try: 00151 mod = __import__(confMod,globals(),locals(),confClass) 00152 except ImportError: 00153 log.warning( "%s: Module %s not found (needed for configurable %s)", 00154 requester, confMod, className ) 00155 return None 00156 # get the class 00157 try: 00158 confClass = getattr(mod,confClass) 00159 except AttributeError: 00160 log.warning( "%s: Configurable %s not found in module %s", 00161 requester, confClass, confMod ) 00162 return None 00163 # Got it! 00164 log.debug( "%s: Found configurable %s in module %s", 00165 requester, confClass, confMod ) 00166 00167 return confClass