Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
471facd
interpreter: Replace last uses of Feature*Kwargs
dcbaker Jul 13, 2026
57b44b9
interpreterbase/decorators: pull some helpers out of typed_kwargs
dcbaker Jul 21, 2026
85201f6
interpreterbase/decorators: share code between pos and kwarg checking
dcbaker Jul 21, 2026
7e4308f
decorators: share error formatting code between pos and kw arg checking
dcbaker Jul 22, 2026
407cd7a
decorators: normalize quoting of types in errors
dcbaker Jul 22, 2026
4b3dd8b
decorators: make the quoting of types fully standard
dcbaker Jul 22, 2026
263c844
decorators: consistently quote the name of functions in errors
dcbaker Jul 22, 2026
0a9ca80
decorators: Convert KwargInfo to a dataclass
dcbaker Jul 22, 2026
252fd63
decorators: use some `TypeAlias`es to make further changes easier
dcbaker Jul 22, 2026
6ad1137
decorators: allow tuples of types in KWargInfo since_values and depre…
dcbaker Jul 22, 2026
ed0ad23
modules/cmake: Use KwargInfo since_values instead of open coding
dcbaker Jul 22, 2026
a4c81a7
modules/qt: Use KWargInfo.since_values
dcbaker Jul 22, 2026
86248c5
modules/qt: Use typed_pos_args for qt.preprocess
dcbaker Jul 22, 2026
0ded72e
modules/sourceset: Use KwargInfo.since_values for new types
dcbaker Jul 22, 2026
08187b3
interpreterobjects: move pkgconfig_define FeatureNew to KWargInfo
dcbaker Jul 22, 2026
6f71961
interpreter: Use KWargInfo for some test arguments
dcbaker Jul 22, 2026
d6ea643
interpreter/type_checking: consistently quote in_set_validator errors
dcbaker Jul 23, 2026
6821d80
interpreter/type_checking: quote unknown langauge validator error
dcbaker Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions mesonbuild/interpreter/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from ..compilers import SUFFIX_TO_LANG, RunResult
from ..compilers.compilers import CompileCheckMode
from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs,
FeatureNew, FeatureNewKwargs, disablerIfNotFound,
FeatureNew, disablerIfNotFound,
InterpreterException, InterpreterObject)
from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args
from ..options import OptionKey
Expand Down Expand Up @@ -881,12 +881,18 @@ def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwa
return self.compiler.get_argument_syntax()

@FeatureNew('compiler.preprocess', '0.64.0')
@FeatureNewKwargs('compiler.preprocess', '1.3.2', ['compile_args'], extra_message='compile_args were ignored before this version')
@typed_pos_args('compiler.preprocess', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), min_varargs=1)
@typed_kwargs(
'compiler.preprocess',
KwargInfo('output', str, default='@PLAINNAME@.i'),
KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]),
KwargInfo(
'compile_args',
ContainerTypeInfo(list, str),
listify=True,
default=[],
since='1.3.2',
since_message='compile_args were ignored before this version',
),
_INCLUDE_DIRECTORIES_KW,
_DEPENDENCIES_KW.evolve(since='1.1.0'),
_DEPENDS_KW.evolve(since='1.4.0'),
Expand Down
8 changes: 1 addition & 7 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from .decorators import apply_machine_map
from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from ..interpreterbase import Disabler, disablerIfNotFound
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken
from ..interpreterbase import ObjectHolder, ContextManagerObject, DefaultObject
from ..interpreterbase import stringifyUserArguments, Feature, FeatureValue
from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule, __path__ as modules_path
Expand Down Expand Up @@ -2037,7 +2037,6 @@ def func_jar(self, node: mparser.BaseNode,
kwargs: kwtypes.Jar) -> build.Jar:
return self.build_target(node, T.cast('tuple[str, SourcesVarargsType]', args), kwargs, build.Jar)

@FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options'])
@typed_pos_args('build_target', str, varargs=SOURCES_VARARGS)
@typed_kwargs('build_target', *BUILD_TARGET_KWS)
def func_build_target(self, node: mparser.BaseNode,
Expand Down Expand Up @@ -2395,9 +2394,6 @@ def make_test(self, node: mparser.BaseNode,
if isinstance(exe, (build.Executable, build.CustomTarget, build.CustomTargetIndex)):
kwargs.setdefault('depends', []).append(exe.get_target())

if kwargs['timeout'] <= 0:
FeatureNew.single_use('test() timeout <= 0', '0.57.0', self.subproject, location=node)

expected_fail = False
if kwargs['should_fail'] is not None and kwargs['expected_fail'] is not None:
raise InvalidArguments("Tried to use both 'should_fail' and 'expected_fail'")
Expand Down Expand Up @@ -2435,8 +2431,6 @@ def add_test(self, node: mparser.BaseNode,
kwargs: kwtypes.FuncTest | kwtypes.FuncBenchmark, is_base_test: bool) -> None:
if isinstance(args[1], (build.CustomTarget, build.CustomTargetIndex)):
FeatureNew.single_use('test with CustomTarget as command', '1.4.0', self.subproject)
if any(isinstance(i, ExternalProgram) for i in kwargs['args']):
FeatureNew.single_use('test with program in args', '1.6.0', self.subproject)

t: Test = self.make_test(node, args, kwargs)
if is_base_test:
Expand Down
7 changes: 0 additions & 7 deletions mesonbuild/interpreter/interpreterobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,6 @@ def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConf
from ..dependencies.pkgconfig import PkgConfigDependency
if not isinstance(self.held_object, PkgConfigDependency):
raise InvalidArguments(f'{self.held_object.get_name()!r} is not a pkgconfig dependency')
if kwargs['define_variable'] and len(kwargs['define_variable']) > 1:
FeatureNew.single_use('dependency.get_pkgconfig_variable keyword argument "define_variable" with more than one pair',
'1.3.0', self.subproject, location=self.current_node)
return self.held_object.get_variable(
pkgconfig=args[0],
default_value=kwargs['default'],
Expand Down Expand Up @@ -584,10 +581,6 @@ def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.Depend
default_varname = args[0]
if default_varname is not None:
FeatureNew('Positional argument to dependency.get_variable()', '0.58.0').use(self.subproject, self.current_node)
if kwargs['pkgconfig_define'] and len(kwargs['pkgconfig_define']) > 1:
FeatureNew.single_use('dependency.get_variable keyword argument "pkgconfig_define" with more than one pair',
'1.3.0', self.subproject, 'In previous versions, this silently returned a malformed value.',
self.current_node)
return self.held_object.get_variable(
cmake=kwargs['cmake'] or default_varname,
pkgconfig=kwargs['pkgconfig'] or default_varname,
Expand Down
42 changes: 34 additions & 8 deletions mesonbuild/interpreter/type_checking.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ..options import OptionKey
from ..dependencies import Dependency, DependencyMethods, InternalDependency
from ..interpreterbase import Feature
from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo, FeatureBroken, FeatureDeprecated
from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo, FeatureBroken, FeatureDeprecated, FeatureNew
from ..mesonlib import (File, FileMode, MachineChoice, has_path_sep, listify, stringlistify,
EnvironmentVariables)
from ..programs import Program, ExternalProgram
Expand All @@ -37,12 +37,18 @@
SourcesVarargsType = T.List[T.Union[str, File, GeneratedTypes, StructuredSources, ExtractedObjects, BuildTarget]]


def _quote(x: T.Iterable[str]) -> T.Iterable[str]:
if isinstance(x, str):
return f'"{x}"'
return [f'"{c}"' for c in x]


def in_set_validator(choices: T.Set[str]) -> T.Callable[[str], T.Optional[str]]:
"""Check that the choice given was one of the given set."""

def inner(check: str) -> T.Optional[str]:
if check not in choices:
return f"must be one of {', '.join(sorted(choices))}, not {check}"
return f"must be one of {', '.join(_quote(sorted(choices)))}, not \"{check}\""
return None

return inner
Expand All @@ -55,7 +61,7 @@ def _language_validator(l: T.List[str]) -> T.Optional[str]:
"""
diff = {a.lower() for a in l}.difference(compilers.all_languages)
if diff:
return f'unknown languages: {", ".join(diff)}'
return f'unknown languages: {", ".join(_quote(diff))}'
return None


Expand Down Expand Up @@ -524,11 +530,18 @@ def suite_convertor(suite: T.List[str]) -> T.List[str]:
return ['']
return suite


def _test_timeout_feature_validator(value: int) -> T.Iterable[FeatureCheckBase]:
if value <= 0:
yield FeatureNew('test timeout <= 0', '0.57.0')


TEST_KWS_NO_ARGS: T.List[KwargInfo] = [
KwargInfo('should_fail', (bool, NoneType), deprecated='1.11.0', deprecated_message='Use expected_fail instead of should_fail'),
KwargInfo('expected_fail', (bool, NoneType), since='1.11.0'),
KwargInfo('expected_exitcode', (int, NoneType), since='1.11.0'),
KwargInfo('timeout', int, default=30),
KwargInfo('timeout', int, default=30,
feature_validator=_test_timeout_feature_validator),
KwargInfo('workdir', (str, NoneType), default=None,
validator=lambda x: 'must be an absolute path' if not os.path.isabs(x) else None),
KwargInfo('protocol', str,
Expand All @@ -544,8 +557,13 @@ def suite_convertor(suite: T.List[str]) -> T.List[str]:
]

TEST_KWS: T.List[KwargInfo] = TEST_KWS_NO_ARGS + [
KwargInfo('args', ContainerTypeInfo(list, (str, File, BuildTarget, CustomTarget, CustomTargetIndex, Program)),
listify=True, default=[]),
KwargInfo(
'args',
ContainerTypeInfo(list, (str, File, BuildTarget, CustomTarget, CustomTargetIndex, Program)),
listify=True,
default=[],
since_values={ExternalProgram: '1.6.0'},
),
]

# Cannot have a default value because we need to check that rust_crate_type and
Expand Down Expand Up @@ -641,7 +659,7 @@ def _bt_install_dir_deprecated(args: T.List[T.Union[str, bool]]) -> T.Iterator[F

# Applies to all build_target like classes
_ALL_TARGET_KWS: T.List[KwargInfo] = [
OVERRIDE_OPTIONS_KW,
OVERRIDE_OPTIONS_KW.evolve(since='0.40.0'),
KwargInfo('build_by_default', bool, default=True, since='0.38.0'),
DEPENDENCIES_KW,
KwargInfo(
Expand Down Expand Up @@ -784,6 +802,7 @@ def _pch_convertor(args: T.List[str]) -> T.Optional[T.Tuple[str, T.Optional[str]
INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'),
LINK_ARGS_KW,
LINK_WHOLE_KW.evolve(
since='0.40.0',
as_default=[('', ('1.11.0', "Replace an empty string with an empty array: `link_whole : ''` -> `link_whole : []`"))],
),
_NAME_PREFIX_KW,
Expand Down Expand Up @@ -1068,11 +1087,18 @@ def _pkgconfig_define_convertor(x: T.List[str]) -> PkgConfigDefineType:
return tuple(zip(keys, vals))
return None

PKGCONFIG_DEFINE_KW: KwargInfo = KwargInfo(
def _pkgconfig_define_feature_validator(x: list[str]) -> T.Iterable[FeatureCheckBase]:
if len(x) > 1:
yield FeatureNew(
'dependency.get_variable keyword argument "pkgconfig_define" with more than one pair',
'1.3.0', 'In previous versions, this silently returned a malformed value.')

PKGCONFIG_DEFINE_KW: KwargInfo[list[str]] = KwargInfo(
'pkgconfig_define',
ContainerTypeInfo(list, str, pairs=True),
default=[],
convertor=_pkgconfig_define_convertor,
feature_validator=_pkgconfig_define_feature_validator,
)

INCLUDE_TYPE = KwargInfo(
Expand Down
4 changes: 0 additions & 4 deletions mesonbuild/interpreterbase/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
'FeatureNew',
'FeatureDeprecated',
'FeatureBroken',
'FeatureNewKwargs',
'FeatureDeprecatedKwargs',

'InterpreterBase',

Expand Down Expand Up @@ -104,8 +102,6 @@
FeatureNew,
FeatureDeprecated,
FeatureBroken,
FeatureNewKwargs,
FeatureDeprecatedKwargs,
)

from .exceptions import (
Expand Down
Loading
Loading