diff options
Diffstat (limited to 'mesonbuild/options.py')
| -rw-r--r-- | mesonbuild/options.py | 61 |
1 files changed, 41 insertions, 20 deletions
diff --git a/mesonbuild/options.py b/mesonbuild/options.py index a53cb91a4..ae580785e 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -253,7 +253,6 @@ class UserOption(T.Generic[_T], HoldableObject): name: str description: str value_: dataclasses.InitVar[_T] - choices: T.Optional[T.Union[str, T.List[_T]]] = None yielding: bool = DEFAULT_YIELDING deprecated: DeprecatedType = False readonly: bool = dataclasses.field(default=False, init=False) @@ -269,11 +268,7 @@ class UserOption(T.Generic[_T], HoldableObject): return self.value def printable_choices(self) -> T.Optional[T.List[str]]: - if not self.choices: - return None - if isinstance(self.choices, str): - return [self.choices] - return [str(c) for c in self.choices] + return None # Check that the input is a valid value and return the # "cleaned" or "native" version. For example the Boolean @@ -288,6 +283,17 @@ class UserOption(T.Generic[_T], HoldableObject): @dataclasses.dataclass +class EnumeratedUserOption(UserOption[_T]): + + """A generic UserOption that has enumerated values.""" + + choices: T.List[_T] = dataclasses.field(default_factory=list) + + def printable_choices(self) -> T.Optional[T.List[str]]: + return [str(c) for c in self.choices] + + +@dataclasses.dataclass class UserStringOption(UserOption[str]): def validate_value(self, value: T.Any) -> str: @@ -296,7 +302,7 @@ class UserStringOption(UserOption[str]): return value @dataclasses.dataclass -class UserBooleanOption(UserOption[bool]): +class UserBooleanOption(EnumeratedUserOption[bool]): choices: T.List[bool] = dataclasses.field(default_factory=lambda: [True, False]) @@ -327,7 +333,10 @@ class UserIntegerOption(UserOption[int]): choices.append(f'>= {self.min_value!s}') if self.max_value is not None: choices.append(f'<= {self.max_value!s}') - self.choices = ', '.join(choices) + self.__choices: str = ', '.join(choices) + + def printable_choices(self) -> T.Optional[T.List[str]]: + return [self.__choices] def validate_value(self, value: T.Any) -> int: if isinstance(value, str): @@ -376,7 +385,7 @@ class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]): raise MesonException(f'Invalid mode for option "{self.name}" {e}') @dataclasses.dataclass -class UserComboOption(UserOption[str]): +class UserComboOption(EnumeratedUserOption[str]): def validate_value(self, value: T.Any) -> str: if value not in self.choices: @@ -390,15 +399,32 @@ class UserComboOption(UserOption[str]): raise MesonException('Value "{}" (of type "{}") for option "{}" is not one of the choices.' ' Possible choices are (as string): {}.'.format( value, _type, self.name, optionsstring)) + + assert isinstance(value, str), 'for mypy' return value @dataclasses.dataclass -class UserArrayOption(UserOption[T.List[str]]): +class UserArrayOption(UserOption[T.List[_T]]): - value_: dataclasses.InitVar[T.Union[str, T.List[str]]] + value_: dataclasses.InitVar[T.Union[_T, T.List[_T]]] + choices: T.Optional[T.List[_T]] = None split_args: bool = False allow_dups: bool = False + def extend_value(self, value: T.Union[str, T.List[str]]) -> None: + """Extend the value with an additional value.""" + new = self.validate_value(value) + self.set_value(self.value + new) + + def printable_choices(self) -> T.Optional[T.List[str]]: + if self.choices is None: + return None + return [str(c) for c in self.choices] + + +@dataclasses.dataclass +class UserStringArrayOption(UserArrayOption[str]): + def listify(self, value: T.Any) -> T.List[T.Any]: try: return listify_array_value(value, self.split_args) @@ -427,11 +453,6 @@ class UserArrayOption(UserOption[T.List[str]]): ) return newvalue - def extend_value(self, value: T.Union[str, T.List[str]]) -> None: - """Extend the value with an additional value.""" - new = self.validate_value(value) - self.set_value(self.value + new) - @dataclasses.dataclass class UserFeatureOption(UserComboOption): @@ -471,7 +492,7 @@ class UserStdOption(UserComboOption): # Map a deprecated std to its replacement. e.g. gnu11 -> c11. self.deprecated_stds: T.Dict[str, str] = {} opt_name = 'cpp_std' if lang == 'c++' else f'{lang}_std' - super().__init__(opt_name, f'{lang} language standard to use', 'none', ['none']) + super().__init__(opt_name, f'{lang} language standard to use', 'none', choices=['none']) def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: bool = False) -> None: assert all(std in self.all_stds for std in versions) @@ -637,7 +658,7 @@ BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ (OptionKey('warning_level'), BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3', 'everything'], yielding=False)), (OptionKey('werror'), BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)), (OptionKey('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])), - (OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])), + (OptionKey('force_fallback_for'), BuiltinOption(UserStringArrayOption, 'Force fallback for those subprojects', [])), (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), # Pkgconfig module @@ -660,8 +681,8 @@ BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items())) BUILTIN_OPTIONS_PER_MACHINE: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])), - (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])), + (OptionKey('pkg_config_path'), BuiltinOption(UserStringArrayOption, 'List of additional paths for pkg-config to search', [])), + (OptionKey('cmake_prefix_path'), BuiltinOption(UserStringArrayOption, 'List of additional prefixes for cmake to search', [])), ]) # Special prefix-dependent defaults for installation directories that reside in |
