diff options
Diffstat (limited to 'SCons/Variables/EnumVariable.py')
-rw-r--r-- | SCons/Variables/EnumVariable.py | 116 |
1 files changed, 78 insertions, 38 deletions
diff --git a/SCons/Variables/EnumVariable.py b/SCons/Variables/EnumVariable.py index 1a4f3fb..d13e9a9 100644 --- a/SCons/Variables/EnumVariable.py +++ b/SCons/Variables/EnumVariable.py @@ -38,12 +38,12 @@ Usage example:: ignorecase=2, ) ) - ... + env = Environment(variables=opts) if env['debug'] == 'full': - ... + ... """ -from typing import Tuple, Callable +from typing import Callable, List, Optional, Tuple import SCons.Errors @@ -51,57 +51,97 @@ __all__ = ['EnumVariable',] def _validator(key, val, env, vals) -> None: - if val not in vals: - raise SCons.Errors.UserError( - 'Invalid value for option %s: %s. Valid values are: %s' % (key, val, vals)) - + """Validate that val is in vals. -def EnumVariable(key, help, default, allowed_values, map={}, ignorecase: int=0) -> Tuple[str, str, str, Callable, Callable]: + Usable as the base for :class:`EnumVariable` validators. + """ + if val not in vals: + msg = ( + f"Invalid value for enum variable {key!r}: {val!r}. " + f"Valid values are: {vals}" + ) + raise SCons.Errors.UserError(msg) from None + + +# lint: W0622: Redefining built-in 'help' (redefined-builtin) +# lint: W0622: Redefining built-in 'map' (redefined-builtin) +def EnumVariable( + key, + help: str, + default: str, + allowed_values: List[str], + map: Optional[dict] = None, + ignorecase: int = 0, +) -> Tuple[str, str, str, Callable, Callable]: """Return a tuple describing an enumaration SCons Variable. - The input parameters describe an option with only certain values - allowed. Returns A tuple including an appropriate converter and - validator. The result is usable as input to :meth:`Add`. - - *key* and *default* are passed directly on to :meth:`Add`. - - *help* is the descriptive part of the help text, - and will have the allowed values automatically appended. + The input parameters describe a variable with only predefined values + allowed. The value of *ignorecase* defines the behavior of the + validator and converter: if ``0``, the validator/converter are + case-sensitive; if ``1``, the validator/converter are case-insensitive; + if ``2``, the validator/converter are case-insensitive and the + converted value will always be lower-case. + + Arguments: + key: variable name, passed directly through to the return tuple. + default: default values, passed directly through to the return tuple. + help: descriptive part of the help text, + will have the allowed values automatically appended. + allowed_values: list of the allowed values for this variable. + map: optional dictionary which may be used for converting the + input value into canonical values (e.g. for aliases). + ignorecase: defines the behavior of the validator and converter. + validator: callback function to test whether the value is in the + list of allowed values. + converter: callback function to convert input values according to + the given *map*-dictionary. Unmapped input values are returned + unchanged. + + Returns: + A tuple including an appropriate converter and validator. + The result is usable as input to :meth:`~SCons.Variables.Variables.Add`. + and :meth:`~SCons.Variables.Variables.AddVariables`. + """ + # these are all inner functions so they can access EnumVariable locals. + def validator_rcase(key, val, env): + """Case-respecting validator.""" + return _validator(key, val, env, allowed_values) - *allowed_values* is a list of strings, which are the allowed values - for this option. + def validator_icase(key, val, env): + """Case-ignoring validator.""" + return _validator(key, val.lower(), env, allowed_values) - The *map*-dictionary may be used for converting the input value - into canonical values (e.g. for aliases). + def converter_rcase(val): + """Case-respecting converter.""" + return map.get(val, val) - The value of *ignorecase* defines the behaviour of the validator: + def converter_icase(val): + """Case-ignoring converter.""" + return map.get(val.lower(), val) - * 0: the validator/converter are case-sensitive. - * 1: the validator/converter are case-insensitive. - * 2: the validator/converter is case-insensitive and the - converted value will always be lower-case. + def converter_lcase(val): + """Case-lowering converter.""" + return map.get(val.lower(), val).lower() - The *validator* tests whether the value is in the list of allowed values. - The *converter* converts input values according to the given - *map*-dictionary (unmapped input values are returned unchanged). - """ + if map is None: + map = {} + help = f"{help} ({'|'.join(allowed_values)})" - help = '%s (%s)' % (help, '|'.join(allowed_values)) # define validator if ignorecase: - validator = lambda key, val, env: \ - _validator(key, val.lower(), env, allowed_values) + validator = validator_icase else: - validator = lambda key, val, env: \ - _validator(key, val, env, allowed_values) + validator = validator_rcase + # define converter if ignorecase == 2: - converter = lambda val: map.get(val.lower(), val).lower() + converter = converter_lcase elif ignorecase == 1: - converter = lambda val: map.get(val.lower(), val) + converter = converter_icase else: - converter = lambda val: map.get(val, val) - return (key, help, default, validator, converter) + converter = converter_rcase + + return key, help, default, validator, converter # Local Variables: # tab-width:4 |