20 from itertools
import chain
21 from pathlib
import Path
23 from GaudiPluginService.cpluginsvc
import GAUDI_DEFAULT_PLUGIN_PATH
27 [
"GAUDI_PLUGIN_PATH",
"DYLD_LIBRARY_PATH"]
28 if sys.platform ==
"darwin"
29 else [
"GAUDI_PLUGIN_PATH",
"LD_LIBRARY_PATH"]
31 ignored_files = set(os.environ.get(
"CONFIGURABLE_DB_IGNORE",
"").split(
","))
33 [GAUDI_DEFAULT_PLUGIN_PATH],
34 *[os.getenv(pv,
"").split(os.pathsep)
for pv
in pathvars],
36 if not path
or not os.path.isdir(path):
39 f.absolute().as_posix()
40 for f
in Path(path).glob(
"*.confdb2")
41 if f.absolute().as_posix()
not in ignored_files
44 for db
in [shelve.open(f,
"r")
for f
in dbfiles]:
46 self.
_dbs.setdefault(key, db)
49 return self.
_dbs[key][key]
52 return key
in self.
_dbs
55 return iter(self.
_dbs)
59if "GAUDICONFIG2_DB" in os.environ:
61 "from {} import {} as _DB".
format(*os.environ[
"GAUDICONFIG2_DB"].rsplit(
".", 1))
67_TRANS_TABLE = str.maketrans(
"<>&*,: ().",
"__rp__s___")
72 Translate a C++ type name (with templates etc.) to Python identifier.
74 return name.replace(
", ",
",").translate(_TRANS_TABLE)
79 Split a C++ qualified namespace in the tuple (top_namespace, rest) starting
80 searching the separator from pos.
82 >>> split_namespace('std::chrono::time_point')
83 ('std', 'chrono::time_point')
86 tpos = typename.find(
"<")
87 pos = typename.find(
"::")
90 if pos > 0
and (tpos < 0
or pos < tpos):
92 tail = typename[pos + 2 :]
101 Helper to expose Configurables classes (from Configurables database) as
102 a tree of subpackages, each mapped to a namespace.
107 @param modulename: name of the module
108 @param root: name of the root modules (that pointing to the root C++
109 namespace), None is ewuivalent to pass modulename as root
111 self.
_log = logging.getLogger(modulename)
112 self.
_log.debug(
"initializing module %r (with root %r)", modulename, root)
117 assert (
not root)
or modulename.startswith(
119 ),
"modulename should be (indirect submodule of root)"
121 self.
_namespace = modulename[len(root) + 1 :].replace(
".",
"::")
if root
else ""
122 self.
_log.debug(
"%r mapping namespace %r", modulename, self.
_namespace or "::")
128 if alt_name != cname:
131 self.
_alt_names[cname.replace(
" ",
"")] = cname
136 sys.modules[modulename] = self
147 Extract from the Configurables DB the namespaces and classes names in
148 the namespace this instance represents.
150 self.
_log.debug(
"getting list of entries under %r", self.
_namespace)
152 prefix_len = len(prefix)
157 if name.startswith(prefix):
165 "found %d namespaces and %d classes", len(namespaces), len(classes)
167 return (namespaces, classes)
171 Helper to instantiate on demand Configurable classes.
175 from ._configurables
import makeConfigurableClass
177 self.
_log.debug(
"generating %r (%s)", name, fullname)
178 entry = makeConfigurableClass(
182 __cpp_type__=fullname,
185 elif name.replace(
" ",
"")
in self.
_alt_names:
186 entry = getattr(self, self.
_alt_names[name.replace(
" ",
"")])
187 elif name ==
"__spec__":
190 entry = importlib.machinery.ModuleSpec(
191 name=self.__package__,
194 elif name ==
"__package__":
197 raise AttributeError(
200 setattr(self, name, entry)
205 Return a configurable from the fully qualified type name (relative to
206 the current namespace).any
210 return getattr(self, head).
getByType(tail)
212 return getattr(self, tail)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
getByType(self, typename)
__init__(self, modulename, root=None)
_normalize_cpp_type_name(name)
split_namespace(typename)