The Gaudi Framework
master (bb4415cc)
Toggle main menu visibility
Loading...
Searching...
No Matches
_db.py
Go to the documentation of this file.
1
12
import
logging
13
import
os
14
import
sys
15
16
17
class
ConfDB2
(object):
18
def
__init__
(self):
19
import
shelve
20
from
pathlib
import
Path
21
22
from
GaudiPluginService.cpluginsvc
import
GAUDI_DEFAULT_PLUGIN_PATH
23
24
self.
_dbs
= {}
25
ignored_files = set(os.environ.get(
"CONFIGURABLE_DB_IGNORE"
,
""
).split(
","
))
26
loaded = set()
27
for
path
in
GAUDI_DEFAULT_PLUGIN_PATH:
28
if
not
path
or
not
os.path.isdir(path):
29
continue
30
dbfiles = [
31
fabs
32
for
f
in
Path(path).glob(
"*.confdb2"
)
33
if
(fabs := f.absolute().as_posix())
not
in
ignored_files
34
and
fabs
not
in
loaded
35
]
36
dbfiles.sort()
37
# Avoid loading same file twice (can happen if entries in search path point to same dir)
38
loaded.update(dbfiles)
39
for
db
in
[shelve.open(f,
"r"
)
for
f
in
dbfiles]:
40
for
key
in
db:
41
self.
_dbs
.setdefault(key, db)
42
43
def
__getitem__
(self, key):
44
return
self.
_dbs
[key][key]
45
46
def
__contains__
(self, key):
47
return
key
in
self.
_dbs
48
49
def
__iter__
(self):
50
return
iter(self.
_dbs
)
51
52
53
# allow overriding the low level DB access for testing
54
if
"GAUDICONFIG2_DB"
in
os.environ:
55
exec(
56
"from {} import {} as _DB"
.
format
(*os.environ[
"GAUDICONFIG2_DB"
].rsplit(
"."
, 1))
57
)
58
else
:
# pragma no cover
59
_DB =
ConfDB2
()
60
61
62
_TRANS_TABLE = str.maketrans(
"<>&*,: ()."
,
"__rp__s___"
)
63
64
65
def
_normalize_cpp_type_name
(name):
66
"""
67
Translate a C++ type name (with templates etc.) to Python identifier.
68
"""
69
return
name.replace(
", "
,
","
).translate(_TRANS_TABLE)
70
71
72
def
split_namespace
(typename):
73
"""
74
Split a C++ qualified namespace in the tuple (top_namespace, rest) starting
75
searching the separator from pos.
76
77
>>> split_namespace('std::chrono::time_point')
78
('std', 'chrono::time_point')
79
"""
80
# find next namespace separator skipping template arguments
81
tpos = typename.find(
"<"
)
82
pos = typename.find(
"::"
)
83
# '<' can appear only in a class name, if we find a '::'
84
# earlier than a '<', then we got a namespace, else a class
85
if
pos > 0
and
(tpos < 0
or
pos < tpos):
86
head = typename[:pos]
87
tail = typename[pos + 2 :]
88
else
:
89
head =
None
90
tail = typename
91
return
(head, tail)
92
93
94
class
ConfigurablesDB
(object):
95
"""
96
Helper to expose Configurables classes (from Configurables database) as
97
a tree of subpackages, each mapped to a namespace.
98
"""
99
100
def
__init__
(self, modulename, root=None):
101
"""
102
@param modulename: name of the module
103
@param root: name of the root modules (that pointing to the root C++
104
namespace), None is ewuivalent to pass modulename as root
105
"""
106
self.
_log
= logging.getLogger(modulename)
107
self.
_log
.debug(
"initializing module %r (with root %r)"
, modulename, root)
108
109
self.
__name__
= modulename
110
self.
__loader__
=
None
111
self.
_root
= root
or
modulename
112
assert
(
not
root)
or
modulename.startswith(
113
root +
"."
114
),
"modulename should be (indirect submodule of root)"
115
116
self.
_namespace
= modulename[len(root) + 1 :].replace(
"."
,
"::"
)
if
root
else
""
117
self.
_log
.debug(
"%r mapping namespace %r"
, modulename, self.
_namespace
or
"::"
)
118
119
self.
_namespaces
, self.
_classes
= self.
_getEntries
()
120
self.
_alt_names
= {}
121
for
cname
in
self.
_classes
:
122
alt_name =
_normalize_cpp_type_name
(cname)
123
if
alt_name != cname:
124
self.
_alt_names
[alt_name] = cname
125
if
" "
in
cname:
# allow matching of 'T<A, B>' a well as 'T<A,B>'
126
self.
_alt_names
[cname.replace(
" "
,
""
)] = cname
127
self.
__all__
= list(
128
self.
_namespaces
.union(self.
_classes
).union(self.
_alt_names
)
129
)
130
131
sys.modules[modulename] = self
132
133
for
submodule
in
self.
_namespaces
:
134
setattr(
135
self,
136
submodule,
137
ConfigurablesDB
(
"."
.join([self.
__name__
, submodule]), self.
_root
),
138
)
139
140
def
_getEntries
(self):
141
"""
142
Extract from the Configurables DB the namespaces and classes names in
143
the namespace this instance represents.
144
"""
145
self.
_log
.debug(
"getting list of entries under %r"
, self.
_namespace
)
146
prefix = self.
_namespace
+
"::"
if
self.
_namespace
else
""
147
prefix_len = len(prefix)
148
149
namespaces = set()
150
classes = set()
151
for
name
in
_DB:
152
if
name.startswith(prefix):
153
head, tail =
split_namespace
(name[prefix_len:])
154
if
head:
155
namespaces.add(head)
156
else
:
157
classes.add(tail)
158
159
self.
_log
.debug(
160
"found %d namespaces and %d classes"
, len(namespaces), len(classes)
161
)
162
return
(namespaces, classes)
163
164
def
__getattr__
(self, name):
165
"""
166
Helper to instantiate on demand Configurable classes.
167
"""
168
if
name
in
self.
_classes
:
169
fullname =
"::"
.join([self.
_namespace
, name])
if
self.
_namespace
else
name
170
from
._configurables
import
makeConfigurableClass
171
172
self.
_log
.debug(
"generating %r (%s)"
, name, fullname)
173
entry = makeConfigurableClass(
174
name,
175
__module__=self.
__name__
,
176
__qualname__=name,
177
__cpp_type__=fullname,
178
**_DB[fullname],
179
)
180
elif
name.replace(
" "
,
""
)
in
self.
_alt_names
:
181
entry = getattr(self, self.
_alt_names
[name.replace(
" "
,
""
)])
182
elif
name ==
"__spec__"
:
# pragma no cover
183
import
importlib
184
185
entry = importlib.machinery.ModuleSpec(
186
name=self.__package__,
187
loader=self.
__loader__
,
188
)
189
elif
name ==
"__package__"
:
# pragma no cover
190
entry = self.
__name__
191
else
:
192
raise
AttributeError(
193
"module {!r} has no attribute {!r}"
.
format
(self.
__name__
, name)
194
)
195
setattr(self, name, entry)
196
return
entry
197
198
def
getByType
(self, typename):
199
"""
200
Return a configurable from the fully qualified type name (relative to
201
the current namespace).any
202
"""
203
head, tail =
split_namespace
(typename)
204
if
head:
205
return
getattr(self, head).
getByType
(tail)
206
else
:
207
return
getattr(self, tail)
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition
MsgStream.cpp:93
GaudiConfig2._db.ConfDB2
Definition
_db.py:17
GaudiConfig2._db.ConfDB2.__contains__
__contains__(self, key)
Definition
_db.py:46
GaudiConfig2._db.ConfDB2.__getitem__
__getitem__(self, key)
Definition
_db.py:43
GaudiConfig2._db.ConfDB2.__iter__
__iter__(self)
Definition
_db.py:49
GaudiConfig2._db.ConfDB2._dbs
dict _dbs
Definition
_db.py:24
GaudiConfig2._db.ConfDB2.__init__
__init__(self)
Definition
_db.py:18
GaudiConfig2._db.ConfigurablesDB
Definition
_db.py:94
GaudiConfig2._db.ConfigurablesDB.__all__
__all__
Definition
_db.py:127
GaudiConfig2._db.ConfigurablesDB._classes
_classes
Definition
_db.py:119
GaudiConfig2._db.ConfigurablesDB._namespace
str _namespace
Definition
_db.py:116
GaudiConfig2._db.ConfigurablesDB._alt_names
dict _alt_names
Definition
_db.py:120
GaudiConfig2._db.ConfigurablesDB.__loader__
__loader__
Definition
_db.py:110
GaudiConfig2._db.ConfigurablesDB.__getattr__
__getattr__(self, name)
Definition
_db.py:164
GaudiConfig2._db.ConfigurablesDB._getEntries
_getEntries(self)
Definition
_db.py:140
GaudiConfig2._db.ConfigurablesDB.getByType
getByType(self, typename)
Definition
_db.py:198
GaudiConfig2._db.ConfigurablesDB.__init__
__init__(self, modulename, root=None)
Definition
_db.py:100
GaudiConfig2._db.ConfigurablesDB._namespaces
_namespaces
Definition
_db.py:119
GaudiConfig2._db.ConfigurablesDB.__name__
__name__
Definition
_db.py:109
GaudiConfig2._db.ConfigurablesDB._log
_log
Definition
_db.py:106
GaudiConfig2._db.ConfigurablesDB._root
_root
Definition
_db.py:111
GaudiConfig2._db.split_namespace
split_namespace(typename)
Definition
_db.py:72
GaudiConfig2._db._normalize_cpp_type_name
_normalize_cpp_type_name(name)
Definition
_db.py:65
GaudiConfiguration
python
GaudiConfig2
_db.py
Generated on
for The Gaudi Framework by
1.17.0