Skip to content

Commit 280f78d

Browse files
committed
Raise ValidationError from the config test validators
`frequenz-quantities` 1.0.2 changed its `marshmallow` optional dependency floor from `< 4` to `>= 4` (frequenz-floss/frequenz-quantities-python#107), correcting metadata that had been wrong since that library was ported to `marshmallow` 4. That cap was the only thing holding us on `marshmallow` 3, as our own requirement has allowed `< 5` since 870e880, so CI now resolves `marshmallow` 4. `marshmallow` 4 removed support for validators that signal failure by returning `False`, deprecated in 3.24.0: Custom validators must raise a `ValidationError` for invalid values (deprecated in 3.24.0). Returning `False` is no longer supported. The configuration test dataclasses used exactly that pattern, a `lambda s: s.startswith("test")` in the field metadata. The validator is still registered and still called, only its return value is ignored, so the invalid value is accepted and `test_load_config_dataclass` and `test_new_receiver_configurations[Validation Error]` fail. Replacing the lambdas with a function that raises restores the checks. The message stays `Invalid value.`, which is what `marshmallow` 3 emitted through its `validator_failed` error key, so the expected output in `test_manager.py` is unchanged and the surrounding test cases remain consistent in asserting on `marshmallow`'s stock messages. Nothing under `src/` needed changing: the validators there are `marshmallow.validate.Range` and `OneOf`, which already raise. A raising validator also works on `marshmallow` 3, so the supported range is not narrowed, but the same silent acceptance can hit users who wrote their own boolean validators, hence the release notes entry. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
1 parent 9e92877 commit 280f78d

3 files changed

Lines changed: 31 additions & 3 deletions

File tree

‎RELEASE_NOTES.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
## Upgrading
88

9+
- Custom validators passed through a configuration dataclass field's `metadata` (as used by `load_config()` and `ConfigManager.new_receiver()`) must now raise a `marshmallow.ValidationError` to reject a value. `marshmallow` 4 removed support for validators that signal failure by returning `False`, so such validators are now ignored and the invalid value is accepted silently. This affects you as soon as `marshmallow` 4 is installed, which `frequenz-quantities` 1.0.2 and later require.
10+
911
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
1012

1113
## New Features

‎tests/config/test_manager.py‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,24 @@
2020
from frequenz.sdk.config._manager import _get_key
2121

2222

23+
def _validate_name(value: str) -> None:
24+
"""Validate that a name starts with `test`.
25+
26+
Args:
27+
value: The name to validate.
28+
29+
Raises:
30+
marshmallow.ValidationError: If the name doesn't start with `test`.
31+
"""
32+
if not value.startswith("test"):
33+
raise marshmallow.ValidationError("Invalid value.")
34+
35+
2336
@dataclass
2437
class SimpleConfig:
2538
"""A simple configuration class for testing."""
2639

27-
name: str = dataclasses.field(metadata={"validate": lambda s: s.startswith("test")})
40+
name: str = dataclasses.field(metadata={"validate": _validate_name})
2841
value: int
2942

3043

‎tests/config/test_util.py‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,32 @@
1414
from frequenz.sdk.config._util import load_config
1515

1616

17+
def _validate_name(value: str) -> None:
18+
"""Validate that a name starts with `test`.
19+
20+
Args:
21+
value: The name to validate.
22+
23+
Raises:
24+
marshmallow.ValidationError: If the name doesn't start with `test`.
25+
"""
26+
if not value.startswith("test"):
27+
raise marshmallow.ValidationError("Invalid value.")
28+
29+
1730
@dataclasses.dataclass
1831
class SimpleConfig:
1932
"""A simple configuration class for testing."""
2033

21-
name: str = dataclasses.field(metadata={"validate": lambda s: s.startswith("test")})
34+
name: str = dataclasses.field(metadata={"validate": _validate_name})
2235
value: int
2336

2437

2538
@marshmallow_dataclass.dataclass
2639
class MmSimpleConfig:
2740
"""A simple marshmallow_dataclass configuration class for testing."""
2841

29-
name: str = dataclasses.field(metadata={"validate": lambda s: s.startswith("test")})
42+
name: str = dataclasses.field(metadata={"validate": _validate_name})
3043
value: int
3144

3245

0 commit comments

Comments
 (0)