aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/interpreterbase/decorators.py63
1 files changed, 39 insertions, 24 deletions
diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py
index a75aade..8832d29 100644
--- a/mesonbuild/interpreterbase/decorators.py
+++ b/mesonbuild/interpreterbase/decorators.py
@@ -326,9 +326,9 @@ class ContainerTypeInfo:
:return: string to be printed
"""
- container = 'dict' if self.container is dict else 'list'
+ container = 'dict' if self.container is dict else 'array'
if isinstance(self.contains, tuple):
- contains = ','.join([t.__name__ for t in self.contains])
+ contains = ' | '.join([t.__name__ for t in self.contains])
else:
contains = self.contains.__name__
s = f'{container}[{contains}]'
@@ -456,6 +456,39 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
"""
def inner(f: TV_func) -> TV_func:
+ def types_description(types_tuple: T.Tuple[T.Union[T.Type, ContainerTypeInfo], ...]) -> str:
+ candidates = []
+ for t in types_tuple:
+ if isinstance(t, ContainerTypeInfo):
+ candidates.append(t.description())
+ else:
+ candidates.append(t.__name__)
+ shouldbe = 'one of: ' if len(candidates) > 1 else ''
+ shouldbe += ', '.join(candidates)
+ return shouldbe
+
+ def raw_description(t: object) -> str:
+ """describe a raw type (ie, one that is not a ContainerTypeInfo)."""
+ if isinstance(t, list):
+ if t:
+ return f"array[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t)))}]"
+ return 'array[]'
+ elif isinstance(t, dict):
+ if t:
+ return f"dict[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t.values())))}]"
+ return 'dict[]'
+ return type(t).__name__
+
+ def check_value_type(types_tuple: T.Tuple[T.Union[T.Type, ContainerTypeInfo], ...],
+ value: T.Any) -> bool:
+ for t in types_tuple:
+ if isinstance(t, ContainerTypeInfo):
+ if t.check(value):
+ return True
+ elif isinstance(value, t):
+ return True
+ return False
+
@wraps(f)
def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
node, _, _kwargs, subproject = get_callee_args(wrapped_args)
@@ -470,24 +503,6 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
for info in types:
types_tuple = info.types if isinstance(info.types, tuple) else (info.types,)
- def check_value_type(value: T.Any) -> bool:
- for t in types_tuple:
- if isinstance(t, ContainerTypeInfo):
- if t.check(value):
- return True
- elif isinstance(value, t):
- return True
- return False
- def types_description() -> str:
- candidates = []
- for t in types_tuple:
- if isinstance(t, ContainerTypeInfo):
- candidates.append(t.description())
- else:
- candidates.append(t.__name__)
- shouldbe = 'one of: ' if len(candidates) > 1 else ''
- shouldbe += ', '.join(candidates)
- return shouldbe
value = kwargs.get(info.name)
if value is not None:
if info.since:
@@ -498,9 +513,9 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
FeatureDeprecated.single_use(feature_name, info.deprecated, subproject, location=node)
if info.listify:
kwargs[info.name] = value = mesonlib.listify(value)
- if not check_value_type(value):
- shouldbe = types_description()
- raise InvalidArguments(f'{name} keyword argument {info.name!r} was of type {type(value).__name__!r} but should have been {shouldbe}')
+ if not check_value_type(types_tuple, value):
+ shouldbe = types_description(types_tuple)
+ raise InvalidArguments(f'{name} keyword argument {info.name!r} was of type {raw_description(value)} but should have been {shouldbe}')
if info.validator is not None:
msg = info.validator(value)
@@ -533,7 +548,7 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
else:
# set the value to the default, this ensuring all kwargs are present
# This both simplifies the typing checking and the usage
- assert check_value_type(info.default), f'In funcion {name} default value of {info.name} is not a valid type, got {type(info.default)} expected {types_description()}'
+ assert check_value_type(types_tuple, info.default), f'In funcion {name} default value of {info.name} is not a valid type, got {type(info.default)} expected {types_description(types_tuple)}'
# Create a shallow copy of the container. This allows mutable
# types to be used safely as default values
kwargs[info.name] = copy.copy(info.default)