From 5f14cdf69ddc5e2bc78013372eac53b74063ef40 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 27 Jun 2023 02:24:22 -0400 Subject: [PATCH] Allow stopping a script with a response value (#95284) --- homeassistant/components/script/__init__.py | 34 +++++++++++--- .../components/websocket_api/commands.py | 10 ++++- homeassistant/const.py | 3 +- homeassistant/helpers/config_validation.py | 7 ++- homeassistant/helpers/script.py | 45 ++++++++++++++----- homeassistant/helpers/template_entity.py | 2 +- homeassistant/helpers/trace.py | 5 ++- tests/common.py | 21 ++++++++- tests/components/script/test_init.py | 32 +++++++++++++ .../components/websocket_api/test_commands.py | 9 +++- 10 files changed, 140 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/script/__init__.py b/homeassistant/components/script/__init__.py index 659131e902b..1a60c7131c7 100644 --- a/homeassistant/components/script/__init__.py +++ b/homeassistant/components/script/__init__.py @@ -28,7 +28,14 @@ from homeassistant.const import ( SERVICE_TURN_ON, STATE_ON, ) -from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.core import ( + Context, + HomeAssistant, + ServiceCall, + ServiceResponse, + SupportsResponse, + callback, +) from homeassistant.helpers import entity_registry as er import homeassistant.helpers.config_validation as cv from homeassistant.helpers.config_validation import make_entity_service_schema @@ -436,6 +443,12 @@ class ScriptEntity(ToggleEntity, RestoreEntity): variables = kwargs.get("variables") context = kwargs.get("context") wait = kwargs.get("wait", True) + await self._async_start_run(variables, context, wait) + + async def _async_start_run( + self, variables: dict, context: Context, wait: bool + ) -> ServiceResponse: + """Start the run of a script.""" self.async_set_context(context) self.hass.bus.async_fire( EVENT_SCRIPT_STARTED, @@ -444,8 +457,7 @@ class ScriptEntity(ToggleEntity, RestoreEntity): ) coro = self._async_run(variables, context) if wait: - await coro - return + return await coro # Caller does not want to wait for called script to finish so let script run in # separate Task. Make a new empty script stack; scripts are allowed to @@ -457,6 +469,7 @@ class ScriptEntity(ToggleEntity, RestoreEntity): # Wait for first state change so we can guarantee that # it is written to the State Machine before we return. await self._changed.wait() + return None async def _async_run(self, variables, context): with trace_script( @@ -483,16 +496,25 @@ class ScriptEntity(ToggleEntity, RestoreEntity): """ await self.script.async_stop() - async def _service_handler(self, service: ServiceCall) -> None: + async def _service_handler(self, service: ServiceCall) -> ServiceResponse: """Execute a service call to script.