From 6ab78b5979afb3347eca0da1a8000aee3a443cb9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 4 Jun 2021 10:52:15 -0700 Subject: intperperterbase: Add a convertor keyword argument This is meant to allow simple type conversions to happen before the interpreter function is called. This should simplify some cases like the "native" keyword arugment that are booleans in the Meson DSL, but an Enum in the implementation --- mesonbuild/interpreterbase.py | 11 ++++++++++- run_unittests.py | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 136eb6e28..0273c36b6 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -428,6 +428,10 @@ class KwargInfo(T.Generic[_T]): 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 + :param convertor: A callable that converts the raw input value into a + different type. This is intended for cases such as the meson DSL using a + string, but the implementation using an Enum. This should not do + validation, just converstion. """ def __init__(self, name: str, types: T.Union[T.Type[_T], T.Tuple[T.Type[_T], ...], ContainerTypeInfo], @@ -435,7 +439,8 @@ class KwargInfo(T.Generic[_T]): default: T.Optional[_T] = None, since: T.Optional[str] = None, deprecated: T.Optional[str] = None, - validator: T.Optional[T.Callable[[_T], T.Optional[str]]] = None): + validator: T.Optional[T.Callable[[_T], T.Optional[str]]] = None, + convertor: T.Optional[T.Callable[[_T], TYPE_nvar]] = None): self.name = name self.types = types self.required = required @@ -444,6 +449,7 @@ class KwargInfo(T.Generic[_T]): self.since = since self.deprecated = deprecated self.validator = validator + self.convertor = convertor def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]: @@ -517,6 +523,9 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]: else: kwargs[info.name] = info.default + if info.convertor: + kwargs[info.name] = info.convertor(kwargs[info.name]) + return f(*wrapped_args, **wrapped_kwargs) return T.cast(TV_func, wrapper) return inner diff --git a/run_unittests.py b/run_unittests.py index 9f66d9c18..21bb30e4d 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1644,6 +1644,16 @@ class InternalTests(unittest.TestCase): _(None, mock.Mock(), tuple(), dict(input='bar')) self.assertEqual(str(cm.exception), "testfunc keyword argument \"input\" invalid!") + def test_typed_kwarg_convertor(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('native', bool, convertor=lambda n: MachineChoice.BUILD if n else MachineChoice.HOST) + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, MachineChoice]) -> None: + assert isinstance(kwargs['native'], MachineChoice) + + _(None, mock.Mock(), tuple(), dict(native=True)) + @unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release') class DataTests(unittest.TestCase): -- cgit v1.2.3