Add a syntax for merging lists of triggers (#117698)

* Add a syntax for merging lists of triggers

* Updating to the new syntax

* Update homeassistant/helpers/config_validation.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* fix suggestion

* update test and add comments

* not actually json

* move test to new file

* update tests

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
pull/125587/head^2
karwosts 2024-09-09 04:51:32 -07:00 committed by GitHub
parent 06e876aee0
commit 056e6eae82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 159 additions and 1 deletions

View File

@ -282,6 +282,7 @@ CONF_THEN: Final = "then"
CONF_TIMEOUT: Final = "timeout"
CONF_TIME_ZONE: Final = "time_zone"
CONF_TOKEN: Final = "token"
CONF_TRIGGERS: Final = "triggers"
CONF_TRIGGER_TIME: Final = "trigger_time"
CONF_TTL: Final = "ttl"
CONF_TYPE: Final = "type"

View File

@ -81,6 +81,7 @@ from homeassistant.const import (
CONF_TARGET,
CONF_THEN,
CONF_TIMEOUT,
CONF_TRIGGERS,
CONF_UNTIL,
CONF_VALUE_TEMPLATE,
CONF_VARIABLES,
@ -1781,6 +1782,19 @@ TRIGGER_BASE_SCHEMA = vol.Schema(
_base_trigger_validator_schema = TRIGGER_BASE_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
def _base_trigger_list_flatten(triggers: list[Any]) -> list[Any]:
"""Flatten trigger arrays containing 'triggers:' sublists into a single list of triggers."""
flatlist = []
for t in triggers:
if CONF_TRIGGERS in t and len(t.keys()) == 1:
triggerlist = ensure_list(t[CONF_TRIGGERS])
flatlist.extend(triggerlist)
else:
flatlist.append(t)
return flatlist
# This is first round of validation, we don't want to process the config here already,
# just ensure basics as platform and ID are there.
def _base_trigger_validator(value: Any) -> Any:
@ -1788,7 +1802,9 @@ def _base_trigger_validator(value: Any) -> Any:
return value
TRIGGER_SCHEMA = vol.All(ensure_list, [_base_trigger_validator])
TRIGGER_SCHEMA = vol.All(
ensure_list, _base_trigger_list_flatten, [_base_trigger_validator]
)
_SCRIPT_DELAY_SCHEMA = vol.Schema(
{

View File

@ -25,6 +25,7 @@ from homeassistant.helpers import (
selector,
template,
)
from homeassistant.helpers.config_validation import TRIGGER_SCHEMA
def test_boolean() -> None:
@ -1817,6 +1818,82 @@ async def test_async_validate(hass: HomeAssistant, tmpdir: py.path.local) -> Non
validator_calls = {}
async def test_nested_trigger_list() -> None:
"""Test triggers within nested lists are flattened."""
trigger_config = [
{
"triggers": {
"platform": "event",
"event_type": "trigger_1",
},
},
{
"platform": "event",
"event_type": "trigger_2",
},
{"triggers": []},
{"triggers": None},
{
"triggers": [
{
"platform": "event",
"event_type": "trigger_3",
},
{
"platform": "event",
"event_type": "trigger_4",
},
],
},
]
validated_triggers = TRIGGER_SCHEMA(trigger_config)
assert validated_triggers == [
{
"platform": "event",
"event_type": "trigger_1",
},
{
"platform": "event",
"event_type": "trigger_2",
},
{
"platform": "event",
"event_type": "trigger_3",
},
{
"platform": "event",
"event_type": "trigger_4",
},
]
async def test_nested_trigger_list_extra() -> None:
"""Test triggers key with extra keys is not modified."""
trigger_config = [
{
"platform": "other",
"triggers": [
{
"platform": "event",
"event_type": "trigger_1",
},
{
"platform": "event",
"event_type": "trigger_2",
},
],
},
]
validated_triggers = TRIGGER_SCHEMA(trigger_config)
assert validated_triggers == trigger_config
async def test_is_entity_service_schema(
hass: HomeAssistant,
) -> None:

View File

@ -159,6 +159,70 @@ async def test_trigger_enabled_templates(
assert len(service_calls) == 2
async def test_nested_trigger_list(
hass: HomeAssistant, service_calls: list[ServiceCall]
) -> None:
"""Test triggers within nested list."""
assert await async_setup_component(
hass,
"automation",
{
"automation": {
"trigger": [
{
"triggers": {
"platform": "event",
"event_type": "trigger_1",
},
},
{
"platform": "event",
"event_type": "trigger_2",
},
{"triggers": []},
{"triggers": None},
{
"triggers": [
{
"platform": "event",
"event_type": "trigger_3",
},
{
"platform": "event",
"event_type": "trigger_4",
},
],
},
],
"action": {
"service": "test.automation",
},
}
},
)
hass.bus.async_fire("trigger_1")
await hass.async_block_till_done()
assert len(service_calls) == 1
hass.bus.async_fire("trigger_2")
await hass.async_block_till_done()
assert len(service_calls) == 2
hass.bus.async_fire("trigger_none")
await hass.async_block_till_done()
assert len(service_calls) == 2
hass.bus.async_fire("trigger_3")
await hass.async_block_till_done()
assert len(service_calls) == 3
hass.bus.async_fire("trigger_4")
await hass.async_block_till_done()
assert len(service_calls) == 4
async def test_trigger_enabled_template_limited(
hass: HomeAssistant,
service_calls: list[ServiceCall],