diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index 1a7d2e3a..71c54714 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -339,6 +339,9 @@ def is_map( ) -> bool: """True if proto_field_obj is a map, otherwise False.""" if proto_field_obj.type == FieldDescriptorProtoType.TYPE_MESSAGE: + if not hasattr(parent_message, "nested_type"): + return False + # This might be a map... message_type = proto_field_obj.type_name.split(".").pop().lower() map_entry = f"{proto_field_obj.name.replace('_', '').lower()}entry" diff --git a/tests/inputs/entry/entry.proto b/tests/inputs/entry/entry.proto new file mode 100644 index 00000000..3f2af4d1 --- /dev/null +++ b/tests/inputs/entry/entry.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package entry; + +// This is a minimal example of a repeated message field that caused issues when +// checking whether a message is a map. +// +// During the check wheter a field is a "map", the string "entry" is added to +// the field name, checked against the type name and then further checks are +// made against the nested type of a parent message. In this edge-case, the +// first check would pass even though it shouldn't and that would cause an +// error because the parent type does not have a "nested_type" attribute. + +message Test { + repeated ExportEntry export = 1; +} + +message ExportEntry { + string name = 1; +}