1
mirror of https://github.com/home-assistant/core synced 2024-09-06 10:29:55 +02:00

Revert "Allow setting an entity's name by its device class" (#93539)

This commit is contained in:
Erik Montnemery 2023-05-25 17:20:54 +02:00 committed by GitHub
parent f7404e2ee0
commit a71c097aeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 35 additions and 141 deletions

View File

@ -28,7 +28,7 @@ from homeassistant.const import (
UnitOfTime,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DEVICE_CLASS_NAME, DeviceInfo
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
@ -105,13 +105,6 @@ def sensor_update_to_bluetooth_data_update(
adv: Aranet4Advertisement,
) -> PassiveBluetoothDataUpdate:
"""Convert a sensor update to a Bluetooth data update."""
entity_names: dict[PassiveBluetoothEntityKey, str | None] = {}
for key, desc in SENSOR_DESCRIPTIONS.items():
# PassiveBluetoothDataUpdate does not support DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
assert desc.name is not DEVICE_CLASS_NAME
entity_names[_device_key_to_bluetooth_entity_key(adv.device, key)] = desc.name
return PassiveBluetoothDataUpdate(
devices={adv.device.address: _sensor_device_info_to_hass(adv)},
entity_descriptions={
@ -124,7 +117,10 @@ def sensor_update_to_bluetooth_data_update(
)
for key in SENSOR_DESCRIPTIONS
},
entity_names=entity_names,
entity_names={
_device_key_to_bluetooth_entity_key(adv.device, key): desc.name
for key, desc in SENSOR_DESCRIPTIONS.items()
},
)

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from pybalboa import EVENT_UPDATE, SpaClient
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.entity import DeviceClassName, DeviceInfo, Entity
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import DOMAIN
@ -12,9 +12,7 @@ from .const import DOMAIN
class BalboaBaseEntity(Entity):
"""Balboa base entity."""
def __init__(
self, client: SpaClient, name: str | DeviceClassName | None = None
) -> None:
def __init__(self, client: SpaClient, name: str | None = None) -> None:
"""Initialize the control."""
mac = client.mac_address
model = client.model

View File

@ -35,11 +35,6 @@ class BondButtonEntityDescription(
):
"""Class to describe a Bond Button entity."""
# BondEntity does not support DEVICE_CLASS_NAME
# Restrict the type to satisfy the type checker and catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
name: str | None = None
STOP_BUTTON = BondButtonEntityDescription(
key=Action.STOP,

View File

@ -88,7 +88,7 @@ class BruntDevice(
self._attr_attribution = ATTRIBUTION
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._attr_unique_id)}, # type: ignore[arg-type]
name=self._thing.name,
name=self._attr_name,
via_device=(DOMAIN, self._entry_id),
manufacturer="Brunt",
sw_version=self._thing.fw_version,

View File

@ -30,8 +30,8 @@ class FreeboxHomeEntity(Entity):
self._node = node
self._sub_node = sub_node
self._id = node["id"]
self._device_name = node["label"].strip()
self._attr_name = self._device_name
self._attr_name = node["label"].strip()
self._device_name = self._attr_name
self._attr_unique_id = f"{self._router.mac}-node_{self._id}"
if sub_node is not None:

View File

@ -28,10 +28,6 @@ class IncomfortSensorEntityDescription(SensorEntityDescription):
"""Describes Incomfort sensor entity."""
extra_key: str | None = None
# IncomfortSensor does not support DEVICE_CLASS_NAME
# Restrict the type to satisfy the type checker and catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
name: str | None = None
SENSOR_TYPES: tuple[IncomfortSensorEntityDescription, ...] = (

View File

@ -14,7 +14,6 @@ from homeassistant.const import (
STATE_ON,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import DEVICE_CLASS_NAME
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
@ -74,11 +73,6 @@ class ModbusBinarySensor(BasePlatform, RestoreEntity, BinarySensorEntity):
# this ensures that idx = bit position of value in result
# polling is done with the base class
name = self._attr_name if self._attr_name else "modbus_sensor"
# DataUpdateCoordinator does not support DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in _attr_name.
assert name is not DEVICE_CLASS_NAME
self._coordinator = DataUpdateCoordinator(
hass,
_LOGGER,

View File

@ -17,7 +17,6 @@ from homeassistant.const import (
CONF_UNIT_OF_MEASUREMENT,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import DEVICE_CLASS_NAME
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.helpers.update_coordinator import (
@ -80,11 +79,6 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity):
# this ensures that idx = bit position of value in result
# polling is done with the base class
name = self._attr_name if self._attr_name else "modbus_sensor"
# DataUpdateCoordinator does not support DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in _attr_name.
assert name is not DEVICE_CLASS_NAME
self._coordinator = DataUpdateCoordinator(
hass,
_LOGGER,

View File

@ -67,7 +67,7 @@ class MinutPointAlarmControl(AlarmControlPanelEntity):
self._attr_device_info = DeviceInfo(
identifiers={(POINT_DOMAIN, home_id)},
manufacturer="Minut",
name=self._home["name"],
name=self._attr_name,
)
async def async_added_to_hass(self) -> None:

View File

@ -19,7 +19,6 @@ from homeassistant.helpers.device_registry import (
async_get as dr_async_get,
format_mac,
)
from homeassistant.helpers.entity import DEVICE_CLASS_NAME, DeviceClassName
from homeassistant.helpers.entity_registry import async_get as er_async_get
from homeassistant.helpers.typing import EventType
from homeassistant.util.dt import utcnow
@ -73,16 +72,12 @@ def get_number_of_channels(device: BlockDevice, block: Block) -> int:
def get_block_entity_name(
device: BlockDevice,
block: Block | None,
description: str | DeviceClassName | None = None,
description: str | None = None,
) -> str:
"""Naming for block based switch and sensors."""
channel_name = get_block_channel_name(device, block)
if description:
# It's not possible to do string manipulations on DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME as description.
assert description is not DEVICE_CLASS_NAME
return f"{channel_name} {description.lower()}"
return channel_name
@ -306,16 +301,12 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str:
def get_rpc_entity_name(
device: RpcDevice, key: str, description: str | DeviceClassName | None = None
device: RpcDevice, key: str, description: str | None = None
) -> str:
"""Naming for RPC based switch and sensors."""
channel_name = get_rpc_channel_name(device, key)
if description:
# It's not possible to do string manipulations on DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME as description.
assert description is not DEVICE_CLASS_NAME
return f"{channel_name} {description.lower()}"
return channel_name

View File

@ -30,7 +30,7 @@ from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import DEVICE_CLASS_NAME, DeviceClassName, DeviceInfo
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN, MODULES
@ -279,17 +279,13 @@ class SystemBridgeEntity(CoordinatorEntity[SystemBridgeDataUpdateCoordinator]):
coordinator: SystemBridgeDataUpdateCoordinator,
api_port: int,
key: str,
name: str | DeviceClassName | None,
name: str | None,
) -> None:
"""Initialize the System Bridge entity."""
super().__init__(coordinator)
self._hostname = coordinator.data.system.hostname
self._key = f"{self._hostname}_{key}"
# It's not possible to do string manipulations on DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME as name.
assert name is not DEVICE_CLASS_NAME
self._name = f"{self._hostname} {name}"
self._configuration_url = (
f"http://{self._hostname}:{api_port}/app/settings.html"

View File

@ -32,7 +32,6 @@ from homeassistant.const import (
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DEVICE_CLASS_NAME
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import slugify
from homeassistant.util.unit_conversion import DistanceConverter, SpeedConverter
@ -350,10 +349,6 @@ class BaseTomorrowioSensorEntity(TomorrowioEntity, SensorEntity):
"""Initialize Tomorrow.io Sensor Entity."""
super().__init__(config_entry, coordinator, api_version)
self.entity_description = description
# It's not possible to do string manipulations on DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
assert description.name is not DEVICE_CLASS_NAME
self._attr_name = f"{self._config_entry.data[CONF_NAME]} - {description.name}"
self._attr_unique_id = (
f"{self._config_entry.unique_id}_{slugify(description.name)}"

View File

@ -22,12 +22,7 @@ from pyunifiprotect.data import (
from homeassistant.core import callback
import homeassistant.helpers.device_registry as dr
from homeassistant.helpers.entity import (
DEVICE_CLASS_NAME,
DeviceInfo,
Entity,
EntityDescription,
)
from homeassistant.helpers.entity import DeviceInfo, Entity, EntityDescription
from .const import (
ATTR_EVENT_ID,
@ -204,10 +199,6 @@ class ProtectDeviceEntity(Entity):
self.entity_description = description
self._attr_unique_id = f"{self.device.mac}_{description.key}"
name = description.name or ""
# It's not possible to do string manipulations on DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
assert name is not DEVICE_CLASS_NAME
self._attr_name = f"{self.device.display_name} {name.title()}"
self._attr_attribution = DEFAULT_ATTRIBUTION

View File

@ -131,8 +131,6 @@ async def async_setup_entry(
class VizioDevice(MediaPlayerEntity):
"""Media Player implementation which performs REST requests to device."""
_attr_name: str
def __init__(
self,
config_entry: ConfigEntry,

View File

@ -28,10 +28,6 @@ from .wemo_device import DeviceCoordinator
class AttributeSensorDescription(SensorEntityDescription):
"""SensorEntityDescription for WeMo AttributeSensor entities."""
# AttributeSensor does not support DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
name: str | None = None
state_conversion: Callable[[StateType], StateType] | None = None
unique_id_suffix: str | None = None

View File

@ -8,7 +8,7 @@ from zwave_js_server.model.value import Value as ZwaveValue, get_value_id_str
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import DEVICE_CLASS_NAME, DeviceInfo, Entity
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import DOMAIN, LOGGER
from .discovery import ZwaveDiscoveryInfo
@ -149,10 +149,6 @@ class ZWaveBaseEntity(Entity):
and self.entity_description
and self.entity_description.name
):
# It's not possible to do string manipulations on DEVICE_CLASS_NAME
# the assert satisfies the type checker and will catch attempts
# to use DEVICE_CLASS_NAME in the entity descriptions.
assert self.entity_description.name is not DEVICE_CLASS_NAME
name = self.entity_description.name
if name_prefix:

View File

@ -115,7 +115,7 @@ async def async_setup_platforms(
class ZWaveMeEntity(Entity):
"""Representation of a ZWaveMe device."""
def __init__(self, controller: ZWaveMeController, device: ZWaveMeData) -> None:
def __init__(self, controller, device):
"""Initialize the device."""
self.controller = controller
self.device = device
@ -124,9 +124,13 @@ class ZWaveMeEntity(Entity):
f"{self.controller.config.unique_id}-{self.device.id}"
)
self._attr_should_poll = False
self._attr_device_info = DeviceInfo(
@property
def device_info(self) -> DeviceInfo:
"""Return device specific attributes."""
return DeviceInfo(
identifiers={(DOMAIN, self.device.deviceIdentifier)},
name=device.title,
name=self._attr_name,
manufacturer=self.device.manufacturer,
sw_version=self.device.firmware,
suggested_area=self.device.locationName,

View File

@ -52,16 +52,6 @@ DATA_ENTITY_SOURCE = "entity_info"
SOURCE_CONFIG_ENTRY = "config_entry"
SOURCE_PLATFORM_CONFIG = "platform_config"
class DeviceClassName(Enum):
"""Singleton to use device class name."""
_singleton = 0
DEVICE_CLASS_NAME = DeviceClassName._singleton # pylint: disable=protected-access
# Used when converting float states to string: limit precision according to machine
# epsilon to make the string representation readable
FLOAT_PRECISION = abs(int(math.floor(math.log10(abs(sys.float_info.epsilon))))) - 1
@ -229,7 +219,7 @@ class EntityDescription:
force_update: bool = False
icon: str | None = None
has_entity_name: bool = False
name: str | DeviceClassName | None = None
name: str | None = None
translation_key: str | None = None
unit_of_measurement: str | None = None
@ -298,7 +288,7 @@ class Entity(ABC):
_attr_extra_state_attributes: MutableMapping[str, Any]
_attr_force_update: bool
_attr_icon: str | None
_attr_name: str | DeviceClassName | None
_attr_name: str | None
_attr_should_poll: bool = True
_attr_state: StateType = STATE_UNKNOWN
_attr_supported_features: int | None = None
@ -328,24 +318,10 @@ class Entity(ABC):
return self.entity_description.has_entity_name
return False
def _device_class_name(self) -> str | None:
"""Return a translated name of the entity based on its device class."""
assert self.platform
if not self.has_entity_name:
return None
device_class_key = self.device_class or "_"
name_translation_key = (
f"component.{self.platform.domain}.entity_component."
f"{device_class_key}.name"
)
return self.platform.component_translations.get(name_translation_key)
@property
def name(self) -> str | None:
"""Return the name of the entity."""
if hasattr(self, "_attr_name"):
if self._attr_name is DEVICE_CLASS_NAME:
return self._device_class_name()
return self._attr_name
if self.translation_key is not None and self.has_entity_name:
assert self.platform
@ -353,12 +329,10 @@ class Entity(ABC):
f"component.{self.platform.platform_name}.entity.{self.platform.domain}"
f".{self.translation_key}.name"
)
if name_translation_key in self.platform.platform_translations:
name: str = self.platform.platform_translations[name_translation_key]
if name_translation_key in self.platform.entity_translations:
name: str = self.platform.entity_translations[name_translation_key]
return name
if hasattr(self, "entity_description"):
if self.entity_description.name is DEVICE_CLASS_NAME:
return self._device_class_name()
return self.entity_description.name
return None

View File

@ -125,8 +125,7 @@ class EntityPlatform:
self.entity_namespace = entity_namespace
self.config_entry: config_entries.ConfigEntry | None = None
self.entities: dict[str, Entity] = {}
self.component_translations: dict[str, Any] = {}
self.platform_translations: dict[str, Any] = {}
self.entity_translations: dict[str, Any] = {}
self._tasks: list[asyncio.Task[None]] = []
# Stop tracking tasks after setup is completed
self._setup_complete = False
@ -280,15 +279,7 @@ class EntityPlatform:
full_name = f"{self.domain}.{self.platform_name}"
try:
self.component_translations = await translation.async_get_translations(
hass, hass.config.language, "entity_component", {self.domain}
)
except Exception as err: # pylint: disable=broad-exception-caught
_LOGGER.debug(
"Could not load translations for %s", self.domain, exc_info=err
)
try:
self.platform_translations = await translation.async_get_translations(
self.entity_translations = await translation.async_get_translations(
hass, hass.config.language, "entity", {self.platform_name}
)
except Exception as err: # pylint: disable=broad-exception-caught

View File

@ -172,8 +172,6 @@ class _TemplateAttribute:
class TemplateEntity(Entity):
"""Entity that uses templates to calculate attributes."""
_attr_name: str | None
_attr_available = True
_attr_entity_picture = None
_attr_icon = None

View File

@ -1,10 +1,9 @@
"""esphome session fixtures."""
from __future__ import annotations
from asyncio import Event
from unittest.mock import AsyncMock, Mock, patch
from aioesphomeapi import APIClient, APIVersion, DeviceInfo, ReconnectLogic
from aioesphomeapi import APIClient, APIVersion, DeviceInfo
import pytest
from zeroconf import Zeroconf
@ -159,18 +158,10 @@ async def mock_voice_assistant_v1_entry(
mock_client.device_info = AsyncMock(return_value=device_info)
mock_client.subscribe_voice_assistant = AsyncMock(return_value=Mock())
try_connect_done = Event()
real_try_connect = ReconnectLogic._try_connect
async def mock_try_connect(self):
"""Set an event when ReconnectLogic._try_connect has been awaited."""
result = await real_try_connect(self)
try_connect_done.set()
return result
with patch.object(ReconnectLogic, "_try_connect", mock_try_connect):
await hass.config_entries.async_setup(entry.entry_id)
await try_connect_done.wait()
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
await hass.async_block_till_done()
await hass.async_block_till_done()
return entry