Handle ConditionError with multiple entity_id for state/numeric_state (#46855)
This commit is contained in:
parent
75b37b4c2a
commit
d61d39de08
3 changed files with 61 additions and 33 deletions
|
@ -85,7 +85,7 @@ class ConditionErrorIndex(ConditionError):
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class ConditionErrorContainer(ConditionError):
|
class ConditionErrorContainer(ConditionError):
|
||||||
"""Condition error with index."""
|
"""Condition error with subconditions."""
|
||||||
|
|
||||||
# List of ConditionErrors that this error wraps
|
# List of ConditionErrors that this error wraps
|
||||||
errors: Sequence[ConditionError] = attr.ib()
|
errors: Sequence[ConditionError] = attr.ib()
|
||||||
|
|
|
@ -342,12 +342,25 @@ def async_numeric_state_from_config(
|
||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
return all(
|
errors = []
|
||||||
async_numeric_state(
|
for index, entity_id in enumerate(entity_ids):
|
||||||
hass, entity_id, below, above, value_template, variables, attribute
|
try:
|
||||||
)
|
if not async_numeric_state(
|
||||||
for entity_id in entity_ids
|
hass, entity_id, below, above, value_template, variables, attribute
|
||||||
)
|
):
|
||||||
|
return False
|
||||||
|
except ConditionError as ex:
|
||||||
|
errors.append(
|
||||||
|
ConditionErrorIndex(
|
||||||
|
"numeric_state", index=index, total=len(entity_ids), error=ex
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Raise the errors if no check was false
|
||||||
|
if errors:
|
||||||
|
raise ConditionErrorContainer("numeric_state", errors=errors)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
return if_numeric_state
|
return if_numeric_state
|
||||||
|
|
||||||
|
@ -429,10 +442,23 @@ def state_from_config(
|
||||||
|
|
||||||
def if_state(hass: HomeAssistant, variables: TemplateVarsType = None) -> bool:
|
def if_state(hass: HomeAssistant, variables: TemplateVarsType = None) -> bool:
|
||||||
"""Test if condition."""
|
"""Test if condition."""
|
||||||
return all(
|
errors = []
|
||||||
state(hass, entity_id, req_states, for_period, attribute)
|
for index, entity_id in enumerate(entity_ids):
|
||||||
for entity_id in entity_ids
|
try:
|
||||||
)
|
if not state(hass, entity_id, req_states, for_period, attribute):
|
||||||
|
return False
|
||||||
|
except ConditionError as ex:
|
||||||
|
errors.append(
|
||||||
|
ConditionErrorIndex(
|
||||||
|
"state", index=index, total=len(entity_ids), error=ex
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Raise the errors if no check was false
|
||||||
|
if errors:
|
||||||
|
raise ConditionErrorContainer("state", errors=errors)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
return if_state
|
return if_state
|
||||||
|
|
||||||
|
|
|
@ -390,17 +390,18 @@ async def test_state_raises(hass):
|
||||||
with pytest.raises(ConditionError, match="no entity"):
|
with pytest.raises(ConditionError, match="no entity"):
|
||||||
condition.state(hass, entity=None, req_state="missing")
|
condition.state(hass, entity=None, req_state="missing")
|
||||||
|
|
||||||
# Unknown entity_id
|
# Unknown entities
|
||||||
with pytest.raises(ConditionError, match="unknown entity"):
|
test = await condition.async_from_config(
|
||||||
test = await condition.async_from_config(
|
hass,
|
||||||
hass,
|
{
|
||||||
{
|
"condition": "state",
|
||||||
"condition": "state",
|
"entity_id": ["sensor.door_unknown", "sensor.window_unknown"],
|
||||||
"entity_id": "sensor.door_unknown",
|
"state": "open",
|
||||||
"state": "open",
|
},
|
||||||
},
|
)
|
||||||
)
|
with pytest.raises(ConditionError, match="unknown entity.*door"):
|
||||||
|
test(hass)
|
||||||
|
with pytest.raises(ConditionError, match="unknown entity.*window"):
|
||||||
test(hass)
|
test(hass)
|
||||||
|
|
||||||
# Unknown attribute
|
# Unknown attribute
|
||||||
|
@ -632,17 +633,18 @@ async def test_state_using_input_entities(hass):
|
||||||
|
|
||||||
async def test_numeric_state_raises(hass):
|
async def test_numeric_state_raises(hass):
|
||||||
"""Test that numeric_state raises ConditionError on errors."""
|
"""Test that numeric_state raises ConditionError on errors."""
|
||||||
# Unknown entity_id
|
# Unknown entities
|
||||||
with pytest.raises(ConditionError, match="unknown entity"):
|
test = await condition.async_from_config(
|
||||||
test = await condition.async_from_config(
|
hass,
|
||||||
hass,
|
{
|
||||||
{
|
"condition": "numeric_state",
|
||||||
"condition": "numeric_state",
|
"entity_id": ["sensor.temperature_unknown", "sensor.humidity_unknown"],
|
||||||
"entity_id": "sensor.temperature_unknown",
|
"above": 0,
|
||||||
"above": 0,
|
},
|
||||||
},
|
)
|
||||||
)
|
with pytest.raises(ConditionError, match="unknown entity.*temperature"):
|
||||||
|
test(hass)
|
||||||
|
with pytest.raises(ConditionError, match="unknown entity.*humidity"):
|
||||||
test(hass)
|
test(hass)
|
||||||
|
|
||||||
# Unknown attribute
|
# Unknown attribute
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue