aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2021-11-19 10:39:21 -0800
committerDylan Baker <dylan@pnwbakers.com>2021-11-22 12:24:14 -0800
commitecc47d67a945760c3d5e739581fa984bfea6a840 (patch)
tree8bf93ff2ef715e9f41d010bd77af76b7ba56eb10
parent1f6351461c5d3654aeff2355c96fe54bb28469f8 (diff)
downloadmeson-ecc47d67a945760c3d5e739581fa984bfea6a840.zip
meson-ecc47d67a945760c3d5e739581fa984bfea6a840.tar.gz
meson-ecc47d67a945760c3d5e739581fa984bfea6a840.tar.bz2
typed_kwargs: provide better error messages for wrong container types
Currently, if you pass a `[]string`, but the argument expects `[]number`, then you get a message like `expected list[str] but got list`. That isn't helpful. With this patch arrays and dictionaries will both print messages with the types provided.
-rw-r--r--mesonbuild/interpreterbase/decorators.py14
-rw-r--r--test cases/failing/116 run_target in test/test.json2
-rw-r--r--unittests/internaltests.py6
3 files changed, 17 insertions, 5 deletions
diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py
index 16aa7d2..817cb85 100644
--- a/mesonbuild/interpreterbase/decorators.py
+++ b/mesonbuild/interpreterbase/decorators.py
@@ -467,6 +467,18 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
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"list[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t)))}]"
+ return 'list[]'
+ 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:
@@ -503,7 +515,7 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
kwargs[info.name] = value = mesonlib.listify(value)
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 {type(value).__name__!r} but should have been {shouldbe}')
+ 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)
diff --git a/test cases/failing/116 run_target in test/test.json b/test cases/failing/116 run_target in test/test.json
index c273a3b..7826ceb 100644
--- a/test cases/failing/116 run_target in test/test.json
+++ b/test cases/failing/116 run_target in test/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/116 run_target in test/meson.build:4:0: ERROR: test keyword argument 'args' was of type 'list' but should have been list[str,File,BuildTarget,CustomTarget]"
+ "line": "test cases/failing/116 run_target in test/meson.build:4:0: ERROR: test keyword argument 'args' was of type list[RunTarget] but should have been list[str,File,BuildTarget,CustomTarget]"
}
]
}
diff --git a/unittests/internaltests.py b/unittests/internaltests.py
index 207bd37..86c1890 100644
--- a/unittests/internaltests.py
+++ b/unittests/internaltests.py
@@ -1266,7 +1266,7 @@ class InternalTests(unittest.TestCase):
with self.assertRaises(InvalidArguments) as cm:
_(None, mock.Mock(), [], {'input': {}})
- self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type 'dict' but should have been list[str]")
+ self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type dict[] but should have been list[str]")
def test_typed_kwarg_contained_invalid(self) -> None:
@typed_kwargs(
@@ -1278,7 +1278,7 @@ class InternalTests(unittest.TestCase):
with self.assertRaises(InvalidArguments) as cm:
_(None, mock.Mock(), [], {'input': {'key': 1}})
- self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type 'dict' but should have been dict[str]")
+ self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type dict[int] but should have been dict[str]")
def test_typed_kwarg_container_listify(self) -> None:
@typed_kwargs(
@@ -1313,7 +1313,7 @@ class InternalTests(unittest.TestCase):
with self.assertRaises(MesonException) as cm:
_(None, mock.Mock(), [], {'input': ['a']})
- self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type 'list' but should have been list[str] that has even size")
+ self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type list[str] but should have been list[str] that has even size")
@mock.patch.dict(mesonbuild.mesonlib.project_meson_versions, {})
def test_typed_kwarg_since(self) -> None: