Change Entity.name default to UNDEFINED (#94574)

* Change Entity.name default to UNDEFINED

* Update typing

* Update Pylint plugin

* Update TTS test
This commit is contained in:
Erik Montnemery 2023-06-15 11:09:53 +02:00 committed by GitHub
parent d369d679c7
commit 334dacc322
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 277 additions and 67 deletions

View file

@ -258,6 +258,9 @@ class Entity(ABC):
# it should be using async_write_ha_state.
_async_update_ha_state_reported = False
# If we reported this entity is implicitly using device name
_implicit_device_name_reported = False
# If we reported this entity was added without its platform set
_no_platform_reported = False
@ -319,6 +322,53 @@ class Entity(ABC):
"""Return a unique ID."""
return self._attr_unique_id
@property
def use_device_name(self) -> bool:
"""Return if this entity does not have its own name.
Should be True if the entity represents the single main feature of a device.
"""
def report_implicit_device_name() -> None:
"""Report entities which use implicit device name."""
if self._implicit_device_name_reported:
return
report_issue = self._suggest_report_issue()
_LOGGER.warning(
(
"Entity %s (%s) is implicitly using device name by not setting its "
"name. Instead, the name should be set to None, please %s"
),
self.entity_id,
type(self),
report_issue,
)
self._implicit_device_name_reported = True
if hasattr(self, "_attr_name"):
return not self._attr_name
if name_translation_key := self._name_translation_key():
if name_translation_key in self.platform.platform_translations:
return False
if hasattr(self, "entity_description"):
if not (name := self.entity_description.name):
return True
if name is UNDEFINED:
# Backwards compatibility with leaving EntityDescription.name unassigned
# for device name.
# Deprecated in HA Core 2023.6, remove in HA Core 2023.9
report_implicit_device_name()
return True
return False
if self.name is UNDEFINED:
# Backwards compatibility with not overriding name property for device name.
# Deprecated in HA Core 2023.6, remove in HA Core 2023.9
report_implicit_device_name()
return True
return not self.name
@property
def has_entity_name(self) -> bool:
"""Return if the name of the entity is describing only the entity itself."""
@ -344,16 +394,23 @@ class Entity(ABC):
"""Return True if an unnamed entity should be named by its device class."""
return False
def _name_translation_key(self) -> str | None:
"""Return translation key for entity name."""
if self.translation_key is None:
return None
return (
f"component.{self.platform.platform_name}.entity.{self.platform.domain}"
f".{self.translation_key}.name"
)
@property
def name(self) -> str | None:
def name(self) -> str | UndefinedType | None:
"""Return the name of the entity."""
if hasattr(self, "_attr_name"):
return self._attr_name
if self.translation_key is not None and self.has_entity_name:
name_translation_key = (
f"component.{self.platform.platform_name}.entity.{self.platform.domain}"
f".{self.translation_key}.name"
)
if self.has_entity_name and (
name_translation_key := self._name_translation_key()
):
if name_translation_key in self.platform.platform_translations:
name: str = self.platform.platform_translations[name_translation_key]
return name
@ -361,15 +418,13 @@ class Entity(ABC):
description_name = self.entity_description.name
if description_name is UNDEFINED and self._default_to_device_class_name():
return self._device_class_name()
if description_name is not UNDEFINED:
return description_name
return None
return description_name
# The entity has no name set by _attr_name, translation_key or entity_description
# Check if the entity should be named by its device class
if self._default_to_device_class_name():
return self._device_class_name()
return None
return UNDEFINED
@property
def state(self) -> StateType:
@ -653,16 +708,20 @@ class Entity(ABC):
If has_entity_name is False, this returns self.name
If has_entity_name is True, this returns device.name + self.name
"""
name = self.name
if name is UNDEFINED:
name = None
if not self.has_entity_name or not self.registry_entry:
return self.name
return name
device_registry = dr.async_get(self.hass)
if not (device_id := self.registry_entry.device_id) or not (
device_entry := device_registry.async_get(device_id)
):
return self.name
return name
if not (name := self.name):
if self.use_device_name:
return device_entry.name_by_user or device_entry.name
return f"{device_entry.name_by_user or device_entry.name} {name}"