Allow templates for enabling conditions (#117047)

* Allow templates for enabling automation conditions

* Use `cv.template` instead of `cv.template_complex`
pull/111426/head^2
Matthias Alphart 2024-05-15 21:03:28 +02:00 committed by GitHub
parent aa2485c7b9
commit 076f57ee07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 11 deletions

View File

@ -227,16 +227,25 @@ async def async_from_config(
factory = platform.async_condition_from_config
# Check if condition is not enabled
if not config.get(CONF_ENABLED, True):
if CONF_ENABLED in config:
enabled = config[CONF_ENABLED]
if isinstance(enabled, Template):
try:
enabled = enabled.async_render(limited=True)
except TemplateError as err:
raise HomeAssistantError(
f"Error rendering condition enabled template: {err}"
) from err
if not enabled:
@trace_condition_function
def disabled_condition(
hass: HomeAssistant, variables: TemplateVarsType = None
) -> bool | None:
"""Condition not enabled, will act as if it didn't exist."""
return None
@trace_condition_function
def disabled_condition(
hass: HomeAssistant, variables: TemplateVarsType = None
) -> bool | None:
"""Condition not enabled, will act as if it didn't exist."""
return None
return disabled_condition
return disabled_condition
# Check for partials to properly determine if coroutine function
check_factory = factory

View File

@ -1356,7 +1356,7 @@ NUMERIC_STATE_THRESHOLD_SCHEMA = vol.Any(
CONDITION_BASE_SCHEMA = {
vol.Optional(CONF_ALIAS): string,
vol.Optional(CONF_ENABLED): boolean,
vol.Optional(CONF_ENABLED): vol.Any(boolean, template),
}
NUMERIC_STATE_CONDITION_SCHEMA = vol.All(

View File

@ -3382,10 +3382,36 @@ async def test_platform_async_validate_condition_config(hass: HomeAssistant) ->
device_automation_validate_condition_mock.assert_awaited()
async def test_disabled_condition(hass: HomeAssistant) -> None:
@pytest.mark.parametrize("enabled_value", [True, "{{ 1 == 1 }}"])
async def test_enabled_condition(
hass: HomeAssistant, enabled_value: bool | str
) -> None:
"""Test an explicitly enabled condition."""
config = {
"enabled": enabled_value,
"condition": "state",
"entity_id": "binary_sensor.test",
"state": "on",
}
config = cv.CONDITION_SCHEMA(config)
config = await condition.async_validate_condition_config(hass, config)
test = await condition.async_from_config(hass, config)
hass.states.async_set("binary_sensor.test", "on")
assert test(hass) is True
# Still passes, condition is not enabled
hass.states.async_set("binary_sensor.test", "off")
assert test(hass) is False
@pytest.mark.parametrize("enabled_value", [False, "{{ 1 == 9 }}"])
async def test_disabled_condition(
hass: HomeAssistant, enabled_value: bool | str
) -> None:
"""Test a disabled condition returns none."""
config = {
"enabled": False,
"enabled": enabled_value,
"condition": "state",
"entity_id": "binary_sensor.test",
"state": "on",
@ -3402,6 +3428,21 @@ async def test_disabled_condition(hass: HomeAssistant) -> None:
assert test(hass) is None
async def test_condition_enabled_template_limited(hass: HomeAssistant) -> None:
"""Test conditions enabled template raises for non-limited template uses."""
config = {
"enabled": "{{ states('sensor.limited') }}",
"condition": "state",
"entity_id": "binary_sensor.test",
"state": "on",
}
config = cv.CONDITION_SCHEMA(config)
config = await condition.async_validate_condition_config(hass, config)
with pytest.raises(HomeAssistantError):
await condition.async_from_config(hass, config)
async def test_and_condition_with_disabled_condition(hass: HomeAssistant) -> None:
"""Test the 'and' condition with one of the conditions disabled."""
config = {