diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2021-06-01 15:42:07 -0400 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2021-06-01 20:01:20 -0400 |
commit | 16c3f033943206b4b90532a9656f64678e87a7ec (patch) | |
tree | df2087377105deb1dcbe0a337befa913395da892 | |
parent | 6aef800ba83a4dd469c354900b6e537777d3080c (diff) | |
download | meson-16c3f033943206b4b90532a9656f64678e87a7ec.zip meson-16c3f033943206b4b90532a9656f64678e87a7ec.tar.gz meson-16c3f033943206b4b90532a9656f64678e87a7ec.tar.bz2 |
typed_kwargs: Add since and deprecated annotations
-rw-r--r-- | mesonbuild/interpreterbase.py | 19 | ||||
-rwxr-xr-x | run_unittests.py | 32 |
2 files changed, 47 insertions, 4 deletions
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index ed0f9fa..4318023 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -420,15 +420,20 @@ class KwargInfo(T.Generic[_T]): checked. This is useful for cases where the Meson DSL allows a scalar or a container, but internally we only want to work with containers :param default: A default value to use if this isn't set. defaults to None + :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 """ 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): + required: bool = False, listify: bool = False, default: T.Optional[_T] = None, + since: T.Optional[str] = None, deprecated: T.Optional[str] = None): self.name = name self.types = types self.required = required self.listify = listify self.default = default + self.since = since + self.deprecated = deprecated def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]: @@ -447,7 +452,7 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]: @wraps(f) def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: - kwargs = _get_callee_args(wrapped_args)[3] + kwargs, subproject = _get_callee_args(wrapped_args, want_subproject=True)[3:5] all_names = {t.name for t in types} unknowns = set(kwargs).difference(all_names) @@ -460,8 +465,14 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]: del kwargs[u] for info in types: - if info.name in kwargs: - value = kwargs[info.name] + value = kwargs.get(info.name) + if value is not None: + if info.since: + feature_name = info.name + ' arg in ' + name + FeatureNew.single_use(feature_name, info.since, subproject) + if info.deprecated: + feature_name = info.name + ' arg in ' + name + FeatureDeprecated.single_use(feature_name, info.deprecated, subproject) if info.listify: kwargs[info.name] = value = mesonlib.listify(value) if isinstance(info.types, ContainerTypeInfo): diff --git a/run_unittests.py b/run_unittests.py index 1c6d491..3a98368 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1586,6 +1586,38 @@ class InternalTests(unittest.TestCase): _(None, mock.Mock(), [], {'input': ['a']}) self.assertEqual(str(cm.exception), "testfunc keyword argument \"input\" container should be of even length, but is not") + def test_typed_kwarg_since(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, since='1.0', deprecated='2.0') + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertIsInstance(kwargs['input'], str) + self.assertEqual(kwargs['input'], 'foo') + + # With Meson 0.1 it should trigger the "introduced" warning but not the "deprecated" warning + mesonbuild.mesonlib.project_meson_versions[''] = '0.1' + sys.stdout = io.StringIO() + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(sys.stdout.getvalue(), r'WARNING:.*introduced.*input arg in testfunc') + self.assertNotRegex(sys.stdout.getvalue(), r'WARNING:.*deprecated.*input arg in testfunc') + + # With Meson 1.5 it shouldn't trigger any warning + mesonbuild.mesonlib.project_meson_versions[''] = '1.5' + sys.stdout = io.StringIO() + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertNotRegex(sys.stdout.getvalue(), r'WARNING:.*') + self.assertNotRegex(sys.stdout.getvalue(), r'WARNING:.*') + + # With Meson 2.0 it should trigger the "deprecated" warning but not the "introduced" warning + mesonbuild.mesonlib.project_meson_versions[''] = '2.0' + sys.stdout = io.StringIO() + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(sys.stdout.getvalue(), r'WARNING:.*deprecated.*input arg in testfunc') + self.assertNotRegex(sys.stdout.getvalue(), r'WARNING:.*introduced.*input arg in testfunc') + + sys.stdout = sys.__stdout__ + @unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release') class DataTests(unittest.TestCase): |