mirror of
https://github.com/home-assistant/core.git
synced 2025-11-08 18:39:30 +00:00
Add stop/error script/automation action (#67340)
This commit is contained in:
@@ -33,6 +33,7 @@ from homeassistant.const import (
|
||||
CONF_DELAY,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
CONF_ERROR,
|
||||
CONF_EVENT,
|
||||
CONF_EVENT_DATA,
|
||||
CONF_EVENT_DATA_TEMPLATE,
|
||||
@@ -41,6 +42,7 @@ from homeassistant.const import (
|
||||
CONF_SCENE,
|
||||
CONF_SEQUENCE,
|
||||
CONF_SERVICE,
|
||||
CONF_STOP,
|
||||
CONF_TARGET,
|
||||
CONF_TIMEOUT,
|
||||
CONF_UNTIL,
|
||||
@@ -191,9 +193,11 @@ async def trace_action(hass, script_run, stop, variables):
|
||||
|
||||
try:
|
||||
yield trace_element
|
||||
except _StopScript as ex:
|
||||
except _AbortScript as ex:
|
||||
trace_element.set_error(ex.__cause__ or ex)
|
||||
raise ex
|
||||
except _StopScript as ex:
|
||||
raise ex
|
||||
except Exception as ex:
|
||||
trace_element.set_error(ex)
|
||||
raise ex
|
||||
@@ -227,6 +231,8 @@ STATIC_VALIDATION_ACTION_TYPES = (
|
||||
cv.SCRIPT_ACTION_FIRE_EVENT,
|
||||
cv.SCRIPT_ACTION_ACTIVATE_SCENE,
|
||||
cv.SCRIPT_ACTION_VARIABLES,
|
||||
cv.SCRIPT_ACTION_ERROR,
|
||||
cv.SCRIPT_ACTION_STOP,
|
||||
)
|
||||
|
||||
|
||||
@@ -295,6 +301,10 @@ async def async_validate_action_config(
|
||||
return config
|
||||
|
||||
|
||||
class _AbortScript(Exception):
|
||||
"""Throw if script needs to abort because of an unexpected error."""
|
||||
|
||||
|
||||
class _StopScript(Exception):
|
||||
"""Throw if script needs to stop."""
|
||||
|
||||
@@ -360,6 +370,8 @@ class _ScriptRun:
|
||||
else:
|
||||
script_execution_set("finished")
|
||||
except _StopScript:
|
||||
script_execution_set("finished")
|
||||
except _AbortScript:
|
||||
script_execution_set("aborted")
|
||||
except Exception:
|
||||
script_execution_set("error")
|
||||
@@ -378,7 +390,7 @@ class _ScriptRun:
|
||||
handler = f"_async_{cv.determine_script_action(self._action)}_step"
|
||||
await getattr(self, handler)()
|
||||
except Exception as ex:
|
||||
if not isinstance(ex, _StopScript) and (
|
||||
if not isinstance(ex, (_AbortScript, _StopScript)) and (
|
||||
self._log_exceptions or log_exceptions
|
||||
):
|
||||
self._log_exception(ex)
|
||||
@@ -443,7 +455,7 @@ class _ScriptRun:
|
||||
ex,
|
||||
level=logging.ERROR,
|
||||
)
|
||||
raise _StopScript from ex
|
||||
raise _AbortScript from ex
|
||||
|
||||
async def _async_delay_step(self):
|
||||
"""Handle delay."""
|
||||
@@ -509,7 +521,7 @@ class _ScriptRun:
|
||||
if not self._action.get(CONF_CONTINUE_ON_TIMEOUT, True):
|
||||
self._log(_TIMEOUT_MSG)
|
||||
trace_set_result(wait=self._variables["wait"], timeout=True)
|
||||
raise _StopScript from ex
|
||||
raise _AbortScript from ex
|
||||
finally:
|
||||
for task in tasks:
|
||||
task.cancel()
|
||||
@@ -643,7 +655,7 @@ class _ScriptRun:
|
||||
self._log("Test condition %s: %s", self._script.last_action, check)
|
||||
trace_update_result(result=check)
|
||||
if not check:
|
||||
raise _StopScript
|
||||
raise _AbortScript
|
||||
|
||||
def _test_conditions(self, conditions, name, condition_path=None):
|
||||
if condition_path is None:
|
||||
@@ -700,7 +712,7 @@ class _ScriptRun:
|
||||
ex,
|
||||
level=logging.ERROR,
|
||||
)
|
||||
raise _StopScript from ex
|
||||
raise _AbortScript from ex
|
||||
extra_msg = f" of {count}"
|
||||
for iteration in range(1, count + 1):
|
||||
set_repeat_var(iteration, count)
|
||||
@@ -820,7 +832,7 @@ class _ScriptRun:
|
||||
if not self._action.get(CONF_CONTINUE_ON_TIMEOUT, True):
|
||||
self._log(_TIMEOUT_MSG)
|
||||
trace_set_result(wait=self._variables["wait"], timeout=True)
|
||||
raise _StopScript from ex
|
||||
raise _AbortScript from ex
|
||||
finally:
|
||||
for task in tasks:
|
||||
task.cancel()
|
||||
@@ -833,6 +845,20 @@ class _ScriptRun:
|
||||
self._hass, self._variables, render_as_defaults=False
|
||||
)
|
||||
|
||||
async def _async_stop_step(self):
|
||||
"""Stop script execution."""
|
||||
stop = self._action[CONF_STOP]
|
||||
self._log("Stop script sequence: %s", stop)
|
||||
trace_set_result(stop=stop)
|
||||
raise _StopScript(stop)
|
||||
|
||||
async def _async_error_step(self):
|
||||
"""Abort and error script execution."""
|
||||
error = self._action[CONF_ERROR]
|
||||
self._log("Error script sequence: %s", error)
|
||||
trace_set_result(error=error)
|
||||
raise _AbortScript(error)
|
||||
|
||||
async def _async_run_script(self, script: Script) -> None:
|
||||
"""Execute a script."""
|
||||
await self._async_run_long_action(
|
||||
|
||||
Reference in New Issue
Block a user