diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index e6af1bcb8..ffb3730b2 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -1317,7 +1317,12 @@ def is_set(self, name: str) -> bool: :class:`bool` `True` if field has been set, otherwise `False`. """ - return self.__raw_get(name) is not PLACEHOLDER + default = ( + PLACEHOLDER + if not self._betterproto.meta_by_field_name[name].optional + else None + ) + return self.__raw_get(name) is not default def serialized_on_wire(message: Message) -> bool: diff --git a/tests/test_features.py b/tests/test_features.py index 39fa5c280..ffbab475e 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -517,3 +517,15 @@ class Spam(betterproto.Message): assert spam == deepcopied assert spam is not deepcopied assert spam.baz is not deepcopied.baz + + +def test_is_set(): + @dataclass + class Spam(betterproto.Message): + foo: bool = betterproto.bool_field(1) + bar: Optional[int] = betterproto.int32_field(2, optional=True) + + assert not Spam().is_set("foo") + assert not Spam().is_set("bar") + assert Spam(foo=True).is_set("foo") + assert Spam(foo=True, bar=0).is_set("bar")