The Gaudi Framework  v32r0 (3325bb39)
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 self.has_key(configurable):
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 self._duplicates.has_key(configurable):
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 Exception:
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  if sys.platform == 'darwin':
120  pathlist = os.getenv("DYLD_LIBRARY_PATH", "").split(os.pathsep)
121  else:
122  pathlist = os.getenv("LD_LIBRARY_PATH", "").split(os.pathsep)
123  for path in pathlist:
124  if not os.path.isdir(path):
125  continue
126  log.debug("walking in [%s]...", path)
127  confDbFiles = [
128  f for f in [
129  path_join(path, f) for f in os.listdir(path)
130  if f.endswith('.confdb')
131  ] if os.path.isfile(f)
132  ]
133  # check if we use "*_merged.confdb"
134  mergedConfDbFiles = [
135  f for f in confDbFiles if f.endswith('_merged.confdb')
136  ]
137  if mergedConfDbFiles:
138  # use only the merged ones
139  confDbFiles = mergedConfDbFiles
140 
141  for confDb in confDbFiles:
142  log.debug("\t-loading [%s]...", confDb)
143  try:
144  cfgDb._loadModule(confDb)
145  except Exception as err:
146  log.warning("Could not load file [%s] !", confDb)
147  log.warning("Reason: %s", err)
148  nFiles += 1
149  log.debug("loading confDb files... [DONE]")
150  nPkgs = len(set([k['package'] for k in cfgDb.values()]))
151  log.debug("loaded %i confDb packages", nPkgs)
152  return nFiles
153 
154 
155 def getConfigurable(className, requester='', assumeCxxClass=True):
156  confClass = className
157  if assumeCxxClass:
158  # assume className is C++: --> translate to python
159  try:
160  confClass = str.translate(confClass, _transtable)
161  except AttributeError:
162  # Python 2 compatibility
163  confClass = string.translate(confClass, _transtable)
164  # see if I have it in my dictionary
165  confClassInfo = cfgDb.get(confClass)
166  if not confClassInfo:
167  confClassInfo = cfgDb.get(confClass)
168  # get the python module
169  confMod = confClassInfo and confClassInfo.get('module')
170  if not confMod:
171  log.warning("%s: Class %s not in database", requester, className)
172  return None
173  # load the module
174  try:
175  mod = __import__(confMod, globals(), locals(), confClass)
176  except ImportError:
177  log.warning("%s: Module %s not found (needed for configurable %s)",
178  requester, confMod, className)
179  return None
180  # get the class
181  try:
182  confClass = getattr(mod, confClass)
183  except AttributeError:
184  log.warning("%s: Configurable %s not found in module %s", requester,
185  confClass, confMod)
186  return None
187  # Got it!
188  log.debug("%s: Found configurable %s in module %s", requester, confClass,
189  confMod)
190 
191  return confClass
def add(self, configurable, package, module, lib)
def getConfigurable(className, requester='', assumeCxxClass=True)