Implement Message.__bool__ (#142)

* Implement Message.__bool__ with similar semantics to a collection, such that any value being set on the message (i.e. having a non-default value) make the Message value truthy .

Co-authored-by: nat <n@natn.me>
This commit is contained in:
James 2020-11-24 18:35:09 +00:00 committed by GitHub
parent a8a082e4e7
commit 69dfe9cafc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 1 deletions

View File

@ -12,7 +12,7 @@ Message
.. autoclass:: betterproto.Message .. autoclass:: betterproto.Message
:members: :members:
:special-members: __bytes__ :special-members: __bytes__, __bool__
.. autofunction:: betterproto.serialized_on_wire .. autofunction:: betterproto.serialized_on_wire

View File

@ -516,6 +516,10 @@ class Message(ABC):
.. describe:: bytes(x) .. describe:: bytes(x)
Calls :meth:`__bytes__`. Calls :meth:`__bytes__`.
.. describe:: bool(x)
Calls :meth:`__bool__`.
""" """
_serialized_on_wire: bool _serialized_on_wire: bool
@ -606,6 +610,14 @@ class Message(ABC):
super().__setattr__(attr, value) super().__setattr__(attr, value)
def __bool__(self) -> bool:
"""True if the Message has any fields with non-default values."""
return any(
self.__raw_get(field_name)
not in (PLACEHOLDER, self._get_field_default(field_name))
for field_name in self._betterproto.meta_by_field_name
)
@property @property
def _betterproto(self) -> ProtoClassMetadata: def _betterproto(self) -> ProtoClassMetadata:
""" """

View File

@ -365,3 +365,33 @@ def test_message_repr():
assert repr(Test(name="Loki")) == "Test(name='Loki')" assert repr(Test(name="Loki")) == "Test(name='Loki')"
assert repr(Test(child=Test(), name="Loki")) == "Test(name='Loki', child=Test())" assert repr(Test(child=Test(), name="Loki")) == "Test(name='Loki', child=Test())"
def test_bool():
"""Messages should evaluate similarly to a collection
>>> test = []
>>> bool(test)
... False
>>> test.append(1)
>>> bool(test)
... True
>>> del test[0]
>>> bool(test)
... False
"""
@dataclass
class Falsy(betterproto.Message):
pass
@dataclass
class Truthy(betterproto.Message):
bar: int = betterproto.int32_field(1)
assert not Falsy()
t = Truthy()
assert not t
t.bar = 1
assert t
t.bar = 0
assert not t