diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2023-01-25 11:00:43 -0500 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2023-03-04 14:19:27 -0500 |
commit | 0f67913dee7d4173b1f7c5e95268d7bc4d4d858d (patch) | |
tree | 516cf931cba047f1f352b0b38ed8e0626b8a9fb8 /mesonbuild | |
parent | 2d26c272c3225f99c945d2c510c61910c34a9377 (diff) | |
download | meson-0f67913dee7d4173b1f7c5e95268d7bc4d4d858d.zip meson-0f67913dee7d4173b1f7c5e95268d7bc4d4d858d.tar.gz meson-0f67913dee7d4173b1f7c5e95268d7bc4d4d858d.tar.bz2 |
typed_kwargs: Extend since_values and deprecated_values for types
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/interpreter/type_checking.py | 9 | ||||
-rw-r--r-- | mesonbuild/interpreterbase/decorators.py | 51 | ||||
-rw-r--r-- | mesonbuild/modules/rust.py | 4 | ||||
-rw-r--r-- | mesonbuild/optinterpreter.py | 8 |
4 files changed, 39 insertions, 33 deletions
diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 7e1bd80..129668b 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -13,7 +13,6 @@ from ..build import (CustomTarget, BuildTarget, BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable) from ..coredata import UserFeatureOption from ..dependencies import Dependency, InternalDependency -from ..interpreterbase import FeatureNew from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo from ..mesonlib import (File, FileMode, MachineChoice, listify, has_path_sep, OptionKey, EnvironmentVariables) @@ -26,7 +25,6 @@ if T.TYPE_CHECKING: from typing_extensions import Literal from ..interpreterbase import TYPE_var - from ..interpreterbase.decorators import FeatureCheckBase from ..mesonlib import EnvInitValueType _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] @@ -376,13 +374,6 @@ INCLUDE_DIRECTORIES: KwargInfo[T.List[T.Union[str, IncludeDirs]]] = KwargInfo( default=[], ) -def include_dir_string_new(val: T.List[T.Union[str, IncludeDirs]]) -> T.Iterable[FeatureCheckBase]: - strs = [v for v in val if isinstance(v, str)] - if strs: - str_msg = ", ".join(f"'{s}'" for s in strs) - yield FeatureNew('include_directories kwarg of type string', '1.0.0', - f'Use include_directories({str_msg}) instead') - # for cases like default_options and override_options DEFAULT_OPTIONS: KwargInfo[T.List[str]] = KwargInfo( 'default_options', diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index 7486915..7916072 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -313,15 +313,25 @@ class ContainerTypeInfo: if not isinstance(value, self.container): return False iter_ = iter(value.values()) if isinstance(value, dict) else iter(value) - for each in iter_: - if not isinstance(each, self.contains): - return False + if any(not isinstance(i, self.contains) for i in iter_): + return False if self.pairs and len(value) % 2 != 0: return False if not value and not self.allow_empty: return False return True + def check_any(self, value: T.Any) -> bool: + """Check a value should emit new/deprecated feature. + + :param value: A value to check + :return: True if any of the items in value matches, False otherwise + """ + if not isinstance(value, self.container): + return False + iter_ = iter(value.values()) if isinstance(value, dict) else iter(value) + return any(isinstance(i, self.contains) for i in iter_) + def description(self) -> str: """Human readable description of this container type. @@ -390,10 +400,10 @@ class KwargInfo(T.Generic[_T]): default: T.Optional[_T] = None, since: T.Optional[str] = None, since_message: T.Optional[str] = None, - since_values: T.Optional[T.Dict[T.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]]] = None, + since_values: T.Optional[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]]] = None, deprecated: T.Optional[str] = None, deprecated_message: T.Optional[str] = None, - deprecated_values: T.Optional[T.Dict[T.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]]] = None, + deprecated_values: T.Optional[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]]] = None, feature_validator: T.Optional[T.Callable[[_T], T.Iterable[FeatureCheckBase]]] = None, validator: T.Optional[T.Callable[[T.Any], T.Optional[str]]] = None, convertor: T.Optional[T.Callable[[_T], object]] = None, @@ -421,10 +431,10 @@ class KwargInfo(T.Generic[_T]): default: T.Union[_T, None, _NULL_T] = _NULL, since: T.Union[str, None, _NULL_T] = _NULL, since_message: T.Union[str, None, _NULL_T] = _NULL, - since_values: T.Union[T.Dict[T.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, + since_values: T.Union[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, deprecated: T.Union[str, None, _NULL_T] = _NULL, deprecated_message: T.Union[str, None, _NULL_T] = _NULL, - deprecated_values: T.Union[T.Dict[T.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, + deprecated_values: T.Union[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, feature_validator: T.Union[T.Callable[[_T], T.Iterable[FeatureCheckBase]], None, _NULL_T] = _NULL, validator: T.Union[T.Callable[[_T], T.Optional[str]], None, _NULL_T] = _NULL, convertor: T.Union[T.Callable[[_T], TYPE_var], None, _NULL_T] = _NULL) -> 'KwargInfo': @@ -512,23 +522,28 @@ def typed_kwargs(name: str, *types: KwargInfo, allow_unknown: bool = False) -> T def emit_feature_change(values: T.Dict[_T, T.Union[str, T.Tuple[str, str]]], feature: T.Union[T.Type['FeatureDeprecated'], T.Type['FeatureNew']]) -> None: for n, version in values.items(): - warn = False if isinstance(version, tuple): version, msg = version else: msg = None - if n in {dict, list}: - assert isinstance(n, type), 'for mypy' + warning: T.Optional[str] = None + if isinstance(n, ContainerTypeInfo): + if n.check_any(value): + warning = f'of type {n.description()}' + elif isinstance(n, type): if isinstance(value, n): - feature.single_use(f'"{name}" keyword argument "{info.name}" of type {n.__name__}', version, subproject, msg, location=node) - elif isinstance(value, (dict, list)): - warn = n in value - else: - warn = n == value - - if warn: - feature.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject, msg, location=node) + warning = f'of type {n.__name__}' + elif isinstance(value, list): + if n in value: + warning = f'value "{n}" in list' + elif isinstance(value, dict): + if n in value.keys(): + warning = f'value "{n}" in dict keys' + elif n == value: + warning = f'value "{n}"' + if warning: + feature.single_use(f'"{name}" keyword argument "{info.name}" {warning}', version, subproject, msg, location=node) 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 diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 126b894..6c3200d 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -20,7 +20,7 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, StructuredSources from ..dependencies import Dependency, ExternalLibrary -from ..interpreter.type_checking import DEPENDENCIES_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, include_dir_string_new +from ..interpreter.type_checking import DEPENDENCIES_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs from ..mesonlib import File @@ -172,7 +172,7 @@ class RustModule(ExtensionModule): listify=True, required=True, ), - INCLUDE_DIRECTORIES.evolve(feature_validator=include_dir_string_new), + INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), OUTPUT_KW, DEPENDENCIES_KW.evolve(since='1.0.0'), ) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index d165639..8377614 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -20,7 +20,7 @@ from . import coredata from . import mesonlib from . import mparser from . import mlog -from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo, FeatureDeprecated +from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo from .interpreter.type_checking import NoneType, in_set_validator if T.TYPE_CHECKING: @@ -182,7 +182,7 @@ class OptionInterpreter: (bool, str, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)), default=False, since='0.60.0', - feature_validator=lambda x: [FeatureNew('string value to "deprecated" keyword argument', '0.63.0')] if isinstance(x, str) else [] + since_values={str: '0.63.0'}, ), KwargInfo('yield', bool, default=coredata.DEFAULT_YIELDING, since='0.45.0'), allow_unknown=True, @@ -223,7 +223,7 @@ class OptionInterpreter: (bool, str), default=True, validator=lambda x: None if isinstance(x, bool) or x in {'true', 'false'} else 'boolean options must have boolean values', - deprecated_values={'true': ('1.1.0', 'use a boolean, not a string'), 'false': ('1.1.0', 'use a boolean, not a string')}, + deprecated_values={str: ('1.1.0', 'use a boolean, not a string')}, ), ) def boolean_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption: @@ -247,7 +247,7 @@ class OptionInterpreter: 'value', (int, str), default=True, - feature_validator=lambda x: [FeatureDeprecated('number values as strings', '1.1.0', 'use a raw number instead')] if isinstance(x, str) else [], + deprecated_values={str: ('1.1.0', 'use an integer, not a string')}, convertor=int, ), KwargInfo('min', (int, NoneType)), |