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