From c0c34eeaadabe1cca5f588653f6e00e8917d52a9 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Thu, 18 Jun 2026 17:03:38 +0200 Subject: [PATCH 1/2] fix: resolve TypeAliasType before issubclass in pack_union (#330) --- mashumaro/core/meta/types/pack.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mashumaro/core/meta/types/pack.py b/mashumaro/core/meta/types/pack.py index 91d33b9f..7673be67 100644 --- a/mashumaro/core/meta/types/pack.py +++ b/mashumaro/core/meta/types/pack.py @@ -292,6 +292,12 @@ def pack_any(spec: ValueSpec) -> Expression | None: return spec.expression +def _resolve_type_alias_type(t: type) -> type: + while is_type_alias_type(t): + t = t.__value__ # type: ignore[attr-defined] + return t + + def pack_union( spec: ValueSpec, args: tuple[type, ...], prefix: str = "union" ) -> Expression: @@ -330,7 +336,7 @@ def pack_union( ) if packer not in packers: if packer == "value" and not issubclass( - get_type_origin(type_arg), Collection + get_type_origin(_resolve_type_alias_type(type_arg)), Collection ): packers.insert(0, packer) else: @@ -359,7 +365,7 @@ def pack_union( else: packer_arg_type_check = f"is {packer_arg_type_names[0]}" if packer == "value" and not issubclass( - packer_arg_type, Collection + _resolve_type_alias_type(packer_arg_type), Collection ): with lines.indent( f"if value.__class__ {packer_arg_type_check}:" From 64923fe18516389d7a3244e4728b1cebf9162174 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Sat, 20 Jun 2026 23:49:38 +0200 Subject: [PATCH 2/2] Cover PEP 695 alias union value packing --- mashumaro/core/meta/types/pack.py | 1 + tests/test_pep_695.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/mashumaro/core/meta/types/pack.py b/mashumaro/core/meta/types/pack.py index 7673be67..f1928a26 100644 --- a/mashumaro/core/meta/types/pack.py +++ b/mashumaro/core/meta/types/pack.py @@ -350,6 +350,7 @@ def pack_union( for packer in packers: packer_arg_type_names = [] for packer_arg_type in packer_arg_types[packer]: + packer_arg_type = _resolve_type_alias_type(packer_arg_type) if is_generic(packer_arg_type): packer_arg_type = get_type_origin(packer_arg_type) packer_arg_type_name = clean_id(type_name(packer_arg_type)) diff --git a/tests/test_pep_695.py b/tests/test_pep_695.py index 08c6ebef..040a7893 100644 --- a/tests/test_pep_695.py +++ b/tests/test_pep_695.py @@ -16,6 +16,8 @@ GenericPassthroughSerializable, ) +type ScalarAlias = int + def test_type_alias_type_with_dataclass_dict_mixin(): type MyDate = date @@ -39,6 +41,15 @@ def test_type_alias_type_with_codecs(): assert encoder.encode(obj) == "2024-04-15" +def test_type_alias_type_with_union_value_packer(): + @dataclass + class MyClass(DataClassDictMixin): + x: ScalarAlias | list[int] + + assert MyClass(1).to_dict() == {"x": 1} + assert MyClass([1, 2]).to_dict() == {"x": [1, 2]} + + @pytest.mark.parametrize("deferred_ann", [False, True]) def test_pep695_generic_serialization_strategy(deferred_ann): if deferred_ann: