From 0f218e4f34694508bcdd2e4d49f270db542eacc1 Mon Sep 17 00:00:00 2001 From: giadarol Date: Thu, 1 Oct 2026 17:27:51 +0200 Subject: [PATCH] Fix default filtering for scalar raw unions in to_dict --- tests/test_hybrid_class.py | 22 ++++++++++++++++++++++ xobjects/hybrid_class.py | 8 +++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/test_hybrid_class.py b/tests/test_hybrid_class.py index f4b0676f..bdd5e10b 100644 --- a/tests/test_hybrid_class.py +++ b/tests/test_hybrid_class.py @@ -332,6 +332,28 @@ class A(xo.HybridClass): assert b_dict == {} +def test_to_dict_scalar_raw_union_defaults(): + class ScalarUnion(xo.RawUnion): + scalar = xo.Float64 + bits = xo.UInt64 + + @classmethod + def _from_buffer(cls, buffer, offset=0, container=None): + return xo.Float64._from_buffer(buffer, offset) + + class A(xo.HybridClass): + _xofields = { + "a": ScalarUnion, + "b": xo.Field(ScalarUnion, default=2.5), + "c": xo.Field(ScalarUnion, default_factory=lambda: 3.5), + } + + assert A().to_dict() == {"__class__": "A"} + values = {"__class__": "A", "a": 1.5, "b": 0.0, "c": 0.0} + for copy_to_cpu in (True, False): + assert A.from_dict(values).to_dict(copy_to_cpu=copy_to_cpu) == values + + def test_to_dict_python_vars(): class TD(xo.HybridClass): _xofields = { diff --git a/xobjects/hybrid_class.py b/xobjects/hybrid_class.py index f83086cd..3fffd073 100644 --- a/xobjects/hybrid_class.py +++ b/xobjects/hybrid_class.py @@ -10,6 +10,7 @@ from .struct import Struct from .typeutils import context_default from .ref import Ref +from .raw_union import RawUnion class _FieldOfDressed: @@ -297,7 +298,12 @@ def to_dict(self, copy_to_cpu=True): defaults[field.name] = dft continue try: - defaults[field.name] = field.get_default() + default = field.get_default() + if isinstance(default, RawUnion): + # A raw union can expose a scalar when read as a field. + default = type(default)._from_buffer( + default._buffer, default._offset) + defaults[field.name] = default except (TypeError, ValueError): # The above can fail with different error types # if a field type is dynamic.