mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 17:49:37 +01:00
Unload scripts and conditions created by template entities (#169366)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"""Data update coordinator for trigger based template entities."""
|
||||
|
||||
from collections.abc import Callable, Mapping
|
||||
from collections.abc import Callable
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
from homeassistant.components.blueprint import CONF_USE_BLUEPRINT
|
||||
from homeassistant.const import (
|
||||
@@ -37,7 +37,7 @@ class TriggerUpdateCoordinator(DataUpdateCoordinator):
|
||||
hass, _LOGGER, config_entry=None, name="Trigger Update Coordinator"
|
||||
)
|
||||
self.config = config
|
||||
self._cond_func: Callable[[Mapping[str, Any] | None], bool] | None = None
|
||||
self._cond_func: condition.ConditionsChecker | None = None
|
||||
self._unsub_start: Callable[[], None] | None = None
|
||||
self._unsub_trigger: Callable[[], None] | None = None
|
||||
self._script: Script | None = None
|
||||
@@ -69,7 +69,9 @@ class TriggerUpdateCoordinator(DataUpdateCoordinator):
|
||||
self._unsub_trigger()
|
||||
self._unsub_trigger = None
|
||||
if self._script is not None:
|
||||
await self._script.async_stop()
|
||||
await self._script.async_unload()
|
||||
if self._cond_func is not None:
|
||||
self._cond_func.async_unload()
|
||||
|
||||
async def async_setup(self, hass_config: ConfigType) -> None:
|
||||
"""Set up the trigger and create entities."""
|
||||
@@ -158,7 +160,7 @@ class TriggerUpdateCoordinator(DataUpdateCoordinator):
|
||||
def _check_condition(self, run_variables: TemplateVarsType) -> bool:
|
||||
if not self._cond_func:
|
||||
return True
|
||||
condition_result = self._cond_func(run_variables)
|
||||
condition_result = self._cond_func.async_check(variables=run_variables)
|
||||
if condition_result is False:
|
||||
_LOGGER.debug(
|
||||
"Conditions not met, aborting template trigger update. Condition summary: %s",
|
||||
|
||||
@@ -169,9 +169,15 @@ class AbstractTemplateEntity(Entity):
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Stop scripts when removing from Home Assistant."""
|
||||
for action_script in self._action_scripts.values():
|
||||
await action_script.async_stop()
|
||||
"""Clean up scripts when removing from Home Assistant."""
|
||||
if not self.registry_entry or self.registry_entry.entity_id == self.entity_id:
|
||||
# Entity ID not changed, unload scripts as they will not be reused.
|
||||
for action_script in self._action_scripts.values():
|
||||
await action_script.async_unload()
|
||||
else:
|
||||
# Entity ID changed, just stop scripts
|
||||
for action_script in self._action_scripts.values():
|
||||
await action_script.async_stop()
|
||||
|
||||
async def async_run_script(
|
||||
self,
|
||||
|
||||
@@ -82,4 +82,5 @@ async def test_reload_stops_entity_action_scripts(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not turn_on_script.is_running
|
||||
assert turn_on_script._unloaded
|
||||
assert hass.data["light"].get_entity("light.test_light") is None
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Test trigger template entity."""
|
||||
|
||||
import asyncio
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -17,7 +17,8 @@ from homeassistant.const import (
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import template
|
||||
from homeassistant.helpers import condition, template
|
||||
from homeassistant.helpers.script import Script
|
||||
from homeassistant.helpers.trigger_template_entity import CONF_PICTURE
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
@@ -243,6 +244,23 @@ async def test_multiple_template_validators(hass: HomeAssistant) -> None:
|
||||
assert state.attributes["current_tilt_position"] == 49
|
||||
|
||||
|
||||
async def test_coordinator_shutdown_unloads_script_and_condition(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test that coordinator shutdown stops and unloads script and condition."""
|
||||
coordinator = TriggerUpdateCoordinator(hass, {})
|
||||
|
||||
mock_script = Mock(spec=Script)
|
||||
mock_cond = Mock(spec=condition.ConditionsChecker)
|
||||
coordinator._script = mock_script
|
||||
coordinator._cond_func = mock_cond
|
||||
|
||||
await coordinator.async_shutdown()
|
||||
|
||||
mock_script.async_unload.assert_called_once()
|
||||
mock_cond.async_unload.assert_called_once()
|
||||
|
||||
|
||||
async def test_shutdown_stops_script_and_keeps_triggers_subscribed(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
@@ -281,13 +299,15 @@ async def test_shutdown_stops_script_and_keeps_triggers_subscribed(
|
||||
coordinators = hass.data[DATA_COORDINATORS]
|
||||
assert len(coordinators) == 1
|
||||
assert coordinators[0]._script.is_running
|
||||
assert not coordinators[0]._script._unloaded
|
||||
|
||||
# Fire shutdown
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Script should be stopped - this is handled by the script helper
|
||||
# Script should be stopped but not unloaded - this is handled by the script helper
|
||||
assert not coordinators[0]._script.is_running
|
||||
assert not coordinators[0]._script._unloaded
|
||||
|
||||
# Triggers are not unsubscribed on shutdown
|
||||
listeners = hass.bus.async_listeners()
|
||||
@@ -332,6 +352,7 @@ async def test_reload_stops_script_and_unsubscribes_triggers(
|
||||
assert len(coordinators) == 1
|
||||
coordinator = coordinators[0]
|
||||
assert coordinator._script.is_running
|
||||
assert not coordinator._script._unloaded
|
||||
|
||||
# Reload with empty config
|
||||
with patch(
|
||||
@@ -342,8 +363,9 @@ async def test_reload_stops_script_and_unsubscribes_triggers(
|
||||
await hass.services.async_call("template", SERVICE_RELOAD, blocking=True)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Script should be stopped
|
||||
# Script should be stopped and unloaded
|
||||
assert not coordinator._script.is_running
|
||||
assert coordinator._script._unloaded
|
||||
|
||||
# Old trigger should be unsubscribed
|
||||
listeners = hass.bus.async_listeners()
|
||||
|
||||
Reference in New Issue
Block a user