Skip to content

Commit afa27a3

Browse files
authored
Merge pull request crossplane#102 from fernandezcuesta/main
fix: convert listValues to lists in nested structs
2 parents aaf3d08 + 54d6e39 commit afa27a3

File tree

5 files changed

+88
-10
lines changed

5 files changed

+88
-10
lines changed

crossplane/function/proto/v1/run_function_pb2_grpc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from crossplane.function.proto.v1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2
77

8-
GRPC_GENERATED_VERSION = '1.66.0'
8+
GRPC_GENERATED_VERSION = '1.67.0'
99
GRPC_VERSION = grpc.__version__
1010
_version_not_supported = False
1111

crossplane/function/proto/v1beta1/run_function_pb2_grpc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from crossplane.function.proto.v1beta1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2
77

8-
GRPC_GENERATED_VERSION = '1.66.0'
8+
GRPC_GENERATED_VERSION = '1.67.0'
99
GRPC_VERSION = grpc.__version__
1010
_version_not_supported = False
1111

crossplane/function/resource.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import datetime
1919

2020
import pydantic
21+
from google.protobuf import json_format
2122
from google.protobuf import struct_pb2 as structpb
2223

2324
import crossplane.function.proto.v1.run_function_pb2 as fnv1
@@ -65,9 +66,7 @@ def dict_to_struct(d: dict) -> structpb.Struct:
6566
function makes it possible to work with a Python dict, then convert it to a
6667
struct in a RunFunctionResponse.
6768
"""
68-
s = structpb.Struct()
69-
s.update(d)
70-
return s
69+
return json_format.ParseDict(d, structpb.Struct())
7170

7271

7372
def struct_to_dict(s: structpb.Struct) -> dict:
@@ -77,10 +76,7 @@ def struct_to_dict(s: structpb.Struct) -> dict:
7776
protobuf struct. This function makes it possible to convert resources to a
7877
dictionary.
7978
"""
80-
return {
81-
k: (struct_to_dict(v) if isinstance(v, structpb.Struct) else v)
82-
for k, v in s.items()
83-
}
79+
return json_format.MessageToDict(s, preserving_proto_field_name=True)
8480

8581

8682
@dataclasses.dataclass

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ classifiers = [
1717
]
1818

1919
dependencies = [
20-
"grpcio==1.*",
20+
"grpcio==1.67.0",
2121
"grpcio-reflection==1.*",
2222
"protobuf==5.29.3",
2323
"pydantic==2.*",

tests/test_resource.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,66 @@ class TestCase:
248248
dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got"
249249
)
250250

251+
def test_dict_to_struct(self) -> None:
252+
@dataclasses.dataclass
253+
class TestCase:
254+
reason: str
255+
d: dict
256+
want: structpb.Struct
257+
258+
cases = [
259+
TestCase(
260+
reason="Convert an empty dictionary to a struct.",
261+
d={},
262+
want=structpb.Struct(),
263+
),
264+
TestCase(
265+
reason="Convert a dictionary with a single field to a struct.",
266+
d={"foo": "bar"},
267+
want=structpb.Struct(
268+
fields={"foo": structpb.Value(string_value="bar")}
269+
),
270+
),
271+
TestCase(
272+
reason="Convert a nested dictionary to a struct.",
273+
d={"foo": {"bar": "baz"}},
274+
want=structpb.Struct(
275+
fields={
276+
"foo": structpb.Value(
277+
struct_value=structpb.Struct(
278+
fields={"bar": structpb.Value(string_value="baz")}
279+
)
280+
)
281+
}
282+
),
283+
),
284+
TestCase(
285+
reason="Convert a nested dictionary containing lists to a struct.",
286+
d={"foo": {"bar": ["baz", "qux"]}},
287+
want=structpb.Struct(
288+
fields={
289+
"foo": structpb.Value(
290+
struct_value=structpb.Struct(
291+
fields={
292+
"bar": structpb.Value(
293+
list_value=structpb.ListValue(
294+
values=[
295+
structpb.Value(string_value="baz"),
296+
structpb.Value(string_value="qux"),
297+
]
298+
)
299+
)
300+
}
301+
)
302+
)
303+
}
304+
),
305+
),
306+
]
307+
for case in cases:
308+
got = resource.dict_to_struct(case.d)
309+
self.assertEqual(case.want, got, "-want, +got")
310+
251311
def test_struct_to_dict(self) -> None:
252312
@dataclasses.dataclass
253313
class TestCase:
@@ -279,6 +339,28 @@ class TestCase:
279339
),
280340
want={"foo": {"bar": "baz"}},
281341
),
342+
TestCase(
343+
reason="Convert a nested struct containing ListValues to a dictionary.",
344+
s=structpb.Struct(
345+
fields={
346+
"foo": structpb.Value(
347+
struct_value=structpb.Struct(
348+
fields={
349+
"bar": structpb.Value(
350+
list_value=structpb.ListValue(
351+
values=[
352+
structpb.Value(string_value="baz"),
353+
structpb.Value(string_value="qux"),
354+
]
355+
)
356+
)
357+
}
358+
)
359+
)
360+
}
361+
),
362+
want={"foo": {"bar": ["baz", "qux"]}},
363+
),
282364
]
283365

284366
for case in cases:

0 commit comments

Comments
 (0)