Skip to content
This repository was archived by the owner on Jun 9, 2025. It is now read-only.

Commit 7abf41d

Browse files
committed
Fix unwrap in maps
1 parent 1cbbba6 commit 7abf41d

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

src/betterproto2_compiler/known_types/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,14 @@
9797
# A wrapped type is the type of a message that is automatically replaced by a known Python type.
9898
WRAPPED_TYPES: dict[tuple[str, str], str] = {
9999
("google.protobuf", "BoolValue"): "bool",
100+
("google.protobuf", "Int32Value"): "int",
101+
("google.protobuf", "Int64Value"): "int",
102+
("google.protobuf", "UInt32Value"): "int",
103+
("google.protobuf", "UInt64Value"): "int",
104+
("google.protobuf", "FloatValue"): "float",
105+
("google.protobuf", "DoubleValue"): "float",
100106
("google.protobuf", "StringValue"): "str",
107+
("google.protobuf", "BytesValue"): "bytes",
101108
("google.protobuf", "Timestamp"): "datetime.datetime",
102109
("google.protobuf", "Duration"): "datetime.timedelta",
103110
}

src/betterproto2_compiler/plugin/models.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ def proto_name(self) -> str:
373373

374374
@property
375375
def is_wrapped(self) -> bool:
376+
assert self.field_type == FieldDescriptorProtoType.TYPE_MESSAGE
376377
type_package, type_name = parse_source_type_name(self.proto_obj.type_name, self.output_file.parent_request)
377378

378379
return (type_package, type_name) in WRAPPED_TYPES
@@ -441,6 +442,8 @@ def betterproto_field_args(self) -> list[str]:
441442
class MapEntryCompiler(FieldCompiler):
442443
py_k_type: str = ""
443444
py_v_type: str = ""
445+
unwrap_v: str | None = None
446+
444447
proto_k_type: str = ""
445448
proto_v_type: str = ""
446449

@@ -450,18 +453,30 @@ def ready(self) -> None:
450453
for nested in self.message.proto_obj.nested_type:
451454
if nested.name.replace("_", "").lower() == map_entry and unwrap(nested.options).map_entry:
452455
# Get Python types
456+
assert nested.field[0].name == "key"
453457
self.py_k_type = FieldCompiler(
454458
source_file=self.source_file,
455459
proto_obj=nested.field[0], # key
456460
path=[],
457461
message=self.message,
458462
).py_type
459-
self.py_v_type = FieldCompiler(
463+
464+
assert nested.field[1].name == "value"
465+
value_field_compiler = FieldCompiler(
460466
source_file=self.source_file,
461467
proto_obj=nested.field[1], # value
462468
path=[],
463469
message=self.message,
464-
).py_type
470+
)
471+
472+
self.py_v_type = value_field_compiler.py_type
473+
if (
474+
value_field_compiler.field_type == FieldDescriptorProtoType.TYPE_MESSAGE
475+
and value_field_compiler.is_wrapped
476+
):
477+
self.unwrap_v = value_field_compiler.unwrapped_py_type
478+
else:
479+
self.unwrap_v = None
465480

466481
# Get proto types
467482
self.proto_k_type = unwrap(FieldDescriptorProtoType(nested.field[0].type).name)
@@ -472,11 +487,19 @@ def ready(self) -> None:
472487

473488
def get_field_string(self) -> str:
474489
"""Construct string representation of this field as a field."""
490+
proto_type_1 = f"betterproto2.{self.proto_k_type}"
491+
proto_type_2 = f"betterproto2.{self.proto_v_type}"
492+
493+
unwrap_2 = ""
494+
if self.unwrap_v:
495+
unwrap_2 = f", unwrap_2=lambda: {self.unwrap_v}"
496+
475497
betterproto_field_type = (
476-
f"betterproto2.field({self.proto_obj.number}, "
498+
"betterproto2.field("
499+
f"{self.proto_obj.number}, "
477500
"betterproto2.TYPE_MAP, "
478-
f"map_types=(betterproto2.{self.proto_k_type}, "
479-
f"betterproto2.{self.proto_v_type}))"
501+
f"map_meta=betterproto2.map_meta({proto_type_1}, {proto_type_2}{unwrap_2})"
502+
")"
480503
)
481504
if self.py_name in dir(builtins):
482505
self.message.builtins_types.add(self.py_name)

0 commit comments

Comments
 (0)