28__all__ = [
"ConfigDictField"]
30from .callStack
import getCallStack, getStackFrame
31from .comparison
import compareConfigs, compareScalars, getComparisonName
32from .config
import Config, FieldValidationError, _autocast, _joinNamePath, _typeStr
33from .dictField
import Dict, DictField
37 """Internal representation of a dictionary of configuration classes.
39 Much like `Dict`, `ConfigDict` is a custom `MutableMapper` which tracks
40 the history of changes to any of its items.
43 def __init__(self, config, field, value, at, label):
44 Dict.__init__(self, config, field, value, at, label, setHistory=
False)
47 def __setitem__(self, k, x, at=None, label="setitem", setHistory=True):
49 msg = f
"Cannot modify a frozen Config. Attempting to set item at key {k!r} to value {x}"
55 msg =
"Key {!r} is of type {}, expected type {}".format(
63 msg =
"Value {} at key {!r} is of incorrect type {}. Expected type {}".format(
74 oldValue = self.
_dict.get(k,
None)
77 self.
_dict[k] = dtype(__name=name, __at=at, __label=label)
79 self.
_dict[k] = dtype(__name=name, __at=at, __label=label, **x._storage)
81 self.
historyhistory.append((
"Added item at key %s" % k, at, label))
85 oldValue.update(__at=at, __label=label, **x._storage)
87 self.
historyhistory.append((
"Modified item at key %s" % k, at, label))
92 Dict.__delitem__(self, k, at, label,
False)
93 self.
historyhistory.append((
"Removed item at key %s" % k, at, label))
97 """A configuration field (`~lsst.pex.config.Field` subclass) that is a
100 ``ConfigDictField`` behaves like `DictField` except that the
106 A description of the configuration field.
107 keytype : {`int`, `float`, `complex`, `bool`, `str`}
108 The type of the mapping keys. All keys must have this type.
110 The type of the values
in the mapping. This must be
114 default : ``itemtype``-dtype, optional
115 Default value of this field.
116 optional : `bool`, optional
119 deprecated :
None or `str`, optional
120 A description of why this Field
is deprecated, including removal date.
121 If
not None, the string
is appended to the docstring
for this Field.
126 Raised
if the inputs are invalid:
128 - ``keytype``
or ``itemtype`` arguments are
not supported types
129 (members of `ConfigDictField.supportedTypes`.
130 - ``dictCheck``
or ``itemCheck``
is not a callable function.
146 You can use ``ConfigDictField`` to create name-to-config mappings. One use
147 case
is for configuring mappings
for dataset types
in a Butler. In this
148 case, the dataset type names are arbitrary
and user-selected
while the
149 mapping configurations are known
and fixed.
152 DictClass = ConfigDict
165 source = getStackFrame()
173 deprecated=deprecated,
176 raise ValueError(
"'keytype' %s is not a supported type" % _typeStr(keytype))
177 elif not issubclass(itemtype, Config):
178 raise ValueError(
"'itemtype' %s is not a supported type" % _typeStr(itemtype))
179 if dictCheck
is not None and not hasattr(dictCheck,
"__call__"):
180 raise ValueError(
"'dictCheck' must be callable")
181 if itemCheck
is not None and not hasattr(itemCheck,
"__call__"):
182 raise ValueError(
"'itemCheck' must be callable")
191 if configDict
is not None:
194 configDict[k]._rename(fullname)
198 if value
is not None:
203 msg = f
"Item at key {k!r} is not a valid value: {item}"
205 DictField.validate(self, instance)
209 if configDict
is None:
214 dict_[k] = configDict[k].
toDict()
221 if configDict
is not None:
222 for v
in configDict.values():
224 imports |= v._imports
226 def save(self, outfile, instance):
229 if configDict
is None:
230 outfile.write(f
"{fullname}={configDict!r}\n")
233 outfile.write(f
"{fullname}={{}}\n")
234 for v
in configDict.values():
235 outfile.write(f
"{v._name}={_typeStr(v)}()\n")
240 if configDict
is not None:
244 def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
245 """Compare two fields for equality.
247 Used by `lsst.pex.ConfigDictField.compare`.
252 Left-hand side config instance to compare.
254 Right-hand side config instance to compare.
256 If `True`, this function returns
as soon
as an inequality
if found.
258 Relative tolerance
for floating point comparisons.
260 Absolute tolerance
for floating point comparisons.
262 A callable that takes a string, used (possibly repeatedly) to
268 `
True`
if the fields are equal, `
False` otherwise.
272 Floating point comparisons are performed by `numpy.allclose`.
276 name = getComparisonName(
279 if not compareScalars(
"keys for %s" % name,
set(d1.keys()),
set(d2.keys()), output=output):
282 for k, v1
in d1.items():
284 result = compareConfigs(
285 f
"{name}[{k!r}]", v1, v2, shortcut=shortcut, rtol=rtol, atol=atol, output=output
287 if not result
and shortcut:
289 equal = equal
and result
__get__(self, instance, owner=None, at=None, label="default")
FieldTypeVar __get__(self, Config instance, Any owner=None, Any at=None, str label="default")
Field[FieldTypeVar] __get__(self, None instance, Any owner=None, Any at=None, str label="default")
_setup(self, doc, dtype, default, check, optional, source, deprecated)
_compare(self, instance1, instance2, shortcut, rtol, atol, output)
_collectImports(self, instance, imports)
__init__(self, doc, keytype, itemtype, default=None, optional=False, dictCheck=None, itemCheck=None, deprecated=None)
save(self, outfile, instance)
__init__(self, config, field, value, at, label)
__setitem__(self, k, x, at=None, label="setitem", setHistory=True)
__delitem__(self, k, at=None, label="delitem")
daf::base::PropertySet * set