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,6 +112,12 @@ def condition_trace_update_result(**kwargs: Any) -> None:
@contextmanager @contextmanager
def trace_condition(variables: TemplateVarsType) -> Generator: def trace_condition(variables: TemplateVarsType) -> Generator:
"""Trace condition evaluation.""" """Trace condition evaluation."""
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_element = condition_trace_append(variables, trace_path_get())
trace_stack_push(trace_stack_cv, trace_element) trace_stack_push(trace_stack_cv, trace_element)
try: try:
@ -120,6 +126,7 @@ def trace_condition(variables: TemplateVarsType) -> Generator:
trace_element.set_error(ex) trace_element.set_error(ex)
raise ex raise ex
finally: finally:
if should_pop:
trace_stack_pop(trace_stack_cv) trace_stack_pop(trace_stack_cv)

View file

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

View file

@ -22,6 +22,7 @@ class TraceElement:
self._error: Exception | None = None self._error: Exception | None = None
self.path: str = path self.path: str = path
self._result: dict | None = None self._result: dict | None = None
self.reuse_by_child = False
self._timestamp = dt_util.utcnow() self._timestamp = dt_util.utcnow()
if variables is None: if variables is None:
@ -198,6 +199,12 @@ def trace_set_result(**kwargs: Any) -> None:
node.set_result(**kwargs) 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: class StopReason:
"""Mutable container class for script_execution.""" """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": {}}}], "0": [{"result": {"event": "test_event", "event_data": {}}}],
"1": [{"error_type": script._StopScript, "result": {"result": False}}], "1": [{"error_type": script._StopScript, "result": {"result": False}}],
"1/condition": [{"error_type": ConditionError}], "1/entity_id/0": [{"error_type": ConditionError}],
"1/condition/entity_id/0": [{"error_type": ConditionError}],
}, },
expected_script_execution="aborted", expected_script_execution="aborted",
) )
@ -1448,8 +1447,7 @@ async def test_condition_basic(hass, caplog):
assert_action_trace( assert_action_trace(
{ {
"0": [{"result": {"event": "test_event", "event_data": {}}}], "0": [{"result": {"event": "test_event", "event_data": {}}}],
"1": [{"result": {"result": True}}], "1": [{"result": {"entities": ["test.entity"], "result": True}}],
"1/condition": [{"result": {"entities": ["test.entity"], "result": True}}],
"2": [{"result": {"event": "test_event", "event_data": {}}}], "2": [{"result": {"event": "test_event", "event_data": {}}}],
} }
) )
@ -1465,8 +1463,12 @@ async def test_condition_basic(hass, caplog):
assert_action_trace( assert_action_trace(
{ {
"0": [{"result": {"event": "test_event", "event_data": {}}}], "0": [{"result": {"event": "test_event", "event_data": {}}}],
"1": [{"error_type": script._StopScript, "result": {"result": False}}], "1": [
"1/condition": [{"result": {"entities": ["test.entity"], "result": False}}], {
"error_type": script._StopScript,
"result": {"entities": ["test.entity"], "result": False},
}
],
}, },
expected_script_execution="aborted", expected_script_execution="aborted",
) )