15 from collections.abc
import MutableMapping, MutableSequence
17 _log = logging.getLogger(__name__)
18 is_64bits = sys.maxsize > 2**32
23 Basic property semantics implementation, with no validation/transformation.
25 Not to be used directly for any actual property, use only specializations.
28 __handled_types__ = ()
49 h.match(value)
if hasattr(h,
"match")
else h == value
52 raise TypeError(
"C++ type {!r} not supported".
format(value))
57 Transformation for data when reading the property.
63 Validation/transformation of the data to be stored.
69 Allow overriding the definition of "is set" if we need helper types.
75 Option string version of value.
77 if hasattr(value,
"__opt_value__"):
78 return value.__opt_value__()
85 Used when merging two Configurable instances, by default just ensure
86 the two values do not conflict, but it can be overridden in
87 derived semantics to, for example, append to the two lists.
90 raise ValueError(
"cannot merge values %r and %r" % (a, b))
96 Special semantics that makes a deep copy of the default value on first access
97 and considers a property set if its value is different from the default.
99 This semantics is meant to be used whenever there is no specific semantic
100 (with proper change detection) implemented for a type.
103 __handled_types__ = (re.compile(
r".*"),)
109 return copy.deepcopy(value)
114 return super(DefaultSemantics, self).
store(value)
120 except AttributeError:
128 __handled_types__ = (
"std::string",)
131 if not isinstance(value, str):
132 raise TypeError(
"cannot set property {} to {!r}".
format(self.
name, value))
137 __handled_types__ = (
"bool",)
144 __handled_types__ = (
"float",
"double")
147 from numbers
import Number
149 if not isinstance(value, Number):
151 "number expected, got {!r} in assignemnt to {}".
format(value, self.
name)
159 "signed char": (-128, 127),
160 "short": (-32768, 32767),
161 "int": (-2147483648, 2147483647),
163 (-9223372036854775808, 9223372036854775807)
165 else (-2147483648, 2147483647)
167 "long long": (-9223372036854775808, 9223372036854775807),
168 "unsigned char": (0, 255),
169 "unsigned short": (0, 65535),
170 "unsigned int": (0, 4294967295),
171 "unsigned long": (0, 18446744073709551615
if is_64bits
else 4294967295),
172 "unsigned long long": (0, 18446744073709551615),
175 __handled_types__ = tuple(INT_RANGES)
178 from numbers
import Number
180 if not isinstance(value, Number):
182 "number expected, got {!r} in assignment to {}".
format(value, self.
name)
186 _log.warning(
"converted %s to %d in assignment to %s", value, v, self.
name)
188 if v < min_value
or v > max_value:
190 "value {} outside limits for {!r} {}".
format(
197 _IDENTIFIER_RE =
r"[a-zA-Z_][a-zA-Z0-9_]*"
198 _NS_IDENT_RE =
r"{ident}(::{ident})*".
format(ident=_IDENTIFIER_RE)
199 _COMMA_SEPARATION_RE =
r"{exp}(,{exp})*"
203 __handled_types__ = (
207 r"AlgTool(:{})?$".
format(_COMMA_SEPARATION_RE.format(exp=_NS_IDENT_RE))
210 r"Service(:{})?$".
format(_COMMA_SEPARATION_RE.format(exp=_NS_IDENT_RE))
215 super(ComponentSemantics, self).
__init__(cpp_type)
224 from .
import Configurable, Configurables
226 if isinstance(value, Configurable):
228 elif isinstance(value, str):
230 if value
in Configurable.instances:
231 value = Configurable.instances[value]
235 t, n = value.split(
"/")
238 value = Configurables.getByType(t).getInstance(n)
241 "cannot assign {!r} to {!r}, requested string or {!r}".
format(
245 if value.__component_type__ != self.
cpp_type:
247 "wrong type for {!r}: expected {!r}, got {!r}".
format(
253 if value.__interfaces__:
254 if not self.
interfaces.issubset(value.__interfaces__):
256 "wrong interfaces for {!r}: required {}".
format(
260 except AttributeError:
265 return self.
store(value)
270 Return an iterator over the list of template arguments in a C++ type
273 >>> t = 'map<string, vector<int, allocator<int> >, allocator<v<i>, a<i>> >'
274 >>> list(extract_template_args(t))
275 ['string', 'vector<int, allocator<int> >', 'allocator<v<i>, a<i>>']
276 >>> list(extract_template_args('int'))
281 for p, c
in enumerate(cpp_type):
283 if template_level == 1:
284 yield cpp_type[arg_start:p].strip()
288 if template_level == 1:
292 if template_level == 0:
293 yield cpp_type[arg_start:p].strip()
308 return len(self.
data)
319 raise RuntimeError(
"cannot remove elements from the default value")
341 return repr(self.
data)
345 __handled_types__ = (re.compile(
r"(std::)?(vector|list)<.*>$"),)
348 super(SequenceSemantics, self).
__init__(cpp_type)
364 new_value.extend(value)
369 new_value.default = value
374 Option string version of value.
376 if not isinstance(value, _ListHelper):
378 return value.opt_value()
383 Extend the sequence-semantics with a merge-method to behave like a
384 OrderedSet: Values are unique but the order is maintained.
385 Use 'OrderedSet<T>' as fifth parameter of the Gaudi::Property<T> constructor
386 to invoke this merging method. Also applies to std::[unordered_]set.
389 __handled_types__ = (
390 re.compile(
r"(std::)?(unordered_)?set<.*>$"),
391 re.compile(
r"^OrderedSet<.*>$"),
395 super(OrderedSetSemantics, self).
__init__(cpp_type)
405 def __init__(self, key_semantics, value_semantics):
417 return len(self.
data)
432 raise RuntimeError(
"cannot remove elements from the default value")
436 for key
in self.
data:
453 def get(self, key, default=None):
464 for key, value
in otherMap.items():
474 return repr(self.
data)
478 __handled_types__ = (re.compile(
r"(std::)?(unordered_)?map<.*>$"),)
481 super(MappingSemantics, self).
__init__(cpp_type)
498 new_value.update(value)
503 new_value.default = value
508 Option string version of value.
510 if not isinstance(value, _DictHelper):
512 return value.opt_value()
517 for c
in globals().values()
518 if isinstance(c, type)
519 and issubclass(c, PropertySemantics)
520 and c
not in (PropertySemantics, DefaultSemantics)
525 for semantics
in SEMANTICS:
527 return semantics(cpp_type)