From 556607ede7a5236b399ab84b3845b454320fbd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Fern=C3=A1ndez?= <7312236+fernandezcuesta@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:10:01 +0200 Subject: [PATCH] fix: recursively convert struct to dict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> --- crossplane/function/resource.py | 5 ++++- tests/test_resource.py | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/crossplane/function/resource.py b/crossplane/function/resource.py index 194d7ea..11626f1 100644 --- a/crossplane/function/resource.py +++ b/crossplane/function/resource.py @@ -42,7 +42,10 @@ def struct_to_dict(s: structpb.Struct) -> dict: protobuf struct. This function makes it possible to convert resources to a dictionary. """ - return dict(s) + return { + k: (struct_to_dict(v) if isinstance(v, structpb.Struct) else v) + for k, v in s.items() + } @dataclasses.dataclass diff --git a/tests/test_resource.py b/tests/test_resource.py index 821d228..a7c4796 100644 --- a/tests/test_resource.py +++ b/tests/test_resource.py @@ -165,6 +165,43 @@ class TestResource(unittest.TestCase): dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got" ) + def test_struct_to_dict(self) -> None: + @dataclasses.dataclass + class TestCase: + reason: str + s: structpb.Struct + want: dict + + cases = [ + TestCase( + reason="Convert a struct with no fields to an empty dictionary.", + s=structpb.Struct(), + want={}, + ), + TestCase( + reason="Convert a struct with a single field to a dictionary.", + s=structpb.Struct(fields={"foo": structpb.Value(string_value="bar")}), + want={"foo": "bar"}, + ), + TestCase( + reason="Convert a nested struct to a dictionary.", + s=structpb.Struct( + fields={ + "foo": structpb.Value( + struct_value=structpb.Struct( + fields={"bar": structpb.Value(string_value="baz")} + ) + ) + } + ), + want={"foo": {"bar": "baz"}}, + ), + ] + + for case in cases: + got = resource.struct_to_dict(case.s) + self.assertEqual(case.want, got, "-want, +got") + if __name__ == "__main__": unittest.main()