23 __all__ = [
"ConfigField"]
25 from .config
import Config, Field, FieldValidationError, _joinNamePath, _typeStr
26 from .comparison
import compareConfigs, getComparisonName
27 from .callStack
import getCallStack, getStackFrame
32 Defines a field which is itself a Config. 34 The behavior of this type of field is much like that of the base Field type. 36 Note that dtype must be a subclass of Config. 38 If default=None, the field will default to a default-constructed 41 Additionally, to allow for fewer deep-copies, assigning an instance of 42 ConfigField to dtype itself, is considered equivalent to assigning a 43 default-constructed sub-config. This means that the argument default can be 44 dtype, as well as an instance of dtype. 46 Assigning to ConfigField will update all of the fields in the config. 49 def __init__(self, doc, dtype, default=None, check=None):
50 if not issubclass(dtype, Config):
51 raise ValueError(
"dtype=%s is not a subclass of Config" %
56 self.
_setup(doc=doc, dtype=dtype, default=default, check=check,
57 optional=
False, source=source)
60 if instance
is None or not isinstance(instance, Config):
63 value = instance._storage.get(self.name,
None)
70 def __set__(self, instance, value, at=None, label="assignment"):
73 "Cannot modify a frozen Config")
74 name = _joinNamePath(prefix=instance._name, name=self.name)
76 if value != self.
dtype and type(value) != self.
dtype:
77 msg =
"Value %s is of incorrect type %s. Expected %s" % \
78 (value, _typeStr(value), _typeStr(self.
dtype))
84 oldValue = instance._storage.get(self.name,
None)
86 if value == self.
dtype:
87 instance._storage[self.name] = self.
dtype(__name=name, __at=at, __label=label)
89 instance._storage[self.name] = self.
dtype(__name=name, __at=at,
90 __label=label, **value._storage)
92 if value == self.
dtype:
94 oldValue.update(__at=at, __label=label, **value._storage)
95 history = instance._history.setdefault(self.name, [])
96 history.append((
"config value set", at, label))
100 value._rename(_joinNamePath(instance._name, self.name))
102 def save(self, outfile, instance):
112 return value.toDict()
118 if self.
check is not None and not self.
check(value):
119 msg =
"%s is not a valid value" % str(value)
122 def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
123 """Helper function for Config.compare; used to compare two fields for equality. 125 @param[in] instance1 LHS Config instance to compare. 126 @param[in] instance2 RHS Config instance to compare. 127 @param[in] shortcut If True, return as soon as an inequality is found. 128 @param[in] rtol Relative tolerance for floating point comparisons. 129 @param[in] atol Absolute tolerance for floating point comparisons. 130 @param[in] output If not None, a callable that takes a string, used (possibly repeatedly) 131 to report inequalities. 133 Floating point comparisons are performed by numpy.allclose; refer to that for details. 135 c1 = getattr(instance1, self.name)
136 c2 = getattr(instance2, self.name)
138 _joinNamePath(instance1._name, self.name),
139 _joinNamePath(instance2._name, self.name)
141 return compareConfigs(name, c1, c2, shortcut=shortcut, rtol=rtol, atol=atol, output=output)
def __get__(self, instance, owner=None)
def __set__(self, instance, value, at=None, label="assignment")
def compareConfigs(name, c1, c2, shortcut=True, rtol=1E-8, atol=1E-8, output=None)
def __init__(self, doc, dtype, default=None, check=None)
def __get__(self, instance, owner=None, at=None, label="default")
def _setup(self, doc, dtype, default, check, optional, source)
def freeze(self, instance)
def getStackFrame(relative=0)
def toDict(self, instance)
def rename(self, instance)
def save(self, outfile, instance)
def __set__(self, instance, value, at=None, label='assignment')
def validate(self, instance)
def getComparisonName(name1, name2)