From 9051750add568fcad24721180f108e261c2b2f9c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 25 Jun 2023 08:50:48 -0500 Subject: [PATCH] Cache entity translation lookups and keys (#95180) --- homeassistant/helpers/entity.py | 35 +++++++++++++++++++++++---------- tests/helpers/test_entity.py | 4 ++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 33899b76c87..dbf9fe2f2f0 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -312,6 +312,10 @@ class Entity(ABC): _attr_unique_id: str | None = None _attr_unit_of_measurement: str | None + # Translation cache + _cached_name_translation_key: str | None = None + _cached_device_class_name: str | None = None + @property def should_poll(self) -> bool: """Return True if entity has to be polled for state. @@ -382,14 +386,19 @@ class Entity(ABC): def _device_class_name(self) -> str | None: """Return a translated name of the entity based on its device class.""" + if self._cached_device_class_name is not None: + return self._cached_device_class_name if not self.has_entity_name: return None device_class_key = self.device_class or "_" + platform = self.platform name_translation_key = ( - f"component.{self.platform.domain}.entity_component." - f"{device_class_key}.name" + f"component.{platform.domain}.entity_component." f"{device_class_key}.name" ) - return self.platform.component_translations.get(name_translation_key) + self._cached_device_class_name = platform.component_translations.get( + name_translation_key + ) + return self._cached_device_class_name def _default_to_device_class_name(self) -> bool: """Return True if an unnamed entity should be named by its device class.""" @@ -397,24 +406,30 @@ class Entity(ABC): def _name_translation_key(self) -> str | None: """Return translation key for entity name.""" + if self._cached_name_translation_key is not None: + return self._cached_name_translation_key if self.translation_key is None: return None - return ( - f"component.{self.platform.platform_name}.entity.{self.platform.domain}" + platform = self.platform + self._cached_name_translation_key = ( + f"component.{platform.platform_name}.entity.{platform.domain}" f".{self.translation_key}.name" ) + return self._cached_name_translation_key @property def name(self) -> str | UndefinedType | None: """Return the name of the entity.""" if hasattr(self, "_attr_name"): return self._attr_name - if self.has_entity_name and ( - name_translation_key := self._name_translation_key() + if ( + self.has_entity_name + and (name_translation_key := self._name_translation_key()) + and (name := self.platform.platform_translations.get(name_translation_key)) ): - if name_translation_key in self.platform.platform_translations: - name: str = self.platform.platform_translations[name_translation_key] - return name + if TYPE_CHECKING: + assert isinstance(name, str) + return name if hasattr(self, "entity_description"): description_name = self.entity_description.name if description_name is UNDEFINED and self._default_to_device_class_name(): diff --git a/tests/helpers/test_entity.py b/tests/helpers/test_entity.py index 1861dc54844..85a7932aef8 100644 --- a/tests/helpers/test_entity.py +++ b/tests/helpers/test_entity.py @@ -19,6 +19,7 @@ from homeassistant.const import ( ) from homeassistant.core import Context, HomeAssistant, HomeAssistantError from homeassistant.helpers import device_registry as dr, entity, entity_registry as er +from homeassistant.helpers.entity_component import async_update_entity from homeassistant.helpers.typing import UNDEFINED from tests.common import ( @@ -983,6 +984,9 @@ async def _test_friendly_name( assert state.attributes.get(ATTR_FRIENDLY_NAME) == expected_friendly_name assert (expected_warning in caplog.text) is warn_implicit_name + await async_update_entity(hass, ent.entity_id) + assert state.attributes.get(ATTR_FRIENDLY_NAME) == expected_friendly_name + @pytest.mark.parametrize( ("has_entity_name", "entity_name", "expected_friendly_name", "warn_implicit_name"),