diff --git a/homeassistant/components/lock/__init__.py b/homeassistant/components/lock/__init__.py index a9f31a3a41097..ec462c3b993bd 100644 --- a/homeassistant/components/lock/__init__.py +++ b/homeassistant/components/lock/__init__.py @@ -6,7 +6,7 @@ import functools as ft import logging import re -from typing import Any, final +from typing import TYPE_CHECKING, Any, final import voluptuous as vol @@ -39,6 +39,11 @@ from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.typing import ConfigType, StateType +if TYPE_CHECKING: + from functools import cached_property +else: + from homeassistant.backports.functools import cached_property + _LOGGER = logging.getLogger(__name__) ATTR_CHANGED_BY = "changed_by" @@ -113,7 +118,18 @@ class LockEntityDescription(EntityDescription, frozen_or_thawed=True): """A class that describes lock entities.""" -class LockEntity(Entity): +CACHED_PROPERTIES_WITH_ATTR_ = { + "changed_by", + "code_format", + "is_locked", + "is_locking", + "is_unlocking", + "is_jammed", + "supported_features", +} + + +class LockEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_): """Base class for lock entities.""" entity_description: LockEntityDescription @@ -143,12 +159,12 @@ def add_default_code(self, data: dict[Any, Any]) -> dict[Any, Any]: data[ATTR_CODE] = code return data - @property + @cached_property def changed_by(self) -> str | None: """Last change triggered by.""" return self._attr_changed_by - @property + @cached_property def code_format(self) -> str | None: """Regex for code format or None if no code is required.""" return self._attr_code_format @@ -167,22 +183,22 @@ def code_format_cmp(self) -> re.Pattern[str] | None: self.__code_format_cmp = re.compile(self.code_format) return self.__code_format_cmp - @property + @cached_property def is_locked(self) -> bool | None: """Return true if the lock is locked.""" return self._attr_is_locked - @property + @cached_property def is_locking(self) -> bool | None: """Return true if the lock is locking.""" return self._attr_is_locking - @property + @cached_property def is_unlocking(self) -> bool | None: """Return true if the lock is unlocking.""" return self._attr_is_unlocking - @property + @cached_property def is_jammed(self) -> bool | None: """Return true if the lock is jammed (incomplete locking).""" return self._attr_is_jammed @@ -250,7 +266,7 @@ def state(self) -> str | None: return None return STATE_LOCKED if locked else STATE_UNLOCKED - @property + @cached_property def supported_features(self) -> LockEntityFeature: """Return the list of supported features.""" return self._attr_supported_features