diff --git a/homeassistant/core.py b/homeassistant/core.py index 78ca41682e7..f22e95c2ecc 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1065,6 +1065,7 @@ class State: """ __slots__ = [ + "__weakref__", "entity_id", "state", "attributes", diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 7258bdb830d..b0f51fe08cc 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -21,7 +21,7 @@ from struct import error as StructError, pack, unpack_from import sys from typing import Any, cast from urllib.parse import urlencode as urllib_urlencode -import weakref +from weakref import WeakKeyDictionary, WeakValueDictionary import jinja2 from jinja2 import pass_context, pass_environment @@ -93,6 +93,11 @@ _COLLECTABLE_STATE_ATTRIBUTES = { ALL_STATES_RATE_LIMIT = timedelta(minutes=1) DOMAIN_STATES_RATE_LIMIT = timedelta(seconds=1) +TEMPLATE_STATES_COLLECT: WeakKeyDictionary[State, TemplateState] = WeakKeyDictionary({}) +TEMPLATE_STATES_NO_COLLECT: WeakKeyDictionary[State, TemplateState] = WeakKeyDictionary( + {} +) + template_cv: ContextVar[tuple[str, str] | None] = ContextVar( "template_cv", default=None ) @@ -893,9 +898,13 @@ def _collect_state(hass: HomeAssistant, entity_id: str) -> None: entity_collect.entities.add(entity_id) -@lru_cache(maxsize=4096) def _template_state_no_collect(hass: HomeAssistant, state: State) -> TemplateState: - return TemplateState(hass, state, collect=False) + if temlate_state := TEMPLATE_STATES_NO_COLLECT.get(state): + return temlate_state + template_state = TEMPLATE_STATES_NO_COLLECT[state] = TemplateState( + hass, state, collect=False + ) + return template_state def _state_generator(hass: HomeAssistant, domain: str | None) -> Generator: @@ -915,9 +924,11 @@ def _get_state(hass: HomeAssistant, entity_id: str) -> TemplateState | None: return _get_template_state_from_state(hass, entity_id, hass.states.get(entity_id)) -@lru_cache(maxsize=4096) def _template_state(hass: HomeAssistant, state: State) -> TemplateState: - return TemplateState(hass, state) + if temlate_state := TEMPLATE_STATES_COLLECT.get(state): + return temlate_state + template_state = TEMPLATE_STATES_COLLECT[state] = TemplateState(hass, state) + return template_state def _get_template_state_from_state( @@ -1933,7 +1944,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): undefined = jinja2.StrictUndefined super().__init__(undefined=undefined) self.hass = hass - self.template_cache = weakref.WeakValueDictionary() + self.template_cache = WeakValueDictionary() self.filters["round"] = forgiving_round self.filters["multiply"] = multiply self.filters["log"] = logarithm