diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 0565de316..d74157fb1 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -103,8 +103,7 @@ class TestSerialisation: self.protocol = protocol class OptionProxy: - def __init__(self, name, value): - self.name = name + def __init__(self, value): self.value = value class OptionOverrideProxy: @@ -122,7 +121,7 @@ class OptionOverrideProxy: def _get_override(self, option_name, base_opt): if option_name in self.overrides: - return OptionProxy(base_opt.name, base_opt.validate_value(self.overrides[option_name])) + return OptionProxy(base_opt.validate_value(self.overrides[option_name])) return base_opt def get_backend_from_name(backend, build): diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 0cfcbc36a..5d78ba620 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -96,7 +96,7 @@ class ClangCCompiler(ClangCompiler, CCompiler): if version_compare(self.version, v): c_stds += ['c17'] g_stds += ['gnu17'] - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none'] + c_stds + g_stds, 'none')}) return opts @@ -130,7 +130,7 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler): def get_options(self): opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'], 'none')}) @@ -165,12 +165,12 @@ class GnuCCompiler(GnuCompiler, CCompiler): if version_compare(self.version, v): c_stds += ['c17', 'c18'] g_stds += ['gnu17', 'gnu18'] - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none'] + c_stds + g_stds, 'none')}) if self.compiler_type.is_windows_compiler: opts.update({ - 'c_winlibs': coredata.UserArrayOption('c_winlibs', 'Standard Win libraries to link against', + 'c_winlibs': coredata.UserArrayOption('Standard Win libraries to link against', gnu_winlibs), }) return opts @@ -204,7 +204,7 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): # It does support some various ISO standards and c/gnu 90, 9x, 1x in addition to those which GNU CC supports. def get_options(self): opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11', 'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11', 'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999'], @@ -239,7 +239,7 @@ class IntelCCompiler(IntelGnuLikeCompiler, CCompiler): g_stds = ['gnu89', 'gnu99'] if version_compare(self.version, '>=16.0.0'): c_stds += ['c11'] - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none'] + c_stds + g_stds, 'none')}) return opts @@ -258,8 +258,7 @@ class VisualStudioLikeCCompilerMixin: def get_options(self): opts = super().get_options() - opts.update({'c_winlibs': coredata.UserArrayOption('c_winlibs', - 'Windows libs to link against.', + opts.update({'c_winlibs': coredata.UserArrayOption('Windows libs to link against.', msvc_winlibs)}) return opts @@ -317,7 +316,7 @@ class ArmCCompiler(ArmCompiler, CCompiler): def get_options(self): opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none', 'c90', 'c99'], 'none')}) return opts @@ -340,7 +339,7 @@ class CcrxCCompiler(CcrxCompiler, CCompiler): def get_options(self): opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + opts.update({'c_std': coredata.UserComboOption('C language standard to use', ['none', 'c89', 'c99'], 'none')}) return opts diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index dacf75d22..3ad80fef7 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -381,35 +381,30 @@ msvc_debug_args = {False: [], ccrx_debug_args = {False: [], True: ['-debug']} -base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', True), - 'b_lto': coredata.UserBooleanOption('b_lto', 'Use link time optimization', False), - 'b_sanitize': coredata.UserComboOption('b_sanitize', - 'Code sanitizer to use', +base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', True), + 'b_lto': coredata.UserBooleanOption('Use link time optimization', False), + 'b_sanitize': coredata.UserComboOption('Code sanitizer to use', ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'], 'none'), - 'b_lundef': coredata.UserBooleanOption('b_lundef', 'Use -Wl,--no-undefined when linking', True), - 'b_asneeded': coredata.UserBooleanOption('b_asneeded', 'Use -Wl,--as-needed when linking', True), - 'b_pgo': coredata.UserComboOption('b_pgo', 'Use profile guided optimization', + 'b_lundef': coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True), + 'b_asneeded': coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True), + 'b_pgo': coredata.UserComboOption('Use profile guided optimization', ['off', 'generate', 'use'], 'off'), - 'b_coverage': coredata.UserBooleanOption('b_coverage', - 'Enable coverage tracking.', + 'b_coverage': coredata.UserBooleanOption('Enable coverage tracking.', False), - 'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output', + 'b_colorout': coredata.UserComboOption('Use colored output', ['auto', 'always', 'never'], 'always'), - 'b_ndebug': coredata.UserComboOption('b_ndebug', 'Disable asserts', + 'b_ndebug': coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'), - 'b_staticpic': coredata.UserBooleanOption('b_staticpic', - 'Build static libraries as position independent', + 'b_staticpic': coredata.UserBooleanOption('Build static libraries as position independent', True), - 'b_pie': coredata.UserBooleanOption('b_pie', - 'Build executables as position independent', + 'b_pie': coredata.UserBooleanOption('Build executables as position independent', False), - 'b_bitcode': coredata.UserBooleanOption('b_bitcode', - 'Generate and embed bitcode (only macOS and iOS)', + 'b_bitcode': coredata.UserBooleanOption('Generate and embed bitcode (only macOS and iOS)', False), - 'b_vscrt': coredata.UserComboOption('b_vscrt', 'VS run-time library type to use.', + 'b_vscrt': coredata.UserComboOption('VS run-time library type to use.', ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype'], 'from_buildtype'), } @@ -1044,11 +1039,9 @@ class Compiler: description = 'Extra arguments passed to the {}'.format(self.get_display_language()) opts.update({ self.language + '_args': coredata.UserArrayOption( - self.language + '_args', description + ' compiler', [], shlex_split=True, user_input=True, allow_dups=True), self.language + '_link_args': coredata.UserArrayOption( - self.language + '_link_args', description + ' linker', [], shlex_split=True, user_input=True, allow_dups=True), }) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 9fae22c66..253525a5c 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -158,11 +158,10 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler): def get_options(self): opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh', - 'C++ exception handling type.', + opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], 'default'), - 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', + 'cpp_std': coredata.UserComboOption('C++ language standard to use', ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'], 'none')}) @@ -201,7 +200,7 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): 'C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], 'default'), - 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', + 'cpp_std': coredata.UserComboOption('C++ language standard to use', ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17'], 'none')}) @@ -233,20 +232,18 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): def get_options(self): opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh', - 'C++ exception handling type.', + opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], 'default'), - 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', + 'cpp_std': coredata.UserComboOption('C++ language standard to use', ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'], 'none'), - 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl', - 'STL debug mode', + 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode', False)}) if self.compiler_type.is_windows_compiler: opts.update({ - 'cpp_winlibs': coredata.UserArrayOption('cpp_winlibs', 'Standard Win libraries to link against', + 'cpp_winlibs': coredata.UserArrayOption('Standard Win libraries to link against', gnu_winlibs), }) return opts @@ -288,16 +285,14 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): # It does not support c++/gnu++ 17 and 1z, but still does support 0x, 1y, and gnu++98. def get_options(self): opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh', - 'C++ exception handling type.', + opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], 'default'), - 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', + 'cpp_std': coredata.UserComboOption('C++ language standard to use', ['none', 'c++98', 'c++03', 'c++0x', 'c++11', 'c++14', 'c++1y', 'gnu++98', 'gnu++03', 'gnu++0x', 'gnu++11', 'gnu++14', 'gnu++1y'], 'none'), - 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl', - 'STL debug mode', + 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode', False)}) return opts @@ -338,15 +333,13 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): c_stds += ['c++17'] if version_compare(self.version, '>=17.0.0'): g_stds += ['gnu++14'] - opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh', - 'C++ exception handling type.', + opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], 'default'), - 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', + 'cpp_std': coredata.UserComboOption('C++ language standard to use', ['none'] + c_stds + g_stds, 'none'), - 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl', - 'STL debug mode', + 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode', False)}) return opts @@ -387,16 +380,13 @@ class VisualStudioLikeCPPCompilerMixin: return options['cpp_winlibs'].value[:] def _get_options_impl(self, opts, cpp_stds: typing.List[str]): - opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh', - 'C++ exception handling type.', + opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], 'default'), - 'cpp_std': coredata.UserComboOption('cpp_std', - 'C++ language standard to use', + 'cpp_std': coredata.UserComboOption('C++ language standard to use', cpp_stds, 'none'), - 'cpp_winlibs': coredata.UserArrayOption('cpp_winlibs', - 'Windows libs to link against.', + 'cpp_winlibs': coredata.UserArrayOption('Windows libs to link against.', msvc_winlibs)}) return opts @@ -513,7 +503,7 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler): def get_options(self): opts = CPPCompiler.get_options(self) - opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', + opts.update({'cpp_std': coredata.UserComboOption('C++ language standard to use', ['none', 'c++03', 'c++11'], 'none')}) return opts diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 183b333aa..34adad3e7 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -26,17 +26,19 @@ from .wrap import WrapMode import ast import argparse import configparser -from typing import Optional, Any, TypeVar, Generic, Type, List +from typing import Optional, Any, TypeVar, Generic, Type, List, Union version = '0.50.999' backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode'] default_yielding = False -class UserOption: - def __init__(self, name, description, choices, yielding): +# Can't bind this near the class method it seems, sadly. +_T = TypeVar('_T') + +class UserOption(Generic[_T]): + def __init__(self, description, choices, yielding): super().__init__() - self.name = name self.choices = choices self.description = description if yielding is None: @@ -51,31 +53,31 @@ class UserOption: # Check that the input is a valid value and return the # "cleaned" or "native" version. For example the Boolean # option could take the string "true" and return True. - def validate_value(self, value): + def validate_value(self, value: Any) -> _T: raise RuntimeError('Derived option class did not override validate_value.') def set_value(self, newvalue): self.value = self.validate_value(newvalue) -class UserStringOption(UserOption): - def __init__(self, name, description, value, choices=None, yielding=None): - super().__init__(name, description, choices, yielding) +class UserStringOption(UserOption[str]): + def __init__(self, description, value, choices=None, yielding=None): + super().__init__(description, choices, yielding) self.set_value(value) def validate_value(self, value): if not isinstance(value, str): - raise MesonException('Value "%s" for string option "%s" is not a string.' % (str(value), self.name)) + raise MesonException('Value "%s" for string option is not a string.' % str(value)) return value -class UserBooleanOption(UserOption): - def __init__(self, name, description, value, yielding=None): - super().__init__(name, description, [True, False], yielding) +class UserBooleanOption(UserOption[bool]): + def __init__(self, description, value, yielding=None): + super().__init__(description, [True, False], yielding) self.set_value(value) - def __bool__(self): + def __bool__(self) -> bool: return self.value - def validate_value(self, value): + def validate_value(self, value) -> bool: if isinstance(value, bool): return value if value.lower() == 'true': @@ -84,9 +86,9 @@ class UserBooleanOption(UserOption): return False raise MesonException('Value %s is not boolean (true or false).' % value) -class UserIntegerOption(UserOption): - def __init__(self, name, description, min_value, max_value, value, yielding=None): - super().__init__(name, description, [True, False], yielding) +class UserIntegerOption(UserOption[int]): + def __init__(self, description, min_value, max_value, value, yielding=None): + super().__init__(description, [True, False], yielding) self.min_value = min_value self.max_value = max_value self.set_value(value) @@ -97,7 +99,7 @@ class UserIntegerOption(UserOption): c.append('<=' + str(max_value)) self.choices = ', '.join(c) - def validate_value(self, value): + def validate_value(self, value) -> int: if isinstance(value, str): value = self.toint(value) if not isinstance(value, int): @@ -108,15 +110,15 @@ class UserIntegerOption(UserOption): raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value)) return value - def toint(self, valuestring): + def toint(self, valuestring) -> int: try: return int(valuestring) except ValueError: raise MesonException('Value string "%s" is not convertable to an integer.' % valuestring) -class UserUmaskOption(UserIntegerOption): - def __init__(self, name, description, value, yielding=None): - super().__init__(name, description, 0, 0o777, value, yielding) +class UserUmaskOption(UserIntegerOption, UserOption[Union[str, int]]): + def __init__(self, description, value, yielding=None): + super().__init__(description, 0, 0o777, value, yielding) self.choices = ['preserve', '0000-0777'] def printable_value(self): @@ -135,9 +137,9 @@ class UserUmaskOption(UserIntegerOption): except ValueError as e: raise MesonException('Invalid mode: {}'.format(e)) -class UserComboOption(UserOption): - def __init__(self, name, description, choices, value, yielding=None): - super().__init__(name, description, choices, yielding) +class UserComboOption(UserOption[str]): + def __init__(self, description, choices: List[str], value, yielding=None): + super().__init__(description, choices, yielding) if not isinstance(self.choices, list): raise MesonException('Combo choices must be an array.') for i in self.choices: @@ -148,17 +150,17 @@ class UserComboOption(UserOption): def validate_value(self, value): if value not in self.choices: optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices]) - raise MesonException('Value "%s" for combo option "%s" is not one of the choices. Possible choices are: %s.' % (value, self.name, optionsstring)) + raise MesonException('Value "%s" for combo option is not one of the choices. Possible choices are: %s.' % (value, optionsstring)) return value -class UserArrayOption(UserOption): - def __init__(self, name, description, value, shlex_split=False, user_input=False, allow_dups=False, **kwargs): - super().__init__(name, description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None)) +class UserArrayOption(UserOption[List[str]]): + def __init__(self, description, value, shlex_split=False, user_input=False, allow_dups=False, **kwargs): + super().__init__(description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None)) self.shlex_split = shlex_split self.allow_dups = allow_dups self.value = self.validate_value(value, user_input=user_input) - def validate_value(self, value, user_input=True): + def validate_value(self, value, user_input=True) -> List[str]: # User input is for options defined on the command line (via -D # options). Users can put their input in as a comma separated # string, but for defining options in meson_options.txt the format @@ -182,8 +184,8 @@ class UserArrayOption(UserOption): raise MesonException('"{0}" should be a string array, but it is not'.format(str(newvalue))) if not self.allow_dups and len(set(newvalue)) != len(newvalue): - msg = 'Duplicated values in array option "%s" is deprecated. ' \ - 'This will become a hard error in the future.' % (self.name) + msg = 'Duplicated values in array option is deprecated. ' \ + 'This will become a hard error in the future.' mlog.deprecation(msg) for i in newvalue: if not isinstance(i, str): @@ -199,8 +201,8 @@ class UserArrayOption(UserOption): class UserFeatureOption(UserComboOption): static_choices = ['enabled', 'disabled', 'auto'] - def __init__(self, name, description, value, yielding=None): - super().__init__(name, description, self.static_choices, value, yielding) + def __init__(self, description, value, yielding=None): + super().__init__(description, self.static_choices, value, yielding) def is_enabled(self): return self.value == 'enabled' @@ -334,22 +336,20 @@ class CoreData: # Create builtin options with default values self.builtins = {} for key, opt in builtin_options.items(): - self.builtins[key] = opt.init_option(key) + self.builtins[key] = opt.init_option() if opt.separate_cross: - self.builtins['cross_' + key] = opt.init_option(key) + self.builtins['cross_' + key] = opt.init_option() def init_backend_options(self, backend_name): if backend_name == 'ninja': self.backend_options['backend_max_links'] = \ UserIntegerOption( - 'backend_max_links', 'Maximum number of linker processes to run or 0 for no ' 'limit', 0, None, 0) elif backend_name.startswith('vs'): self.backend_options['backend_startup_project'] = \ UserStringOption( - 'backend_startup_project', 'Default project to execute in Visual Studio', '') @@ -433,7 +433,11 @@ class CoreData: for opts in self.get_all_options(): if option_name in opts: opt = opts[option_name] - return opt.validate_value(override_value) + try: + return opt.validate_value(override_value) + except MesonException as e: + raise type(e)(('Validation failed for option %s: ' % option_name) + str(e)) \ + .with_traceback(sys.exc_into()[2]) raise MesonException('Tried to validate unknown option %s.' % option_name) def get_external_args(self, for_machine: MachineChoice, lang): @@ -695,9 +699,9 @@ def parse_cmd_line_options(args): delattr(args, name) -_U = TypeVar('_U', bound=UserOption) +_U = TypeVar('_U', bound=UserOption[_T]) -class BuiltinOption(Generic[_U]): +class BuiltinOption(Generic[_T, _U]): """Class for a builtin option type. @@ -713,12 +717,12 @@ class BuiltinOption(Generic[_U]): self.yielding = yielding self.separate_cross = separate_cross - def init_option(self, name: str) -> _U: + def init_option(self) -> _U: """Create an instance of opt_type and return it.""" keywords = {'yielding': self.yielding, 'value': self.default} if self.choices: keywords['choices'] = self.choices - return self.opt_type(name, self.description, **keywords) + return self.opt_type(self.description, **keywords) def _argparse_action(self) -> Optional[str]: if self.default is True: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index fe12a7b58..1e8f97232 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -60,12 +60,12 @@ def stringifyUserArguments(args): class FeatureOptionHolder(InterpreterObject, ObjectHolder): - def __init__(self, env, option): + def __init__(self, env, name, option): InterpreterObject.__init__(self) ObjectHolder.__init__(self, option) if option.is_auto(): self.held_object = env.coredata.builtins['auto_features'] - self.name = option.name + self.name = name self.methods.update({'enabled': self.enabled_method, 'disabled': self.disabled_method, 'auto': self.auto_method, @@ -2536,7 +2536,7 @@ external dependencies (including libraries) must go to "dependencies".''') 'options of other subprojects.') opt = self.get_option_internal(optname) if isinstance(opt, coredata.UserFeatureOption): - return FeatureOptionHolder(self.environment, opt) + return FeatureOptionHolder(self.environment, optname, opt) elif isinstance(opt, coredata.UserOption): return opt.value return opt diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 8c8aa15a9..cf55b6f1d 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -26,7 +26,7 @@ from .ast import IntrospectionInterpreter, build_target_functions, AstConditionL from . import mlog from .backend import backends from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode -from typing import List, Optional +from typing import Dict, List, Optional import os import pathlib @@ -236,7 +236,7 @@ def list_buildoptions(coredata: cdata.CoreData) -> List[dict]: add_keys(optlist, test_options, 'test') return optlist -def add_keys(optlist, options, section): +def add_keys(optlist, options: Dict[str, cdata.UserOption], section): keys = list(options.keys()) keys.sort() for key in keys: diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index e64ed4eaf..8feb4f36e 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -14,6 +14,7 @@ import os, re import functools +import typing from . import mparser from . import coredata @@ -49,7 +50,7 @@ def permitted_kwargs(permitted): if bad: raise OptionException('Invalid kwargs for option "{}": "{}"'.format( name, ' '.join(bad))) - return func(name, description, kwargs) + return func(description, kwargs) return _inner return _wraps @@ -57,21 +58,20 @@ def permitted_kwargs(permitted): optname_regex = re.compile('[^a-zA-Z0-9_-]') @permitted_kwargs({'value', 'yield'}) -def StringParser(name, description, kwargs): - return coredata.UserStringOption(name, - description, +def StringParser(description, kwargs): + return coredata.UserStringOption(description, kwargs.get('value', ''), kwargs.get('choices', []), kwargs.get('yield', coredata.default_yielding)) @permitted_kwargs({'value', 'yield'}) -def BooleanParser(name, description, kwargs): - return coredata.UserBooleanOption(name, description, +def BooleanParser(description, kwargs): + return coredata.UserBooleanOption(description, kwargs.get('value', True), kwargs.get('yield', coredata.default_yielding)) @permitted_kwargs({'value', 'yield', 'choices'}) -def ComboParser(name, description, kwargs): +def ComboParser(description, kwargs): if 'choices' not in kwargs: raise OptionException('Combo option missing "choices" keyword.') choices = kwargs['choices'] @@ -80,19 +80,17 @@ def ComboParser(name, description, kwargs): for i in choices: if not isinstance(i, str): raise OptionException('Combo choice elements must be strings.') - return coredata.UserComboOption(name, - description, + return coredata.UserComboOption(description, choices, kwargs.get('value', choices[0]), kwargs.get('yield', coredata.default_yielding),) @permitted_kwargs({'value', 'min', 'max', 'yield'}) -def IntegerParser(name, description, kwargs): +def IntegerParser(description, kwargs): if 'value' not in kwargs: raise OptionException('Integer option must contain value argument.') - return coredata.UserIntegerOption(name, - description, + return coredata.UserIntegerOption(description, kwargs.get('min', None), kwargs.get('max', None), kwargs['value'], @@ -102,7 +100,7 @@ def IntegerParser(name, description, kwargs): # reading options in project(). See func_project() in interpreter.py #@FeatureNew('array type option()', '0.44.0') @permitted_kwargs({'value', 'yield', 'choices'}) -def string_array_parser(name, description, kwargs): +def string_array_parser(description, kwargs): if 'choices' in kwargs: choices = kwargs['choices'] if not isinstance(choices, list): @@ -116,16 +114,14 @@ def string_array_parser(name, description, kwargs): value = kwargs.get('value', []) if not isinstance(value, list): raise OptionException('Array choices must be passed as an array.') - return coredata.UserArrayOption(name, - description, + return coredata.UserArrayOption(description, value, choices=choices, yielding=kwargs.get('yield', coredata.default_yielding)) @permitted_kwargs({'value', 'yield'}) -def FeatureParser(name, description, kwargs): - return coredata.UserFeatureOption(name, - description, +def FeatureParser(description, kwargs): + return coredata.UserFeatureOption(description, kwargs.get('value', 'auto'), yielding=kwargs.get('yield', coredata.default_yielding)) @@ -135,7 +131,7 @@ option_types = {'string': StringParser, 'integer': IntegerParser, 'array': string_array_parser, 'feature': FeatureParser, - } + } # type: typing.Dict[str, typing.Callable[[str, typing.Dict], coredata.UserOption]] class OptionInterpreter: def __init__(self, subproject):