aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2023-01-25 11:00:43 -0500
committerXavier Claessens <xclaesse@gmail.com>2023-03-04 14:19:27 -0500
commit0f67913dee7d4173b1f7c5e95268d7bc4d4d858d (patch)
tree516cf931cba047f1f352b0b38ed8e0626b8a9fb8 /mesonbuild
parent2d26c272c3225f99c945d2c510c61910c34a9377 (diff)
downloadmeson-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.py9
-rw-r--r--mesonbuild/interpreterbase/decorators.py51
-rw-r--r--mesonbuild/modules/rust.py4
-rw-r--r--mesonbuild/optinterpreter.py8
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)),