{"id":2280,"library":"sentinels","title":"Sentinels Library","description":"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.","status":"active","version":"1.1.1","language":"en","source_language":"en","source_url":"https://github.com/vmalloc/sentinels","tags":["utility","sentinel","singleton","type-hinting"],"install":[{"cmd":"pip install sentinels","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"note":"Used to create your own custom sentinel objects.","symbol":"Sentinel","correct":"from sentinels import Sentinel"},{"note":"A pre-defined sentinel often used as a default value when `None` is a valid input.","symbol":"NOTHING","correct":"from sentinels import NOTHING"}],"quickstart":{"code":"from sentinels import NOTHING, Sentinel\n\nclass MyDict(dict):\n    def get_default_or_raise(self, key, default=NOTHING):\n        returned = self.get(key, default)\n        if returned is NOTHING:\n            raise KeyError(key)\n        return returned\n\n# Example usage:\nd = MyDict({\"valid_none\": None, \"valid_zero\": 0})\n\n# Key exists with a valid None value\nprint(f\"'valid_none' value: {d.get_default_or_raise('valid_none', default=None)}\")\n\n# Key exists with a valid zero value\nprint(f\"'valid_zero' value: {d.get_default_or_raise('valid_zero')}\")\n\n# Key does not exist, uses NOTHING as default, raises KeyError\ntry:\n    d.get_default_or_raise(\"non_existent_key\")\nexcept KeyError as e:\n    print(f\"Caught expected error: {e}\")\n\n# Create a custom sentinel\nMISSING_VALUE = Sentinel('MISSING_VALUE')\ndef my_function(arg=MISSING_VALUE):\n    if arg is MISSING_VALUE:\n        print(\"Argument was not provided.\")\n    else:\n        print(f\"Argument provided: {arg}\")\n\nmy_function()\nmy_function(\"hello\")","lang":"python","description":"This quickstart demonstrates how to use the pre-defined `NOTHING` sentinel for dictionary operations where `None` is a valid value, and how to create a custom sentinel using the `Sentinel` class. It highlights the use of `is` for comparison, a key characteristic of sentinel objects."},"warnings":[{"fix":"Ensure you are importing from the correct package `sentinels` and using `Sentinel` or pre-defined constants like `NOTHING` directly from it.","message":"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()`).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Replace `if value == NOTHING:` with `if value is NOTHING:`.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use `MY_SENTINEL = Sentinel('MY_SENTINEL')` instead of `MY_SENTINEL = Sentinel('SOME_OTHER_NAME')`.","message":"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.","severity":"gotcha","affected_versions":"All versions (relevant for users leveraging type hints)"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}