danielgtaylor / danielgtaylor/python-betterproto

OneOf and empty Message issue

Open
#360 4 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

When try to use empty Message (Message without fields) in one_of group, I cannot convert it to dict or bool.

Code to reproduce:
```proto
syntax = "proto3";

message CommandGetInfo
{}

message CommandGetName
{}

message Test {
oneof foo {
bool on = 1;
int32 count = 2;
string name = 3;
CommandGetInfo get_info = 4;
CommandGetName get_name = 5;
}
}
```

```python
import betterproto
from oneof import Test, CommandGetInfo, CommandGetName

def print_one_of(msg: Test):
def _to_bool(_value) -> bool:
return True if _value else False
msg_one_of = betterproto.which_one_of(msg, "foo")
print(f"msg={msg}")
print(f"msg_one_of={msg_one_of}")
print(f"msg to dict={msg.to_dict()}")
print(f"to bool test:")
print(f"\tmsg.on={_to_bool(msg.on)}")
print(f"\tmsg.count={_to_bool(msg.count)}")
print(f"\tmsg.name={_to_bool(msg.name)}")
print(f"\tmsg.get_info={_to_bool(msg.get_info)}")
print(f"\tmsg.get_name={_to_bool(msg.get_name)}")
print(f"to bytes: {bytes(msg)}")
print("\n")

test = Test()
print_one_of(msg=test)

test.get_name = CommandGetName()
print_one_of(msg=test)

test.on = True
print_one_of(msg=test)

test.count = 57
print_one_of(msg=test)

test.name = "Name"
print_one_of(msg=test)

test.get_info = CommandGetInfo()
print_one_of(msg=test)
```

Output:
```bash
msg=Test(on=False, count=0, name='', get_info=CommandGetInfo(), get_name=CommandGetName())
msg_one_of=('', None)
msg to dict={}
to bool test:
msg.on=False
msg.count=False
msg.name=False
msg.get_info=True
msg.get_name=True
to bytes: b''

msg=Test(on=False, count=0, name='', get_info=CommandGetInfo(), get_name=CommandGetName())
msg_one_of=('get_name', CommandGetName())
msg to dict={}
to bool test:
msg.on=False
msg.count=False
msg.name=False
msg.get_info=True
msg.get_name=True
to bytes: b''

msg=Test(on=True, count=0, name='', get_info=CommandGetInfo(), get_name=CommandGetName())
msg_one_of=('on', True)
msg to dict={'on': True}
to bool test:
msg.on=True
msg.count=False
msg.name=False
msg.get_info=True
msg.get_name=True
to bytes: b'\x08\x01'

msg=Test(on=False, count=57, name='', get_info=CommandGetInfo(), get_name=CommandGetName())
msg_one_of=('count', 57)
msg to dict={'count': 57}
to bool test:
msg.on=False
msg.count=True
msg.name=False
msg.get_info=True
msg.get_name=True
to bytes: b'\x109'

msg=Test(on=False, count=0, name='Name', get_info=CommandGetInfo(), get_name=CommandGetName())
msg_one_of=('name', 'Name')
msg to dict={'name': 'Name'}
to bool test:
msg.on=False
msg.count=False
msg.name=True
msg.get_info=True
msg.get_name=True
to bytes: b'\x1a\x04Name'

msg=Test(on=False, count=0, name='', get_info=CommandGetInfo(), get_name=CommandGetName())
msg_one_of=('get_info', CommandGetInfo())
msg to dict={}
to bool test:
msg.on=False
msg.count=False
msg.name=False
msg.get_info=True
msg.get_name=True
to bytes: b''
```

We can see that bool values are always set to True for empty proto messages, serializing them to dictionary gives empty dictionary, serializing to bytes also gives empty value.

I tested on python versions 3.9 and 3.10.
Betterproto: 1.2.5

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.