diff --git a/esphome/helpers.py b/esphome/helpers.py index 7aa1a9a88c..b3102ca277 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -31,6 +31,13 @@ SockAddr = IPv4SockAddr | IPv6SockAddr _LOGGER = logging.getLogger(__name__) +# cv.boolean's closed spelling tables, shared with the env-knob parsing below +TRUTHY_BOOL_STRINGS = frozenset({"true", "yes", "on", "enable"}) +FALSY_BOOL_STRINGS = frozenset({"false", "no", "off", "disable"}) +# cv.boolean's spelling tables plus the 1/0 env convention +TRUTHY_ENV_STRINGS = TRUTHY_BOOL_STRINGS | {"1"} +FALSY_ENV_STRINGS = FALSY_BOOL_STRINGS | {"0"} + IS_MACOS = platform.system() == "Darwin" IS_WINDOWS = platform.system() == "Windows" IS_LINUX = platform.system() == "Linux" @@ -395,12 +402,14 @@ def sort_ip_addresses(address_list: list[str]) -> list[str]: def get_bool_env(var, default=False): + """Read a boolean env var: the ``cv.boolean`` spellings plus ``1``/``0``; + anything else falls through to ``bool(value)``.""" value = os.getenv(var, default) if isinstance(value, str): value = value.lower() - if value in ["1", "true"]: + if value in TRUTHY_ENV_STRINGS: return True - if value in ["0", "false"]: + if value in FALSY_ENV_STRINGS: return False return bool(value) diff --git a/tests/unit_tests/test_helpers.py b/tests/unit_tests/test_helpers.py index eaa7d5a8dc..3160469063 100644 --- a/tests/unit_tests/test_helpers.py +++ b/tests/unit_tests/test_helpers.py @@ -171,6 +171,13 @@ def test_is_ip_address__valid(value): ("FOO", "fAlSe", True, False), ("FOO", "Yes", False, True), ("FOO", "123", False, True), + # cv.boolean's spellings; falsy rows use default=True on purpose + ("FOO", "on", False, True), + ("FOO", "enable", False, True), + ("FOO", "no", True, False), + ("FOO", "off", True, False), + ("FOO", "OFF", True, False), + ("FOO", "Disable", True, False), ), ) def test_get_bool_env(monkeypatch, var, value, default, expected):