danielgtaylor / danielgtaylor/python-betterproto

Proposal to add default values in deserialisation

Open
#356 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
1.8k
Forks
234
PR merge metrics
No merged PRs in 30d

Description

[Protobuf does not serialise default values](https://developers.google.com/protocol-buffers/docs/proto3#default), however the betterproto objects could retain them.

Consider:
```protobuf
enum MyType {
A = 0;
B = 1;
}

message MyMessage {
string name = 1;
MyType type = 2;
}
```

I create a new message with the default enum:
```
m = api.MyMessage(name='foo', type=api.MyType(0))
```

If I send this message, and the receiver creates a betterproto message, they get:
```
api.MyMessage(name='foo')
```

Fortunately betterproto has equality between these messages, even though in the latter type is not specified.

However, this is not particularly easy to find without a bit of digging. I believe it would be simpler to just add the default values when deserialising, which is actually pretty simple:

```python
def _fill_defaults(message: api.betterproto.Message) -> api.betterproto.Message:
message_keys = {}
for k in message.__dict__.keys():
if k not in ["_serialized_on_wire", "_unknown_fields", "_group_current"]:
current_value = getattr(message, k)
if not current_value:
message_keys[k] = message._get_field_default(k)
else:
message_keys[k] = current_value
return message.__class__(**message_keys)
```

I'm sure there is a neater way of handling the internal attributes e.g. `_serialise_on_wire`.

With the above, the receiver would have the same object as the sender, which is more intuitive.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.