ConfigurableDb.py
Go to the documentation of this file.
1 # File: AthenaCommon/python/ConfigurableDb.py
2 # Author: Sebastien Binet (binet@cern.ch)
3 
4 """A singleton holding informations on the whereabouts of all the automatically
5 generated Configurables.
6 This repository of (informations on) Configurables is used by the PropertyProxy
7 class to locate Configurables and feed the JobOptionsSvc. It could also be used
8 to feed the AthenaEmacs module..."""
9 
10 __all__ = [ 'CfgDb', 'cfgDb', 'loadConfigurableDb', 'getConfigurable' ]
11 
12 import string
13 _transtable = string.maketrans('<>&*,: ().', '__rp__s___')
14 
15 import logging
16 log = logging.getLogger( 'ConfigurableDb' )
17 
18 class _CfgDb( dict ):
19  """
20  A singleton class holding informations about automatically generated
21  Configurables.
22  --> package holding that Configurable
23  --> library holding the components related to that Configurable
24  --> python module holding the Configurable
25  --> a dictionary of duplicates
26  """
27 
28  __slots__ = {
29  '_duplicates' : { },
30  }
31 
32  def __init__(self):
33  object.__init__(self)
34  self._duplicates = {}
35 
36  def add( self, configurable, package, module, lib ):
37  """Method to populate the Db.
38  It is called from the auto-generated Xyz_confDb.py files (genconf.cpp)
39  @param configurable: the name of the configurable being added
40  @param package: the name of the package which holds this Configurable
41  @param module: the name of the python module holding the Configurable
42  @param lib: the name of the library holding the component(s) (ie: the
43  C++ Gaudi component which is mapped by the Configurable)
44  """
45  cfg = { 'package' : package,
46  'module' : module,
47  'lib' : lib }
48  if self.has_key( configurable ):
49  ## check if it comes from the same library...
50  if cfg['lib'] != self[configurable]['lib']:
51  log.debug( "dup!! [%s] p=%s m=%s lib=%s",
52  configurable, package, module, lib )
53  if self._duplicates.has_key(configurable):
54  self._duplicates[configurable] += [ cfg ]
55  else:
56  self._duplicates[configurable] = [ cfg ]
57  else:
58  log.debug( "added [%s] p=%s m=%s lib=%s",
59  configurable, package, module, lib )
60  self[configurable] = cfg
61 
62  def duplicates(self):
63  return self._duplicates
64 
65  def _loadModule(self, fname):
66  f = open(fname)
67  for i,ll in enumerate(f):
68  l = ll.strip()
69  if l.startswith('#') or len(l) <= 0:
70  continue
71  try:
72  line = l.split()
73  cname = line[2]
74  pkg = line[0].split('.')[0]
75  module = line[0]
76  lib = line[1]
77  self.add(cname, pkg, module, lib)
78  except Exception:
79  f.close()
80  raise Exception(
81  "invalid line format: %s:%d: %r" %
82  (fname, i+1, ll)
83  )
84  f.close()
85 
86 
87 class _Singleton( object ):
88 
89  ## the object this singleton is holding
90  ## No other object will be created...
91  __obj = _CfgDb()
92 
93  def __call__( self ):
94  return self.__obj
95 
96 CfgDb = _Singleton()
97 
98 # clean-up
99 del _Singleton
100 del _CfgDb
101 
102 ## default name for CfgDb instance
103 cfgDb = CfgDb()
104 
105 ## Helper function to load all ConfigurableDb files holding informations
107  """Helper function to load all ConfigurableDb files (modules) holding
108  informations about Configurables
109  """
110  import os
111  import sys
112  from glob import glob
113  from os.path import join as path_join
114  log.debug( "loading confDb files..." )
115  nFiles = 0 # counter of imported files
116  pathlist = os.getenv("LD_LIBRARY_PATH", "").split(os.pathsep)
117  for path in pathlist:
118  if not os.path.isdir(path):
119  continue
120  log.debug( "walking in [%s]...", path )
121  confDbFiles = [f for f in [path_join(path, f) for f in os.listdir(path)
122  if f.endswith('.confdb')]
123  if os.path.isfile(f)]
124  # check if we use "*_merged.confdb"
125  mergedConfDbFiles = [f for f in confDbFiles
126  if f.endswith('_merged.confdb')]
127  if mergedConfDbFiles:
128  # use only the merged ones
129  confDbFiles = mergedConfDbFiles
130 
131  for confDb in confDbFiles:
132  log.debug( "\t-loading [%s]...", confDb )
133  try:
134  cfgDb._loadModule( confDb )
135  except Exception, err:
136  log.warning( "Could not load file [%s] !", confDb )
137  log.warning( "Reason: %s", err )
138  nFiles += 1
139  log.debug( "loading confDb files... [DONE]" )
140  nPkgs = len( set([k['package'] for k in cfgDb.values()]) )
141  log.debug( "loaded %i confDb packages", nPkgs )
142  return nFiles
143 
144 
145 def getConfigurable( className, requester='', assumeCxxClass=True ):
146  confClass=className
147  if assumeCxxClass:
148  # assume className is C++: --> translate to python
149  confClass = string.translate( confClass, _transtable )
150  # see if I have it in my dictionary
151  confClassInfo = cfgDb.get(confClass)
152  if not confClassInfo:
153  confClassInfo = cfgDb.get(confClass)
154  # get the python module
155  confMod = confClassInfo and confClassInfo.get('module')
156  if not confMod:
157  log.warning( "%s: Class %s not in database", requester, className )
158  return None
159  # load the module
160  try:
161  mod = __import__(confMod,globals(),locals(),confClass)
162  except ImportError:
163  log.warning( "%s: Module %s not found (needed for configurable %s)",
164  requester, confMod, className )
165  return None
166  # get the class
167  try:
168  confClass = getattr(mod,confClass)
169  except AttributeError:
170  log.warning( "%s: Configurable %s not found in module %s",
171  requester, confClass, confMod )
172  return None
173  # Got it!
174  log.debug( "%s: Found configurable %s in module %s",
175  requester, confClass, confMod )
176 
177  return confClass
def loadConfigurableDb()
Helper function to load all ConfigurableDb files holding informations.
def add(self, configurable, package, module, lib)
__obj
the object this singleton is holding No other object will be created...
def getConfigurable(className, requester='', assumeCxxClass=True)