From 69dfe9cafc26248029502df865d2da63a977562c Mon Sep 17 00:00:00 2001 From: James <50501825+Gobot1234@users.noreply.github.com> Date: Tue, 24 Nov 2020 18:35:09 +0000 Subject: [PATCH] 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 --- docs/api.rst | 2 +- src/betterproto/__init__.py | 12 ++++++++++++ tests/test_features.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index ceae2d2..9f99b51 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -12,7 +12,7 @@ Message .. autoclass:: betterproto.Message :members: - :special-members: __bytes__ + :special-members: __bytes__, __bool__ .. autofunction:: betterproto.serialized_on_wire diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index e6daeb3..b26ec4b 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -516,6 +516,10 @@ class Message(ABC): .. describe:: bytes(x) Calls :meth:`__bytes__`. + + .. describe:: bool(x) + + Calls :meth:`__bool__`. """ _serialized_on_wire: bool @@ -606,6 +610,14 @@ class Message(ABC): 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 def _betterproto(self) -> ProtoClassMetadata: """ diff --git a/tests/test_features.py b/tests/test_features.py index f548264..ef33d87 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -365,3 +365,33 @@ def test_message_repr(): assert repr(Test(name="Loki")) == "Test(name='Loki')" 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