Sentinels Library
The `sentinels` module is a small utility providing a `Sentinel` class, along with useful instances for creating unique singleton objects. These objects serve as special markers, often used as default values for function arguments or to denote the absence of a value, especially when `None` is a valid input. The current version is 1.1.1, and it appears to be actively maintained with a recent release in August 2025.
Warnings
- gotcha This library (`sentinels`, plural) provides generic sentinel objects. Do not confuse it with other similarly named, but unrelated, libraries like `sentinel-sdk` (blockchain), `sentinelsat` (satellite data), or `sentinel` (a different sentinel creation utility that uses `sentinel.create()`).
- gotcha Always compare sentinel objects using the `is` operator, not `==`. Sentinels are designed to be singletons, and `is` checks for object identity, which is crucial for their intended use. Using `==` might lead to unexpected behavior if another object coincidentally evaluates as equal.
- gotcha When creating a custom `Sentinel` for use with type checkers (e.g., `MY_SENTINEL = Sentinel('MY_SENTINEL')`), ensure the string name passed to the constructor exactly matches the variable name. This convention is important for proper type inference and narrowing by tools like MyPy.
Install
-
pip install sentinels
Imports
- Sentinel
from sentinels import Sentinel
- NOTHING
from sentinels import NOTHING
Quickstart
from sentinels import NOTHING, Sentinel
class MyDict(dict):
def get_default_or_raise(self, key, default=NOTHING):
returned = self.get(key, default)
if returned is NOTHING:
raise KeyError(key)
return returned
# Example usage:
d = MyDict({"valid_none": None, "valid_zero": 0})
# Key exists with a valid None value
print(f"'valid_none' value: {d.get_default_or_raise('valid_none', default=None)}")
# Key exists with a valid zero value
print(f"'valid_zero' value: {d.get_default_or_raise('valid_zero')}")
# Key does not exist, uses NOTHING as default, raises KeyError
try:
d.get_default_or_raise("non_existent_key")
except KeyError as e:
print(f"Caught expected error: {e}")
# Create a custom sentinel
MISSING_VALUE = Sentinel('MISSING_VALUE')
def my_function(arg=MISSING_VALUE):
if arg is MISSING_VALUE:
print("Argument was not provided.")
else:
print(f"Argument provided: {arg}")
my_function()
my_function("hello")