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