aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreterbase.py
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2021-06-02 15:45:15 -0700
committerDaniel Mensinger <daniel@mensinger-ka.de>2021-06-08 11:00:55 +0200
commitfb385728df5d14c929420c6fd0fb2958f274761d (patch)
tree349e686a476fec3406520b69a335f4db327bad83 /mesonbuild/interpreterbase.py
parent5d81392c67231fa68a67bdacf2a2764ef3e76da5 (diff)
downloadmeson-fb385728df5d14c929420c6fd0fb2958f274761d.zip
meson-fb385728df5d14c929420c6fd0fb2958f274761d.tar.gz
meson-fb385728df5d14c929420c6fd0fb2958f274761d.tar.bz2
interpreterbase: Add validator keyword argument to typed_kwargs
This attribute is a callable that returns a string if the value is invalid, otherwise None. This intended for cases like the `install_*` function's `install_mode` paramater, which is either an int or the string "preserve", which allows us to do nice things like: ```python class Kwargs(TypedDict): install_mode: T.Union[int, T.Literal['preserve']] @typed_kwargs( 'foo', KwargInfo('install_mode', ..., validator=lambda x: None if isinstance(x, int) or x == 'preserve' else 'must be the literal "preserve"), ) def install_data(self, node, args, kwargs: 'Kwargs'): ... ``` In this case mypy *knows* that the string is preserve, as do we, and we can simply do tests like: ```python if kwargs['install_mode'] == 'preserve': ... else: # this is an int ```
Diffstat (limited to 'mesonbuild/interpreterbase.py')
-rw-r--r--mesonbuild/interpreterbase.py14
1 files changed, 13 insertions, 1 deletions
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 6e31202..136eb6e 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -424,12 +424,18 @@ class KwargInfo(T.Generic[_T]):
itself contain mutable types, typed_kwargs will copy the default
:param since: Meson version in which this argument has been added. defaults to None
:param deprecated: Meson version in which this argument has been deprecated. defaults to None
+ :param validator: A callable that does additional validation. This is mainly
+ intended for cases where a string is expected, but only a few specific
+ values are accepted. Must return None if the input is valid, or a
+ message if the input is invalid
"""
def __init__(self, name: str, types: T.Union[T.Type[_T], T.Tuple[T.Type[_T], ...], ContainerTypeInfo],
*, required: bool = False, listify: bool = False,
default: T.Optional[_T] = None,
- since: T.Optional[str] = None, deprecated: T.Optional[str] = None):
+ since: T.Optional[str] = None,
+ deprecated: T.Optional[str] = None,
+ validator: T.Optional[T.Callable[[_T], T.Optional[str]]] = None):
self.name = name
self.types = types
self.required = required
@@ -437,6 +443,7 @@ class KwargInfo(T.Generic[_T]):
self.default = default
self.since = since
self.deprecated = deprecated
+ self.validator = validator
def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
@@ -492,6 +499,11 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
else:
shouldbe = f'"{info.types.__name__}"'
raise InvalidArguments(f'{name} keyword argument "{info.name}"" was of type "{type(value).__name__}" but should have been {shouldbe}')
+
+ if info.validator is not None:
+ msg = info.validator(value)
+ if msg is not None:
+ raise InvalidArguments(f'{name} keyword argument "{info.name}" {msg}')
elif info.required:
raise InvalidArguments(f'{name} is missing required keyword argument "{info.name}"')
else: