| # Gaudi Framework, version v21r7 |

Home |  | Generated: 22 Jan 2010

# ConfigurableDb.py

Go to the documentation of this file.

    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 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 # counter of imported files
    00103     for path in sys.path:
    00104         log.debug( "walking in [%s]..." % path )
    00105         if not os.path.exists(path):
    00106             continue
    00107         # speed-up: <project>_merged_confDb.py files are installed as :
    00108         # "/some/path/InstallArea/python/<project>_merged_confDb.py
    00109         # so why bother wandering in other directories ?
    00110         if path.endswith(path_join("InstallArea","python")):
    00111             # turn filename syntax into module syntax: remove path+extension and replace / with . (dot)
    00112             confDbModules = [ os.path.splitext( f[len(path)+1:] )[0].replace(os.sep,'.')
    00113                               for f in glob(path_join(path, "*_merged_confDb.py"))
    00114                               if os.path.isfile(f) ]
    00115         elif path.endswith(path_join("InstallArea","python.zip")) and is_zipfile(path):
    00116             # turn filename syntax into module syntax: remove path+extension and replace / with . (dot)
    00117             confDbModules = [ os.path.splitext(f)[0].replace('/','.')
    00118                              for f in ZipFile(path).namelist()
    00119                              if f.endswith("_merged_confDb.py") or f.endswith("_merged_confDb.pyc") ]
    00120         else:
    00121             continue
    00122         for confDbModule in confDbModules:
    00123             nFiles += 1
    00124             log.debug( "\t-importing [%s]..." % confDbModule )
    00125             try:
    00126                 mod = __import__( confDbModule )
    00127             except ImportError, err:
    00128                 log.warning( "Could not import module [%s] !", confDbModule )
    00129                 log.warning( "Reason: %s", err )
    00130                 pass
    00131             else:
    00132                 # don't need to keep the module
    00133                 del mod
    00134             pass
    00135         pass # loop over sys.path
    00136     log.debug( "importing confDb packages... [DONE]" )
    00137     nPkgs = len( set([k['package'] for k in cfgDb.values()]) )
    00138     log.debug( "imported %i confDb packages" % nPkgs )
    00139     return nFiles
    00140
    00141
    00142 def getConfigurable( className, requester='', assumeCxxClass=True ):
    00143     confClass=className
    00144     if assumeCxxClass:
    00145         # assume className is C++: --> translate to python
    00146         confClass = string.translate( confClass, _transtable )
    00147     # see if I have it in my dictionary
    00148     confClassInfo = cfgDb.get(confClass)
    00149     if not confClassInfo:
    00150         confClassInfo = cfgDb.get(confClass)
    00151     # get the python module
    00152     confMod = confClassInfo and confClassInfo.get('module')
    00153     if not confMod:
    00154         log.warning( "%s: Class %s not in database", requester, className )
    00155         return None
    00156     # load the module
    00157     try:
    00158         mod = __import__(confMod,globals(),locals(),confClass)
    00159     except ImportError:
    00160         log.warning( "%s: Module %s not found (needed for configurable %s)",
    00161                      requester, confMod, className )
    00162         return None
    00163     # get the class
    00164     try:
    00165         confClass = getattr(mod,confClass)
    00166     except AttributeError:
    00167         log.warning( "%s: Configurable %s not found in module %s",
    00168                      requester, confClass, confMod )
    00169         return None
    00170     # Got it!
    00171     log.debug( "%s: Found configurable %s in module %s",
    00172                requester, confClass, confMod )
    00173
    00174     return confClass