Correct trace of condition actions (#50800)

This commit is contained in:
Erik Montnemery 2021-05-18 01:54:17 +02:00 committed by GitHub
parent 781524ee36
commit 1ea0d8ae02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 12 deletions

View File

@ -112,15 +112,22 @@ def condition_trace_update_result(**kwargs: Any) -> None:
@contextmanager
def trace_condition(variables: TemplateVarsType) -> Generator:
"""Trace condition evaluation."""
trace_element = condition_trace_append(variables, trace_path_get())
trace_stack_push(trace_stack_cv, trace_element)
should_pop = True
trace_element = trace_stack_top(trace_stack_cv)
if trace_element and trace_element.reuse_by_child:
should_pop = False
trace_element.reuse_by_child = False
else:
trace_element = condition_trace_append(variables, trace_path_get())
trace_stack_push(trace_stack_cv, trace_element)
try:
yield trace_element
except Exception as ex:
trace_element.set_error(ex)
raise ex
finally:
trace_stack_pop(trace_stack_cv)
if should_pop:
trace_stack_pop(trace_stack_cv)
def trace_condition_function(condition: ConditionCheckerType) -> ConditionCheckerType:

View File

@ -87,6 +87,8 @@ from .trace import (
trace_stack_cv,
trace_stack_pop,
trace_stack_push,
trace_stack_top,
trace_update_result,
)
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
@ -619,14 +621,16 @@ class _ScriptRun:
)
cond = await self._async_get_condition(self._action)
try:
with trace_path("condition"):
check = cond(self._hass, self._variables)
trace_element = trace_stack_top(trace_stack_cv)
if trace_element:
trace_element.reuse_by_child = True
check = cond(self._hass, self._variables)
except exceptions.ConditionError as ex:
_LOGGER.warning("Error in 'condition' evaluation:\n%s", ex)
check = False
self._log("Test condition %s: %s", self._script.last_action, check)
trace_set_result(result=check)
trace_update_result(result=check)
if not check:
raise _StopScript

View File

@ -22,6 +22,7 @@ class TraceElement:
self._error: Exception | None = None
self.path: str = path
self._result: dict | None = None
self.reuse_by_child = False
self._timestamp = dt_util.utcnow()
if variables is None:
@ -198,6 +199,12 @@ def trace_set_result(**kwargs: Any) -> None:
node.set_result(**kwargs)
def trace_update_result(**kwargs: Any) -> None:
"""Update the result of TraceElement at the top of the stack."""
node = cast(TraceElement, trace_stack_top(trace_stack_cv))
node.update_result(**kwargs)
class StopReason:
"""Mutable container class for script_execution."""

View File

@ -1412,8 +1412,7 @@ async def test_condition_warning(hass, caplog):
{
"0": [{"result": {"event": "test_event", "event_data": {}}}],
"1": [{"error_type": script._StopScript, "result": {"result": False}}],
"1/condition": [{"error_type": ConditionError}],
"1/condition/entity_id/0": [{"error_type": ConditionError}],
"1/entity_id/0": [{"error_type": ConditionError}],
},
expected_script_execution="aborted",
)
@ -1448,8 +1447,7 @@ async def test_condition_basic(hass, caplog):
assert_action_trace(
{
"0": [{"result": {"event": "test_event", "event_data": {}}}],
"1": [{"result": {"result": True}}],
"1/condition": [{"result": {"entities": ["test.entity"], "result": True}}],
"1": [{"result": {"entities": ["test.entity"], "result": True}}],
"2": [{"result": {"event": "test_event", "event_data": {}}}],
}
)
@ -1465,8 +1463,12 @@ async def test_condition_basic(hass, caplog):
assert_action_trace(
{
"0": [{"result": {"event": "test_event", "event_data": {}}}],
"1": [{"error_type": script._StopScript, "result": {"result": False}}],
"1/condition": [{"result": {"entities": ["test.entity"], "result": False}}],
"1": [
{
"error_type": script._StopScript,
"result": {"entities": ["test.entity"], "result": False},
}
],
},
expected_script_execution="aborted",
)