Fix script wait templates with now/utcnow (#44717)
parent
7415dacec9
commit
2ef25e7414
|
@ -715,9 +715,9 @@ def async_track_template(
|
|||
|
||||
hass.async_run_hass_job(
|
||||
job,
|
||||
event.data.get("entity_id"),
|
||||
event.data.get("old_state"),
|
||||
event.data.get("new_state"),
|
||||
event and event.data.get("entity_id"),
|
||||
event and event.data.get("old_state"),
|
||||
event and event.data.get("new_state"),
|
||||
)
|
||||
|
||||
info = async_track_template_result(
|
||||
|
|
|
@ -62,7 +62,11 @@ from homeassistant.core import (
|
|||
callback,
|
||||
)
|
||||
from homeassistant.helpers import condition, config_validation as cv, service, template
|
||||
from homeassistant.helpers.event import async_call_later, async_track_template
|
||||
from homeassistant.helpers.event import (
|
||||
TrackTemplate,
|
||||
async_call_later,
|
||||
async_track_template_result,
|
||||
)
|
||||
from homeassistant.helpers.script_variables import ScriptVariables
|
||||
from homeassistant.helpers.trigger import (
|
||||
async_initialize_triggers,
|
||||
|
@ -355,7 +359,7 @@ class _ScriptRun:
|
|||
return
|
||||
|
||||
@callback
|
||||
def async_script_wait(entity_id, from_s, to_s):
|
||||
def _async_script_wait(event, updates):
|
||||
"""Handle script after template condition is true."""
|
||||
self._variables["wait"] = {
|
||||
"remaining": to_context.remaining if to_context else delay,
|
||||
|
@ -364,9 +368,12 @@ class _ScriptRun:
|
|||
done.set()
|
||||
|
||||
to_context = None
|
||||
unsub = async_track_template(
|
||||
self._hass, wait_template, async_script_wait, self._variables
|
||||
info = async_track_template_result(
|
||||
self._hass,
|
||||
[TrackTemplate(wait_template, self._variables)],
|
||||
_async_script_wait,
|
||||
)
|
||||
unsub = info.async_remove
|
||||
|
||||
self._changed()
|
||||
done = asyncio.Event()
|
||||
|
|
|
@ -908,6 +908,33 @@ async def test_track_template_error_can_recover(hass, caplog):
|
|||
assert "UndefinedError" not in caplog.text
|
||||
|
||||
|
||||
async def test_track_template_time_change(hass, caplog):
|
||||
"""Test tracking template with time change."""
|
||||
template_error = Template("{{ utcnow().minute % 2 == 0 }}", hass)
|
||||
calls = []
|
||||
|
||||
@ha.callback
|
||||
def error_callback(entity_id, old_state, new_state):
|
||||
calls.append((entity_id, old_state, new_state))
|
||||
|
||||
start_time = dt_util.utcnow() + timedelta(hours=24)
|
||||
time_that_will_not_match_right_away = start_time.replace(minute=1, second=0)
|
||||
with patch(
|
||||
"homeassistant.util.dt.utcnow", return_value=time_that_will_not_match_right_away
|
||||
):
|
||||
async_track_template(hass, template_error, error_callback)
|
||||
await hass.async_block_till_done()
|
||||
assert not calls
|
||||
|
||||
first_time = start_time.replace(minute=2, second=0)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=first_time):
|
||||
async_fire_time_changed(hass, first_time)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(calls) == 1
|
||||
assert calls[0] == (None, None, None)
|
||||
|
||||
|
||||
async def test_track_template_result(hass):
|
||||
"""Test tracking template."""
|
||||
specific_runs = []
|
||||
|
|
|
@ -780,6 +780,32 @@ async def test_wait_template_variables_in(hass):
|
|||
assert not script_obj.is_running
|
||||
|
||||
|
||||
async def test_wait_template_with_utcnow(hass):
|
||||
"""Test the wait template with utcnow."""
|
||||
sequence = cv.SCRIPT_SCHEMA({"wait_template": "{{ utcnow().hours == 12 }}"})
|
||||
script_obj = script.Script(hass, sequence, "Test Name", "test_domain")
|
||||
wait_started_flag = async_watch_for_action(script_obj, "wait")
|
||||
start_time = dt_util.utcnow() + timedelta(hours=24)
|
||||
|
||||
try:
|
||||
hass.async_create_task(script_obj.async_run(context=Context()))
|
||||
async_fire_time_changed(hass, start_time.replace(hour=5))
|
||||
assert not script_obj.is_running
|
||||
async_fire_time_changed(hass, start_time.replace(hour=12))
|
||||
|
||||
await asyncio.wait_for(wait_started_flag.wait(), 1)
|
||||
|
||||
assert script_obj.is_running
|
||||
except (AssertionError, asyncio.TimeoutError):
|
||||
await script_obj.async_stop()
|
||||
raise
|
||||
else:
|
||||
async_fire_time_changed(hass, start_time.replace(hour=3))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not script_obj.is_running
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ["no_timeout", "timeout_finish", "timeout_not_finish"])
|
||||
@pytest.mark.parametrize("action_type", ["template", "trigger"])
|
||||
async def test_wait_variables_out(hass, mode, action_type):
|
||||
|
|
Loading…
Reference in New Issue