From 8858de39b7a91a33346e4a7597acfb312914dd8f Mon Sep 17 00:00:00 2001 From: Erfan Nourbakhsh Date: Tue, 10 Dec 2024 23:20:53 -0500 Subject: [PATCH] Add keyCheck user callback function to ConfigDictField --- python/lsst/pex/config/configDictField.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/python/lsst/pex/config/configDictField.py b/python/lsst/pex/config/configDictField.py index c285f10..ba981e8 100644 --- a/python/lsst/pex/config/configDictField.py +++ b/python/lsst/pex/config/configDictField.py @@ -77,6 +77,11 @@ def __setitem__(self, k, x, at=None, label="setitem", setHistory=True): ) raise FieldValidationError(self._field, self._config, msg) + # validate key using keycheck + if self._field.keyCheck is not None and not self._field.keyCheck(k): + msg = f"Key {k!r} is not a valid key" + raise FieldValidationError(self._field, self._config, msg) + if at is None: at = getCallStack() name = _joinNamePath(self._config._name, self._field.name, k) @@ -127,6 +132,8 @@ class ConfigDictField(DictField): Default is `True`. dictCheck : `~collections.abc.Callable` or `None`, optional Callable to check a dict. + keyCheck : `~collections.abc.Callable` or `None`, optional + Callable to check a key. itemCheck : `~collections.abc.Callable` or `None`, optional Callable to check an item. deprecated : None or `str`, optional @@ -140,7 +147,8 @@ class ConfigDictField(DictField): - ``keytype`` or ``itemtype`` arguments are not supported types (members of `ConfigDictField.supportedTypes`. - - ``dictCheck`` or ``itemCheck`` is not a callable function. + - ``dictCheck``, ``keyCheck`` or ``itemCheck`` is not a callable + function. See Also -------- @@ -172,6 +180,7 @@ def __init__( default=None, optional=False, dictCheck=None, + keyCheck=None, itemCheck=None, deprecated=None, ): @@ -191,12 +200,15 @@ def __init__( raise ValueError(f"'itemtype' {_typeStr(itemtype)} is not a supported type") if dictCheck is not None and not hasattr(dictCheck, "__call__"): raise ValueError("'dictCheck' must be callable") + if keyCheck is not None and not hasattr(keyCheck, "__call__"): + raise ValueError("'keyCheck' must be callable") if itemCheck is not None and not hasattr(itemCheck, "__call__"): raise ValueError("'itemCheck' must be callable") self.keytype = keytype self.itemtype = itemtype self.dictCheck = dictCheck + self.keyCheck = keyCheck self.itemCheck = itemCheck def rename(self, instance): @@ -210,6 +222,9 @@ def validate(self, instance): value = self.__get__(instance) if value is not None: for k in value: + if self.keyCheck is not None and not self.keyCheck(k): + msg = f"Key {k!r} is not a valid key" + raise FieldValidationError(self, instance, msg) item = value[k] item.validate() if self.itemCheck is not None and not self.itemCheck(item):