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