From 27f81b3f631dadbecd42d9ddfc640c9e70038d88 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 18 Dec 2023 20:58:32 +0100 Subject: [PATCH] Avoid mutating entity descriptions in unifiprotect (#105976) --- .../components/unifiprotect/binary_sensor.py | 19 +++++++++++-------- .../components/unifiprotect/models.py | 8 +++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/unifiprotect/binary_sensor.py b/homeassistant/components/unifiprotect/binary_sensor.py index 8f8bcab8ede..0be18249e31 100644 --- a/homeassistant/components/unifiprotect/binary_sensor.py +++ b/homeassistant/components/unifiprotect/binary_sensor.py @@ -1,8 +1,7 @@ """Component providing binary sensors for UniFi Protect.""" from __future__ import annotations -from copy import copy -from dataclasses import dataclass +import dataclasses import logging from pyunifiprotect.data import ( @@ -43,14 +42,14 @@ _LOGGER = logging.getLogger(__name__) _KEY_DOOR = "door" -@dataclass +@dataclasses.dataclass class ProtectBinaryEntityDescription( ProtectRequiredKeysMixin, BinarySensorEntityDescription ): """Describes UniFi Protect Binary Sensor entity.""" -@dataclass +@dataclasses.dataclass class ProtectBinaryEventEntityDescription( ProtectEventMixin, BinarySensorEntityDescription ): @@ -561,9 +560,11 @@ class ProtectDeviceBinarySensor(ProtectDeviceEntity, BinarySensorEntity): self._attr_is_on = entity_description.get_ufp_value(updated_device) # UP Sense can be any of the 3 contact sensor device classes if entity_description.key == _KEY_DOOR and isinstance(updated_device, Sensor): - entity_description.device_class = MOUNT_DEVICE_CLASS_MAP.get( + self._attr_device_class = MOUNT_DEVICE_CLASS_MAP.get( updated_device.mount_type, BinarySensorDeviceClass.DOOR ) + else: + self._attr_device_class = self.entity_description.device_class class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity): @@ -584,9 +585,11 @@ class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity): # backwards compat with old unique IDs index = self._disk.slot - 1 - description = copy(description) - description.key = f"{description.key}_{index}" - description.name = f"{disk.type} {disk.slot}" + description = dataclasses.replace( + description, + key=f"{description.key}_{index}", + name=f"{disk.type} {disk.slot}", + ) super().__init__(data, device, description) @callback diff --git a/homeassistant/components/unifiprotect/models.py b/homeassistant/components/unifiprotect/models.py index c250a021340..9f57b92163c 100644 --- a/homeassistant/components/unifiprotect/models.py +++ b/homeassistant/components/unifiprotect/models.py @@ -52,9 +52,11 @@ class ProtectRequiredKeysMixin(EntityDescription, Generic[T]): def __post_init__(self) -> None: """Pre-convert strings to tuples for faster get_nested_attr.""" - self.ufp_required_field = split_tuple(self.ufp_required_field) - self.ufp_value = split_tuple(self.ufp_value) - self.ufp_enabled = split_tuple(self.ufp_enabled) + object.__setattr__( + self, "ufp_required_field", split_tuple(self.ufp_required_field) + ) + object.__setattr__(self, "ufp_value", split_tuple(self.ufp_value)) + object.__setattr__(self, "ufp_enabled", split_tuple(self.ufp_enabled)) def get_ufp_value(self, obj: T) -> Any: """Return value from UniFi Protect device."""