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
pull/8853/head
Dylan Baker 4 years ago committed by Daniel Mensinger
parent fb385728df
commit 6ab78b5979
  1. 11
      mesonbuild/interpreterbase.py
  2. 10
      run_unittests.py

@ -428,6 +428,10 @@ class KwargInfo(T.Generic[_T]):
intended for cases where a string is expected, but only a few specific 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 values are accepted. Must return None if the input is valid, or a
message if the input is invalid 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], 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, default: T.Optional[_T] = None,
since: T.Optional[str] = None, since: T.Optional[str] = None,
deprecated: 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.name = name
self.types = types self.types = types
self.required = required self.required = required
@ -444,6 +449,7 @@ class KwargInfo(T.Generic[_T]):
self.since = since self.since = since
self.deprecated = deprecated self.deprecated = deprecated
self.validator = validator self.validator = validator
self.convertor = convertor
def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]: 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: else:
kwargs[info.name] = info.default kwargs[info.name] = info.default
if info.convertor:
kwargs[info.name] = info.convertor(kwargs[info.name])
return f(*wrapped_args, **wrapped_kwargs) return f(*wrapped_args, **wrapped_kwargs)
return T.cast(TV_func, wrapper) return T.cast(TV_func, wrapper)
return inner return inner

@ -1644,6 +1644,16 @@ class InternalTests(unittest.TestCase):
_(None, mock.Mock(), tuple(), dict(input='bar')) _(None, mock.Mock(), tuple(), dict(input='bar'))
self.assertEqual(str(cm.exception), "testfunc keyword argument \"input\" invalid!") 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') @unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release')
class DataTests(unittest.TestCase): class DataTests(unittest.TestCase):

Loading…
Cancel
Save