interpreterbase: Add evolve to KwargInfo

This works just like OptionKey.evolve, pass new keyword arguments to
override old ones, otherwise the original versions are copied to the new
one.
pull/8884/head
Dylan Baker 3 years ago
parent a024f432dd
commit dd296f321b
  1. 41
      mesonbuild/interpreterbase/decorators.py
  2. 12
      run_unittests.py

@ -272,6 +272,11 @@ class ContainerTypeInfo:
_T = T.TypeVar('_T')
class _NULL_T:
"""Special null type for evolution, this is an implementation detail."""
_NULL = _NULL_T()
class KwargInfo(T.Generic[_T]):
@ -329,6 +334,42 @@ class KwargInfo(T.Generic[_T]):
self.convertor = convertor
self.not_set_warning = not_set_warning
def evolve(self, *,
required: T.Union[bool, _NULL_T] = _NULL,
listify: T.Union[bool, _NULL_T] = _NULL,
default: T.Union[_T, None, _NULL_T] = _NULL,
since: T.Union[str, None, _NULL_T] = _NULL,
since_values: T.Union[T.Dict[str, str], None, _NULL_T] = _NULL,
deprecated: T.Union[str, None, _NULL_T] = _NULL,
deprecated_values: T.Union[T.Dict[str, str], None, _NULL_T] = _NULL,
validator: T.Union[T.Callable[[_T], T.Optional[str]], None, _NULL_T] = _NULL,
convertor: T.Union[T.Callable[[_T], TYPE_var], None, _NULL_T] = _NULL) -> 'KwargInfo':
"""Create a shallow copy of this KwargInfo, with modifications.
This allows us to create a new copy of a KwargInfo with modifications.
This allows us to use a shared kwarg that implements complex logic, but
has slight differences in usage, such as being added to different
functions in different versions of Meson.
The use the _NULL special value here allows us to pass None, which has
meaning in many of these cases. _NULL itself is never stored, always
being replaced by either the copy in self, or the provided new version.
"""
return type(self)(
self.name,
self.types,
listify=listify if not isinstance(listify, _NULL_T) else self.listify,
required=required if not isinstance(required, _NULL_T) else self.required,
default=default if not isinstance(default, _NULL_T) else self.default,
since=since if not isinstance(since, _NULL_T) else self.since,
since_values=since_values if not isinstance(since_values, _NULL_T) else self.since_values,
deprecated=deprecated if not isinstance(deprecated, _NULL_T) else self.deprecated,
deprecated_values=deprecated_values if not isinstance(deprecated_values, _NULL_T) else self.deprecated_values,
validator=validator if not isinstance(validator, _NULL_T) else self.validator,
convertor=convertor if not isinstance(convertor, _NULL_T) else self.convertor,
)
def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
"""Decorator for type checking keyword arguments.

@ -1698,6 +1698,18 @@ class InternalTests(unittest.TestCase):
_(None, mock.Mock(subproject=''), [], {'mode': 'since'})
self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "mode" value "since".*""")
def test_typed_kwarg_evolve(self) -> None:
k = KwargInfo('foo', str, required=True, default='foo')
v = k.evolve(default='bar')
self.assertEqual(k.name, 'foo')
self.assertEqual(k.name, v.name)
self.assertEqual(k.types, str)
self.assertEqual(k.types, v.types)
self.assertEqual(k.required, True)
self.assertEqual(k.required, v.required)
self.assertEqual(k.default, 'foo')
self.assertEqual(v.default, 'bar')
@unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release')
class DataTests(unittest.TestCase):

Loading…
Cancel
Save