From f4922edb4b8a9935e15bda87a8155b6164381ee0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 27 Mar 2024 18:29:43 -1000 Subject: [PATCH] Fix empty delays in script helper (#114346) fixes ``` Logger: homeassistant.components.automation.kamermaster_knop_4_acties_licht Bron: components/automation/__init__.py:726 integratie: Automatisering (documentatie, problemen) Eerst voorgekomen: 22:17:29 (5 gebeurtenissen) Laatst gelogd: 22:59:24 While executing automation automation.kamermaster_knop_4_acties_licht Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/components/automation/__init__.py", line 726, in async_trigger return await self.action_script.async_run( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1645, in async_run return await asyncio.shield(create_eager_task(run.async_run())) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 454, in async_run await self._async_step(log_exceptions=False) File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 506, in _async_step self._handle_exception( File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 536, in _handle_exception raise exception File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 504, in _async_step await getattr(self, handler)() File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 626, in _async_delay_step if timeout_future.done(): ^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'done' ``` --- homeassistant/helpers/script.py | 5 +++++ tests/helpers/test_script.py | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index 560f3227c4f..a86df259f11 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -615,6 +615,11 @@ class _ScriptRun: delay = delay_delta.total_seconds() self._changed() + if not delay: + # Handle an empty delay + trace_set_result(delay=delay, done=True) + return + trace_set_result(delay=delay, done=False) futures, timeout_handle, timeout_future = self._async_futures_with_timeout( delay diff --git a/tests/helpers/test_script.py b/tests/helpers/test_script.py index c1462ccfc2f..86fb84eb582 100644 --- a/tests/helpers/test_script.py +++ b/tests/helpers/test_script.py @@ -672,6 +672,31 @@ async def test_delay_basic(hass: HomeAssistant) -> None: ) +async def test_empty_delay(hass: HomeAssistant) -> None: + """Test an empty delay.""" + delay_alias = "delay step" + sequence = cv.SCRIPT_SCHEMA({"delay": {"seconds": 0}, "alias": delay_alias}) + script_obj = script.Script(hass, sequence, "Test Name", "test_domain") + delay_started_flag = async_watch_for_action(script_obj, delay_alias) + + try: + await script_obj.async_run(context=Context()) + await asyncio.wait_for(delay_started_flag.wait(), 1) + except (AssertionError, TimeoutError): + await script_obj.async_stop() + raise + else: + await hass.async_block_till_done() + assert not script_obj.is_running + assert script_obj.last_action is None + + assert_action_trace( + { + "0": [{"result": {"delay": 0.0, "done": True}}], + } + ) + + async def test_multiple_runs_delay(hass: HomeAssistant) -> None: """Test multiple runs with delay in script.""" event = "test_event"