Skip to content

Commit e89fa91

Browse files
committed
Require using built-in dataclasses in load_config()
This is just the last step to be able to enforce via the type system that only built-in dataclasses are used. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 9ed4030 commit e89fa91

File tree

1 file changed

+13
-5
lines changed

1 file changed

+13
-5
lines changed

src/frequenz/sdk/config/_util.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,30 @@
44
"""Utilities to deal with configuration."""
55

66
from collections.abc import Mapping
7-
from typing import Any, TypeVar, cast
7+
from typing import Any, ClassVar, Protocol, TypeVar, cast
88

99
from marshmallow import Schema
1010
from marshmallow_dataclass import class_schema
1111

12-
T = TypeVar("T")
12+
13+
class Dataclass(Protocol):
14+
"""A protocol for dataclasses."""
15+
16+
__dataclass_fields__: ClassVar[dict[str, Any]]
17+
"""The fields of the dataclass."""
18+
19+
20+
DataclassT = TypeVar("DataclassT", bound=Dataclass)
1321
"""Type variable for configuration classes."""
1422

1523

1624
def load_config(
17-
cls: type[T],
25+
cls: type[DataclassT],
1826
config: Mapping[str, Any],
1927
/,
2028
base_schema: type[Schema] | None = None,
2129
**marshmallow_load_kwargs: Any,
22-
) -> T:
30+
) -> DataclassT:
2331
"""Load a configuration from a dictionary into an instance of a configuration class.
2432
2533
The configuration class is expected to be a [`dataclasses.dataclass`][], which is
@@ -56,4 +64,4 @@ def load_config(
5664
instance = class_schema(cls, base_schema)().load(config, **marshmallow_load_kwargs)
5765
# We need to cast because `.load()` comes from marshmallow and doesn't know which
5866
# type is returned.
59-
return cast(T, instance)
67+
return cast(DataclassT, instance)

0 commit comments

Comments
 (0)