diff --git a/src/workos/__init__.py b/src/workos/__init__.py index a6f03134..faa676ad 100644 --- a/src/workos/__init__.py +++ b/src/workos/__init__.py @@ -16,7 +16,7 @@ ) from ._pagination import AsyncPage, ListMetadata, SyncPage from .public_client import create_public_client -from ._types import RequestOptions +from ._types import NOT_GIVEN, NotGiven, RequestOptions __all__ = [ "WorkOSClient", @@ -34,5 +34,7 @@ "AsyncPage", "ListMetadata", "RequestOptions", + "NOT_GIVEN", + "NotGiven", "create_public_client", ] diff --git a/src/workos/_types.py b/src/workos/_types.py index 3ae131ec..ece7b179 100644 --- a/src/workos/_types.py +++ b/src/workos/_types.py @@ -5,7 +5,7 @@ import sys from datetime import datetime from enum import Enum -from typing import Any, Dict, NoReturn, Protocol, TypedDict, TypeVar +from typing import Any, Dict, Literal, NoReturn, Protocol, TypedDict, TypeVar if sys.version_info >= (3, 11): from typing import Self @@ -35,6 +35,24 @@ def enum_value(value: Any) -> Any: return value.value if isinstance(value, Enum) else value +class NotGiven: + """Sentinel used as the default for nullable optional parameters. + + Distinguishes an omitted argument ("leave unchanged", not sent) from an + explicit ``None``, which clears the field by sending JSON ``null``. + Falsy so ``if not param`` reads naturally. + """ + + def __bool__(self) -> Literal[False]: + return False + + def __repr__(self) -> str: + return "NOT_GIVEN" + + +NOT_GIVEN = NotGiven() + + D = TypeVar("D", bound=Deserializable) diff --git a/tests/test_types.py b/tests/test_types.py new file mode 100644 index 00000000..cf937083 --- /dev/null +++ b/tests/test_types.py @@ -0,0 +1,24 @@ +from workos._types import NOT_GIVEN, NotGiven + + +class TestNotGiven: + """The NOT_GIVEN sentinel is the default for nullable optional params, + letting generated methods tell an omitted argument apart from an explicit + None (which clears the field via JSON null).""" + + def test_is_falsy(self): + assert not NOT_GIVEN + assert bool(NOT_GIVEN) is False + + def test_repr(self): + assert repr(NOT_GIVEN) == "NOT_GIVEN" + + def test_is_distinct_from_none(self): + assert NOT_GIVEN is not None + assert isinstance(NOT_GIVEN, NotGiven) + + def test_exported_from_public_namespace(self): + import workos + + assert workos.NOT_GIVEN is NOT_GIVEN + assert workos.NotGiven is NotGiven