Feature kwargs decorator: automatically report the nodes which trigger an issue

pull/9488/head
Eli Schwartz 3 years ago
parent 7a033c7887
commit 8dbb0ee476
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 20
      mesonbuild/interpreterbase/decorators.py
  2. 2
      test cases/warning/1 version for string div/test.json
  3. 4
      unittests/allplatformstests.py

@ -458,7 +458,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, subproject = get_callee_args(wrapped_args)[2:4]
node, _, _kwargs, subproject = get_callee_args(wrapped_args)
# Cast here, as the convertor function may place something other than a TYPE_var in the kwargs
kwargs = T.cast(T.Dict[str, object], _kwargs)
@ -492,10 +492,10 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
if value is not None:
if info.since:
feature_name = info.name + ' arg in ' + name
FeatureNew.single_use(feature_name, info.since, subproject)
FeatureNew.single_use(feature_name, info.since, subproject, location=node)
if info.deprecated:
feature_name = info.name + ' arg in ' + name
FeatureDeprecated.single_use(feature_name, info.deprecated, subproject)
FeatureDeprecated.single_use(feature_name, info.deprecated, subproject, location=node)
if info.listify:
kwargs[info.name] = value = mesonlib.listify(value)
if not check_value_type(value):
@ -516,7 +516,7 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
warn = n == value
if warn:
FeatureDeprecated.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject)
FeatureDeprecated.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject, location=node)
if info.since_values is not None:
for n, version in info.since_values.items():
@ -526,7 +526,7 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
warn = n == value
if warn:
FeatureNew.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject)
FeatureNew.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject, location=node)
elif info.required:
raise InvalidArguments(f'{name} is missing required keyword argument "{info.name}"')
@ -615,9 +615,10 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
def __call__(self, f: TV_func) -> TV_func:
@wraps(f)
def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
subproject = get_callee_args(wrapped_args)[3]
node, _, _, subproject = get_callee_args(wrapped_args)
if subproject is None:
raise AssertionError(f'{wrapped_args!r}')
self.location = node
self.use(subproject)
return f(*wrapped_args, **wrapped_kwargs)
return T.cast(TV_func, wrapped)
@ -693,16 +694,17 @@ class FeatureCheckKwargsBase(metaclass=abc.ABCMeta):
pass
def __init__(self, feature_name: str, feature_version: str,
kwargs: T.List[str], extra_message: T.Optional[str] = None):
kwargs: T.List[str], extra_message: T.Optional[str] = None, location: T.Optional['mparser.BaseNode'] = None):
self.feature_name = feature_name
self.feature_version = feature_version
self.kwargs = kwargs
self.extra_message = extra_message
self.location = location
def __call__(self, f: TV_func) -> TV_func:
@wraps(f)
def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
kwargs, subproject = get_callee_args(wrapped_args)[2:4]
node, _, kwargs, subproject = get_callee_args(wrapped_args)
if subproject is None:
raise AssertionError(f'{wrapped_args!r}')
for arg in self.kwargs:
@ -710,7 +712,7 @@ class FeatureCheckKwargsBase(metaclass=abc.ABCMeta):
continue
name = arg + ' arg in ' + self.feature_name
self.feature_check_class.single_use(
name, self.feature_version, subproject, self.extra_message)
name, self.feature_version, subproject, self.extra_message, node)
return f(*wrapped_args, **wrapped_kwargs)
return T.cast(TV_func, wrapped)

@ -2,7 +2,7 @@
"stdout": [
{
"comment": "literal '/' appears in output, irrespective of os.path.sep, as that's the operator",
"line": "WARNING: Project targeting '>=0.48.0' but tried to use feature introduced in '0.49.0': / with string arguments."
"line": "test cases/warning/1 version for string div/meson.build:3: WARNING: Project targeting '>=0.48.0' but tried to use feature introduced in '0.49.0': / with string arguments."
}
]
}

@ -2241,8 +2241,8 @@ class AllPlatformTests(BasePlatformTests):
# Parent project warns correctly
self.assertRegex(out, "WARNING: Project targeting '>=0.45'.*'0.47.0': dict")
# Subprojects warn correctly
self.assertRegex(out, r"\| WARNING: Project targeting '>=0.40'.*'0.44.0': disabler")
self.assertRegex(out, r"\| WARNING: Project targeting '!=0.40'.*'0.44.0': disabler")
self.assertRegex(out, r"foo\| .*WARNING: Project targeting '>=0.40'.*'0.44.0': disabler")
self.assertRegex(out, r"baz\| .*WARNING: Project targeting '!=0.40'.*'0.44.0': disabler")
# Subproject has a new-enough meson_version, no warning
self.assertNotRegex(out, "WARNING: Project targeting.*Python")
# Ensure a summary is printed in the subproject and the outer project

Loading…
Cancel
Save