sentinel
A back-port of Python 3.15's sentinel builtin for older Python versions.
On Python 3.15+, you can write:
MISSING = sentinel("MISSING")
DEFAULT = sentinel("DEFAULT", repr="<DEFAULT>")
This package provides the same behaviour on every supported Python version (3.10+) via a small, focused API.
Why?
Sentinel objects are an idiomatic way to distinguish “no value provided”
from “value is None” — useful for default arguments, optional caches,
and any function parameter that needs a tri-state (unset / None /
real value).
from sentinel import sentinel
MISSING = sentinel("MISSING")
def fetch(key: str, default=None):
"""``default`` may legitimately be ``None``; ``MISSING`` means
``fetch`` should compute the fallback itself."""
...
Installation
pip install pythonbackport-sentinel
Usage
Basic sentinel
from sentinel import sentinel
MISSING = sentinel("MISSING")
MISSING
# -> 'MISSING'
Custom representation
from sentinel import sentinel
MISSING = sentinel("MISSING", repr="<MISSING>")
MISSING
# -> '<MISSING>'
Truthy and unique
from sentinel import sentinel
A = sentinel("A")
B = sentinel("A") # a *different* object with the same name
assert A # truthy
assert A is A # identity equality
assert A is not B # even with the same name, A != B
Type hints with |
from sentinel import sentinel
MISSING = sentinel("MISSING")
def next_value(default: int | MISSING = MISSING):
...
Pickle support (module scope)
import pickle
from sentinel import sentinel
PICKLABLE = sentinel("PICKLABLE")
assert pickle.loads(pickle.dumps(PICKLABLE)) is PICKLABLE
Pickle support (class scope)
import pickle
from sentinel import sentinel
class Cls:
PICKLABLE = sentinel("Cls.PICKLABLE")
assert pickle.loads(pickle.dumps(Cls.PICKLABLE)) is Cls.PICKLABLE
API
sentinel(name, /, *, repr=None)
Return a new unique sentinel object.
name(positional-only, required) —str; the sentinel's name, used as the default representation.repr(keyword-only, optional) —str; an alternative representation. Defaults toname.
Attributes on the returned object
| Attribute | Read | Write | Description |
|---|---|---|---|
__name__ |
✅ | ❌ | The sentinel's name. |
__module__ |
✅ | ✅ | The module that created the sentinel (writable, str). |
Behaviour summary
- Always truthy (
bool(s) is True). - Equal only to itself; use the
isoperator. - Cannot be subclassed.
copy.copy(s)andcopy.deepcopy(s)both returns.s | TandT | sbuild a usable Union type for annotations.- Pickling preserves identity when the sentinel is defined at module or class scope with a name that matches the variable (or, for class scope, the qualified name).
Python 3.15+ native syntax
When you are running on Python 3.15+, sentinel is a true builtin.
The package's own API still works identically, so you can use either:
# Native (Python 3.15+ only):
MISSING = sentinel("MISSING")
# Cross-version equivalent via this package:
from sentinel import sentinel
MISSING = sentinel("MISSING")
Compatibility
- Python 3.10 through 3.15 (uses PEP 604 unions; falls back to
typing.Unionon older interpreters). - No third-party dependencies — uses only the standard library
(
pickle,sys,types).
Running the tests
python -m unittest test_sentinel.py -v
Retirement
This project will reach its end-of-life around October 1, 2031 — the
official EOL date of Python 3.15 — and the exact timeline could be
slightly delayed. We plan to ship the final stable release in November
2031. After this release, all support will cease and the repository
will be officially archived, as this library is developed solely to
bring sentinel() compatibility to Python 3.15 and older versions.
License
MIT
Metadata
Release files for pythonbackport-sentinel 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pythonbackport_sentinel-0.1.0.tar.gz | 10.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pythonbackport_sentinel-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.7 kB
Release files / pythonbackport_sentinel-0.1.0.tar.gz
| Download URL | pythonbackport_sentinel-0.1.0.tar.gz |
|---|---|
| Size | 10.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b9d800d8b758ed96ceb3f518212f301f52ca93b68934a73ab80dd70331a637cb
|
|
BLAKE2b-256 checksum How to use checksums |
e04cdc620dc4f47780017085fd43a828d521a488c9e3579390232ae06b805aee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / pythonbackport_sentinel-0.1.0-py3-none-any.whl
| Download URL | pythonbackport_sentinel-0.1.0-py3-none-any.whl |
|---|---|
| Size | 7.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
31833cd5826a2d6453b61c617b16cb20340355031269fe7945f475c8121ed7a9
|
|
BLAKE2b-256 checksum How to use checksums |
91bb77aac4fcaae81650bbb3cb7923ab401726ccff596ce17c0daa64b7bd0ac4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Security for pythonbackport-sentinel 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.