From ac69e297f172dd4d89930b9074792c7f10dfcdc8 Mon Sep 17 00:00:00 2001 From: Uri Granta Date: Wed, 8 Oct 2025 09:11:24 +0100 Subject: [PATCH 1/4] Support generic transforms --- src/dataglasses/core.py | 8 ++++++++ tests/test_dataklasses.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/dataglasses/core.py b/src/dataglasses/core.py index 5ff573a..74afedc 100644 --- a/src/dataglasses/core.py +++ b/src/dataglasses/core.py @@ -107,6 +107,10 @@ def _from_dict( origin = get_origin(cls) + if origin in transform and not transformed: + input_type, fn = transform[origin] + return fn(_from_dict(input_type, value, datacls, transformed=True)) + if origin in (collections.abc.Sequence, list): if not isinstance(value, Sequence): raise TypeError( @@ -276,6 +280,10 @@ def _json_schema( origin = get_origin(cls) + if origin in transform and not transformed: + input_type, _ = transform[origin] + return _json_schema(input_type, datacls, transformed=True) + if origin in (collections.abc.Sequence, list): sequence_type = get_args(cls)[0] return {"type": "array", "items": _json_schema(sequence_type, datacls)} diff --git a/tests/test_dataklasses.py b/tests/test_dataklasses.py index 2be1f51..30f7485 100644 --- a/tests/test_dataklasses.py +++ b/tests/test_dataklasses.py @@ -446,6 +446,25 @@ def test_transform(transform: TransformRules, output: DataclassTransform) -> Non validate(value, schema) +@dataclass +class DataclassTransformGeneric: + a: set[str] + b: set[int] + c: set[float] + + +def test_transform_generic() -> None: + value = {"a": ["a", "b"], "b": [1, 2], "c": [0.5, 0.7]} + transform = { + set: (list[str | int], set), + set[float]: (list[float], lambda l: set(l) | {0.0}), + } + data = from_dict(DataclassTransformGeneric, value, transform=transform) + assert data == DataclassTransformGeneric({"a", "b"}, {1, 2}, {0.0, 0.5, 0.7}) + schema = to_json_schema(DataclassTransformGeneric, transform=transform) + validate(value, schema) + + # ================= # UNSUPPORTED TYPES # ================= From 9fbd3c042968c84f9bdac84e9ecaccdd96922f1e Mon Sep 17 00:00:00 2001 From: Uri Granta Date: Wed, 8 Oct 2025 09:28:04 +0100 Subject: [PATCH 2/4] Fix types --- src/dataglasses/core.py | 4 ++-- tests/test_dataklasses.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dataglasses/core.py b/src/dataglasses/core.py index 74afedc..780b569 100644 --- a/src/dataglasses/core.py +++ b/src/dataglasses/core.py @@ -105,7 +105,7 @@ def _from_dict( datacls, ) - origin = get_origin(cls) + origin = cast(type, get_origin(cls)) if origin in transform and not transformed: input_type, fn = transform[origin] @@ -278,7 +278,7 @@ def _json_schema( evaluated_type = cast(type, ref._evaluate(_globals, _locals, frozenset())) return _json_schema(evaluated_type, datacls) - origin = get_origin(cls) + origin = cast(type, get_origin(cls)) if origin in transform and not transformed: input_type, _ = transform[origin] diff --git a/tests/test_dataklasses.py b/tests/test_dataklasses.py index 30f7485..e59a76d 100644 --- a/tests/test_dataklasses.py +++ b/tests/test_dataklasses.py @@ -455,7 +455,7 @@ class DataclassTransformGeneric: def test_transform_generic() -> None: value = {"a": ["a", "b"], "b": [1, 2], "c": [0.5, 0.7]} - transform = { + transform: TransformRules = { set: (list[str | int], set), set[float]: (list[float], lambda l: set(l) | {0.0}), } From 4e50d69f60c5e3bbb4ea1558bd80ce8197c6ecde Mon Sep 17 00:00:00 2001 From: Uri Granta Date: Wed, 8 Oct 2025 09:30:07 +0100 Subject: [PATCH 3/4] Lint --- tests/test_dataklasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_dataklasses.py b/tests/test_dataklasses.py index e59a76d..30b16c0 100644 --- a/tests/test_dataklasses.py +++ b/tests/test_dataklasses.py @@ -457,7 +457,7 @@ def test_transform_generic() -> None: value = {"a": ["a", "b"], "b": [1, 2], "c": [0.5, 0.7]} transform: TransformRules = { set: (list[str | int], set), - set[float]: (list[float], lambda l: set(l) | {0.0}), + set[float]: (list[float], lambda lst: set(lst) | {0.0}), } data = from_dict(DataclassTransformGeneric, value, transform=transform) assert data == DataclassTransformGeneric({"a", "b"}, {1, 2}, {0.0, 0.5, 0.7}) From 9c249fbbcb02ed6724cd4c1d35b8e60a0f610648 Mon Sep 17 00:00:00 2001 From: Uri Granta Date: Wed, 8 Oct 2025 09:35:45 +0100 Subject: [PATCH 4/4] Bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1b4ed1d..9086d0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dataglasses" -version = "0.6.0" +version = "0.7.0" dependencies = [] requires-python = ">=3.10" authors = [{ name = "Uri Granta", email = "uri.granta+python@gmail.com" }]