From c1aeb2f7e4ef81a046ca28d5dad89bb8fdeefafd Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 14 Jun 2022 19:25:33 -0400 Subject: [PATCH] typed_kwargs: support dict/list as "new since" types Given a kwarg value that is itself a dict/list, we would only check if the since_values was present within that container. If the since_values is itself the dict or list type, then we aren't looking for recursive structures, we just want to know when the function began to accept that type. This is relevant in cases where a function accepted a dict, and at one point began accepting a list (of strings in the form 'key=value'), or vice versa. --- mesonbuild/interpreterbase/decorators.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index a98e9990d..5dd8b8982 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -505,18 +505,24 @@ 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: - def emit_feature_change(values: T.Dict[str, T.Union[str, T.Tuple[str, str]]], feature: T.Union[T.Type['FeatureDeprecated'], T.Type['FeatureNew']]) -> None: + def emit_feature_change(values: T.Dict[_T, T.Union[str, T.Tuple[str, str]]], feature: T.Union[T.Type['FeatureDeprecated'], T.Type['FeatureNew']]) -> None: for n, version in values.items(): - if isinstance(value, (dict, list)): + warn = False + if isinstance(version, tuple): + version, msg = version + else: + msg = None + + if n in {dict, list}: + assert isinstance(n, type), 'for mypy' + if isinstance(value, n): + feature.single_use(f'"{name}" keyword argument "{info.name}" of type {n.__name__}', version, subproject, msg, location=node) + elif isinstance(value, (dict, list)): warn = n in value else: warn = n == value if warn: - if isinstance(version, tuple): - version, msg = version - else: - msg = None feature.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject, msg, location=node) node, _, _kwargs, subproject = get_callee_args(wrapped_args)