maybe-missing
maybe-missing is a tiny typed helper for one annoyingly real distinction:
Nonemeans “the caller explicitly sent null”MISSINGmeans “the caller did not send this value at all”
That difference matters in patch APIs, dataclasses, settings layers, and anywhere a database column is nullable but an omitted field should mean “leave it alone”.
Why this exists
Python’s Optional[T] answers only one question: can the value be None?
It does not answer the other question: was there a value in the first place?
That becomes awkward fast:
- JSON
nullis a valid payload value - a nullable Postgres column may need to be set to
NULLintentionally - omitting a field in a PATCH request should usually mean “don’t update it”
- a dataclass default should sometimes mean “missing”, not “defaulted to null”
So this package gives you exactly two public names:
Maybe[T]MISSING
And then gets out of your way.
Installation
pip install maybe-missing
Usage
from maybe_missing import Maybe, MISSING
def update_display_name(display_name: Maybe[str | None] = MISSING) -> None:
if display_name is MISSING:
print("leave the existing value alone")
elif display_name is None:
print("explicitly store NULL")
else:
print(f"store {display_name!r}")
Dataclass example
from dataclasses import dataclass
from maybe_missing import Maybe, MISSING
@dataclass(slots=True)
class UserPatch:
nickname: Maybe[str | None] = MISSING
bio: Maybe[str | None] = MISSING
def apply_patch(patch: UserPatch) -> None:
if patch.nickname is not MISSING:
# update nickname to a string or to NULL
...
if patch.bio is not MISSING:
# update bio to a string or to NULL
...
API example
Imagine a request body for partial updates:
{
"nickname": null
}
This should mean:
nicknamewas provided- its value is explicitly
null - the server should write
NULL
While this body:
{}
should mean:
nicknamewas not provided- keep the current value as is
Maybe[T] helps model that cleanly in Python code.
There are only a couple of lines though
Yes.
There are only a couple of lines.
And that’s exactly why it’s more pleasant not to duplicate them across your projects and just do:
from maybe_missing import Maybe, MISSING
Isn’t it?
Typing
The package includes py.typed, so type checkers and IDEs can treat it as a typed distribution.
Compatibility
This package currently targets Python 3.10+.
Metadata
Release files for maybe-missing 0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| maybe_missing-0.1.tar.gz | 7.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| maybe_missing-0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.1 kB
Release files / maybe_missing-0.1.tar.gz
| Download URL | maybe_missing-0.1.tar.gz |
|---|---|
| Size | 7.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9edef67a472d55cb21d0c3d1a8425300673ef0a7b1d7a987336f084a86e9e93e
|
|
BLAKE2b-256 checksum How to use checksums |
cdd87db208f728f36abbfb3aa6b3eb75777e1897140d72663ddbc5dde99c870a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.12.12 Darwin/25.3.0
|
Release files / maybe_missing-0.1-py3-none-any.whl
| Download URL | maybe_missing-0.1-py3-none-any.whl |
|---|---|
| Size | 7.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
adaa61d379edd934a221104d65921c899f942b84e85ead5c31c9c3cbec16f6ee
|
|
BLAKE2b-256 checksum How to use checksums |
5b25e3e5fdc6faef63bf8b4ad59d6e5723eae90abc89657eee3728f0678a3c9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.12.12 Darwin/25.3.0
|