Merge pull request #102 from fernandezcuesta/main

fix: convert listValues to lists in nested structs
This commit is contained in:
Bob Haddleton 2025-02-01 15:16:07 -06:00 committed by GitHub
commit afa27a3121
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 88 additions and 10 deletions

View File

@ -5,7 +5,7 @@ import warnings
from crossplane.function.proto.v1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2 from crossplane.function.proto.v1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2
GRPC_GENERATED_VERSION = '1.66.0' GRPC_GENERATED_VERSION = '1.67.0'
GRPC_VERSION = grpc.__version__ GRPC_VERSION = grpc.__version__
_version_not_supported = False _version_not_supported = False

View File

@ -5,7 +5,7 @@ import warnings
from crossplane.function.proto.v1beta1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2 from crossplane.function.proto.v1beta1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2
GRPC_GENERATED_VERSION = '1.66.0' GRPC_GENERATED_VERSION = '1.67.0'
GRPC_VERSION = grpc.__version__ GRPC_VERSION = grpc.__version__
_version_not_supported = False _version_not_supported = False

View File

@ -18,6 +18,7 @@ import dataclasses
import datetime import datetime
import pydantic import pydantic
from google.protobuf import json_format
from google.protobuf import struct_pb2 as structpb from google.protobuf import struct_pb2 as structpb
import crossplane.function.proto.v1.run_function_pb2 as fnv1 import crossplane.function.proto.v1.run_function_pb2 as fnv1
@ -65,9 +66,7 @@ def dict_to_struct(d: dict) -> structpb.Struct:
function makes it possible to work with a Python dict, then convert it to a function makes it possible to work with a Python dict, then convert it to a
struct in a RunFunctionResponse. struct in a RunFunctionResponse.
""" """
s = structpb.Struct() return json_format.ParseDict(d, structpb.Struct())
s.update(d)
return s
def struct_to_dict(s: structpb.Struct) -> dict: def struct_to_dict(s: structpb.Struct) -> dict:
@ -77,10 +76,7 @@ def struct_to_dict(s: structpb.Struct) -> dict:
protobuf struct. This function makes it possible to convert resources to a protobuf struct. This function makes it possible to convert resources to a
dictionary. dictionary.
""" """
return { return json_format.MessageToDict(s, preserving_proto_field_name=True)
k: (struct_to_dict(v) if isinstance(v, structpb.Struct) else v)
for k, v in s.items()
}
@dataclasses.dataclass @dataclasses.dataclass

View File

@ -17,7 +17,7 @@ classifiers = [
] ]
dependencies = [ dependencies = [
"grpcio==1.*", "grpcio==1.67.0",
"grpcio-reflection==1.*", "grpcio-reflection==1.*",
"protobuf==5.29.3", "protobuf==5.29.3",
"pydantic==2.*", "pydantic==2.*",

View File

@ -248,6 +248,66 @@ class TestResource(unittest.TestCase):
dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got" dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got"
) )
def test_dict_to_struct(self) -> None:
@dataclasses.dataclass
class TestCase:
reason: str
d: dict
want: structpb.Struct
cases = [
TestCase(
reason="Convert an empty dictionary to a struct.",
d={},
want=structpb.Struct(),
),
TestCase(
reason="Convert a dictionary with a single field to a struct.",
d={"foo": "bar"},
want=structpb.Struct(
fields={"foo": structpb.Value(string_value="bar")}
),
),
TestCase(
reason="Convert a nested dictionary to a struct.",
d={"foo": {"bar": "baz"}},
want=structpb.Struct(
fields={
"foo": structpb.Value(
struct_value=structpb.Struct(
fields={"bar": structpb.Value(string_value="baz")}
)
)
}
),
),
TestCase(
reason="Convert a nested dictionary containing lists to a struct.",
d={"foo": {"bar": ["baz", "qux"]}},
want=structpb.Struct(
fields={
"foo": structpb.Value(
struct_value=structpb.Struct(
fields={
"bar": structpb.Value(
list_value=structpb.ListValue(
values=[
structpb.Value(string_value="baz"),
structpb.Value(string_value="qux"),
]
)
)
}
)
)
}
),
),
]
for case in cases:
got = resource.dict_to_struct(case.d)
self.assertEqual(case.want, got, "-want, +got")
def test_struct_to_dict(self) -> None: def test_struct_to_dict(self) -> None:
@dataclasses.dataclass @dataclasses.dataclass
class TestCase: class TestCase:
@ -279,6 +339,28 @@ class TestResource(unittest.TestCase):
), ),
want={"foo": {"bar": "baz"}}, want={"foo": {"bar": "baz"}},
), ),
TestCase(
reason="Convert a nested struct containing ListValues to a dictionary.",
s=structpb.Struct(
fields={
"foo": structpb.Value(
struct_value=structpb.Struct(
fields={
"bar": structpb.Value(
list_value=structpb.ListValue(
values=[
structpb.Value(string_value="baz"),
structpb.Value(string_value="qux"),
]
)
)
}
)
)
}
),
want={"foo": {"bar": ["baz", "qux"]}},
),
] ]
for case in cases: for case in cases: