12_GLOBAL_INSTANCES =
False
17 Enable or disable the global instances database.
19 By default global instances are enabled.
21 global _GLOBAL_INSTANCES
22 if enable == _GLOBAL_INSTANCES:
26 not Configurable.instances
27 ),
"Configurable instances DB not empty, cannot be disabled"
28 _GLOBAL_INSTANCES = enable
33 Descriptor class to implement validation of Configurable properties.
36 def __init__(self, cpp_type, default, doc="undocumented", semantics=None):
37 from .semantics
import getSemanticsFor
42 self.
semantics = getSemanticsFor(semantics, strict=
True)
57 if name
not in instance._properties
and hasattr(self.
semantics,
"default"):
65 del instance._properties[self.
name]
72 value = instance._properties[self.
name]
84 Return "merge" (according to the semantic) of the value
85 in this property and the incoming value.
94 Metaclass for Configurables.
97 def __new__(cls, name, bases, namespace, **kwds):
101 if isinstance(namespace[key], Property)
104 doc = namespace.get(
"__doc__",
"").rstrip()
105 doc +=
"\n\nProperties\n----------\n"
108 f
"- {name}: {p.cpp_type} ({p.default!r})\n {p.__doc__}\n"
109 for name, p
in props.items()
112 namespace[
"__doc__"] = doc
113 namespace[
"_descriptors"] = props
114 slots = set(namespace.get(
"__slots__", []))
115 slots.update([
"_properties",
"_name"])
116 namespace[
"__slots__"] = tuple(slots)
117 result = type.__new__(cls, name, bases, namespace)
123 String representation of the value, such that it can be consumed be the
124 Gaudi option parsers.
126 if hasattr(value,
"__opt_repr__"):
127 return value.__opt_repr__()
133 Base class for all configurable instances.
141 if "parent" in kwargs:
142 parent = kwargs.pop(
"parent")
143 if isinstance(parent, str):
146 raise TypeError(
"name is needed when a parent is specified")
147 name = f
"{parent.name}.{name}"
150 elif not _GLOBAL_INSTANCES:
152 for key, value
in kwargs.items():
153 setattr(self, key, value)
157 return cls.
instances.get(name)
or cls(name)
162 raise AttributeError(
163 f
"{repr(type(self).__name__)} instance was not named yet"
169 if value == self.
_name:
171 if not isinstance(value, str)
or not value:
172 raise TypeError(f
"expected string, got {type(value).__name__} instead")
173 if _GLOBAL_INSTANCES:
175 raise ValueError(f
"name {repr(value)} already used")
185 if _GLOBAL_INSTANCES:
190 raise TypeError(
"name attribute cannot be deleted")
195 args.append(repr(self.
name))
196 except AttributeError:
198 args.extend(f
"{k}={repr(v)}" for k, v
in self.
_properties.items())
199 return "{}({})".
format(type(self).__name__,
", ".join(args))
204 state[
"name"] = self.
name
205 except AttributeError:
211 self.
name = state.get(
"name")
217 return f
"{self.__cpp_type__}/{self.name}"
222 for p
in self._descriptors.values():
223 if explicit_defaults
or p.__is_set__(self, type(self)):
224 out[
".".join([name, p.name])] =
opt_repr(
225 p.__opt_value__(self, type(self))
230 return self._descriptors[propname].__is_set__(self, type(self))
234 return cls.__component_type__
244 return f
"{self.__cpp_type__}/{self.name}"
247 return f
"{self.__cpp_type__}/{self.name}"
251 return {k: v.default
for k, v
in cls._descriptors.items()}
255 return cls._descriptors[name].default
258 """Clone instance with all its properties."""
263 Merge the properties of the other instance into the current one.
265 The two instances have to be of the same type, have the same name
266 (or both unnamed) and the settings must be mergable (according to
271 if type(self)
is not type(other):
273 f
"cannot merge instance of {type(other).__name__} into an instance of { type(self).__name__}"
277 if self.
name != other.name:
279 f
"cannot merge configurables with different names ({self.name} and {other.name})"
281 except AttributeError:
282 if hasattr(self,
"name") != hasattr(other,
"name"):
284 "cannot merge a named configurable with an unnamed one"
287 for name
in other._properties:
290 and self.
_properties[name] == other._properties[name]
294 self.
_properties[name] = self._descriptors[name].__merge__(
295 self, type(self), getattr(other, name)
297 except ValueError
as err:
299 "conflicting settings for property {} of {}: {}".
format(
301 self.
name if hasattr(self,
"name")
else type(self).__name__,
311 Create a Configurable specialization.
313 properties = namespace.pop(
"properties", {})
314 namespace.update({pname:
Property(*pargs)
for pname, pargs
in properties.items()})
316 return type(name, (Configurable,), namespace)
321 Return a dictionary with all explicitly set options, or with also the
322 defaults if explicit_defaults is set to True.
325 for c
in Configurable.instances.values():
326 opts.update(c.__opt_properties__(explicit_defaults))
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
__init__(self, name=None, **kwargs)
__setstate__(self, state)
getDefaultProperty(cls, name)
clone(self, newname=None)
getDefaultProperties(cls)
__opt_properties__(self, explicit_defaults=False)
is_property_set(self, propname)
__get__(self, instance, owner)
__init__(self, cpp_type, default, doc="undocumented", semantics=None)
__delete__(self, instance)
__opt_value__(self, instance, owner)
__set__(self, instance, value)
__set_name__(self, owner, name)
__is_set__(self, instance, owner)
__merge__(self, instance, owner, value)
int merge(const char *target, const char *source, bool fixup=false, bool dbg=true)
useGlobalInstances(enable)
makeConfigurableClass(name, **namespace)
all_options(explicit_defaults=False)