Skip to content

Commit c3dce99

Browse files
Update pydantic to v2.3
This update is necessary to stay current with the latest pydantic version, rather than pinning the library to v1.9.0. However, it's worth noting that this is a temporary solution until Frequenz-SDK is updated to use Marshmallow instead of pydantic, which would require a higher level of effort. One important consideration is the dependency on typing-extensions>=4.6.1 introduced in pydantic v2.0. Additionally, there's a breaking change in pydantic v2, which disallows data type conversion if it results in a loss of precision. This is particularly relevant when converting a float to an int. Consequently, the `test_config.py` file has been updated to accommodate this change. Signed-off-by: Daniel Zullo <[email protected]>
1 parent 284b403 commit c3dce99

File tree

3 files changed

+13
-9
lines changed

3 files changed

+13
-9
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ dependencies = [
3737
"networkx >= 2.8, < 4",
3838
"numpy >= 1.24.2, < 2",
3939
"protobuf >= 4.21.6, < 5",
40-
"pydantic >= 1.9, < 2",
40+
"pydantic >= 2.3, < 3",
4141
"tqdm >= 4.38.0, < 5",
42-
"typing_extensions >= 4.4.0, < 5",
42+
"typing_extensions >= 4.6.1, < 5",
4343
"watchfiles >= 0.15.0",
4444
]
4545
dynamic = ["version"]

src/frequenz/sdk/config/_config.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
"""Read and update config variables."""
55

6+
import json
67
import logging
78
from typing import Any, TypeVar
89

9-
# pylint not finding parse_raw_as is a false positive
10-
from pydantic import ValidationError, parse_raw_as # pylint: disable=no-name-in-module
10+
from pydantic import Strict, TypeAdapter, ValidationError
1111

1212
_logger = logging.getLogger(__name__)
1313

@@ -121,7 +121,11 @@ def get_as(self, key: str, expected_type: Any) -> Any:
121121
return value
122122

123123
try:
124-
parsed_value: Any = parse_raw_as(expected_type, value)
124+
obj = json.loads(value)
125+
metadata = getattr(expected_type, "__metadata__", (None,))[0]
126+
strict = metadata.strict if isinstance(metadata, Strict) else False
127+
adapter = TypeAdapter(expected_type)
128+
parsed_value = adapter.validate_python(obj, strict=strict)
125129
except (ValidationError, ValueError) as err:
126130
raise ValueError(
127131
f"Could not convert config variable: {key} = '{value}' "

tests/config/test_config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,18 @@ def test_contains(self, conf_vars: dict[str, Any]) -> None:
9292
("logging_lvl", str, "DEBUG"),
9393
("var_int", int, 5),
9494
("var_int", StrictInt, 5),
95+
("var_int", StrictFloat, 5.0),
9596
("var_int", float, 5.0),
9697
("var_float", float, 3.14),
9798
("var_float", StrictFloat, 3.14),
98-
("var_float", int, 3),
9999
("var_bool", int, 1),
100100
("var_bool", float, 1.0),
101101
("var_bool", bool, True),
102102
("var1", bool, 1),
103103
("var_bool", StrictBool, True),
104104
("list_int", list[int], [1, 2, 3]),
105105
("list_int", list[StrictInt], [1, 2, 3]),
106-
("list_float", list[int], [1, 2, 3]),
106+
("list_int", list[StrictFloat], [1.0, 2.0, 3.0]),
107107
("list_int", list[float], [1.0, 2.0, 3.0]),
108108
("list_float", list[float], [1, 2.0, 3.5]),
109109
("list_non_strict_bool", list[bool], 2 * [False] + 2 * [True]),
@@ -124,12 +124,12 @@ def test_get_as_success(
124124
@pytest.mark.parametrize(
125125
"key, expected_type",
126126
[
127+
("var_float", int),
127128
("var_float", StrictInt),
128-
("var_int", StrictFloat),
129129
("var1", StrictBool),
130130
("list_float", list[StrictInt]),
131-
("list_int", list[StrictFloat]),
132131
("list_non_strict_bool", list[int]),
132+
("list_float", list[int]),
133133
],
134134
)
135135
def test_get_as_validation_error(

0 commit comments

Comments
 (0)