Allow inheriting base component entity descriptions in frozen dataclasses (#105512)
Co-authored-by: J. Nick Koston <nick@koston.org>pull/105841/head^2
parent
47f8e08261
commit
104bcc64b7
|
@ -1,7 +1,6 @@
|
|||
"""Component to interface with an alarm control panel."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any, Final, final
|
||||
|
@ -121,8 +120,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class AlarmControlPanelEntityDescription(EntityDescription):
|
||||
class AlarmControlPanelEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes alarm control panel entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to interface with binary sensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
@ -176,8 +175,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class BinarySensorEntityDescription(EntityDescription):
|
||||
class BinarySensorEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes binary sensor entities."""
|
||||
|
||||
device_class: BinarySensorDeviceClass | None = None
|
||||
|
|
|
@ -93,7 +93,10 @@ def deserialize_entity_description(
|
|||
descriptions_class: type[EntityDescription], data: dict[str, Any]
|
||||
) -> EntityDescription:
|
||||
"""Deserialize an entity description."""
|
||||
# pylint: disable=protected-access
|
||||
result: dict[str, Any] = {}
|
||||
if hasattr(descriptions_class, "_dataclass"):
|
||||
descriptions_class = descriptions_class._dataclass
|
||||
for field in cached_fields(descriptions_class):
|
||||
field_name = field.name
|
||||
# It would be nice if field.type returned the actual
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to pressing a button as platforms."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
@ -73,8 +72,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ButtonEntityDescription(EntityDescription):
|
||||
class ButtonEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes button entities."""
|
||||
|
||||
device_class: ButtonDeviceClass | None = None
|
||||
|
|
|
@ -5,7 +5,7 @@ import asyncio
|
|||
import collections
|
||||
from collections.abc import Awaitable, Callable, Iterable
|
||||
from contextlib import suppress
|
||||
from dataclasses import asdict, dataclass
|
||||
from dataclasses import asdict
|
||||
from datetime import datetime, timedelta
|
||||
from enum import IntFlag
|
||||
from functools import partial
|
||||
|
@ -132,8 +132,7 @@ CAMERA_SERVICE_RECORD: Final = {
|
|||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class CameraEntityDescription(EntityDescription):
|
||||
class CameraEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes camera entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Provides functionality to interact with climate devices."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import functools as ft
|
||||
import logging
|
||||
|
@ -201,8 +200,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ClimateEntityDescription(EntityDescription):
|
||||
class ClimateEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes climate entities."""
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import IntFlag, StrEnum
|
||||
import functools as ft
|
||||
|
@ -212,8 +211,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class CoverEntityDescription(EntityDescription):
|
||||
class CoverEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes cover entities."""
|
||||
|
||||
device_class: CoverDeviceClass | None = None
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to allow setting date as platforms."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import date, timedelta
|
||||
import logging
|
||||
from typing import final
|
||||
|
@ -62,8 +61,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DateEntityDescription(EntityDescription):
|
||||
class DateEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes date entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to allow setting date/time as platforms."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import UTC, datetime, timedelta
|
||||
import logging
|
||||
from typing import final
|
||||
|
@ -71,8 +70,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DateTimeEntityDescription(EntityDescription):
|
||||
class DateTimeEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes date/time entities."""
|
||||
|
||||
|
||||
|
|
|
@ -71,8 +71,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class EventEntityDescription(EntityDescription):
|
||||
class EventEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes event entities."""
|
||||
|
||||
device_class: EventDeviceClass | None = None
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Provides functionality to interact with fans."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import IntFlag
|
||||
import functools as ft
|
||||
|
@ -187,8 +186,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FanEntityDescription(ToggleEntityDescription):
|
||||
class FanEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes fan entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Provides functionality to interact with humidifier devices."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
@ -124,8 +123,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HumidifierEntityDescription(ToggleEntityDescription):
|
||||
class HumidifierEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes humidifier entities."""
|
||||
|
||||
device_class: HumidifierDeviceClass | None = None
|
||||
|
|
|
@ -44,8 +44,7 @@ _RND: Final = SystemRandom()
|
|||
GET_IMAGE_TIMEOUT: Final = 10
|
||||
|
||||
|
||||
@dataclass
|
||||
class ImageEntityDescription(EntityDescription):
|
||||
class ImageEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes image entities."""
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
@ -120,8 +119,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
return True
|
||||
|
||||
|
||||
@dataclass
|
||||
class ImageProcessingEntityDescription(EntityDescription):
|
||||
class ImageProcessingEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes sensor entities."""
|
||||
|
||||
device_class: ImageProcessingDeviceClass | None = None
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""The lawn mower integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import final
|
||||
|
@ -65,8 +64,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class LawnMowerEntityEntityDescription(EntityDescription):
|
||||
class LawnMowerEntityEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes lawn mower entities."""
|
||||
|
||||
|
||||
|
|
|
@ -816,8 +816,7 @@ class Profiles:
|
|||
params.setdefault(ATTR_TRANSITION, profile.transition)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class LightEntityDescription(ToggleEntityDescription):
|
||||
class LightEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes binary sensor entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to interface with locks that can be controlled remotely."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import IntFlag
|
||||
import functools as ft
|
||||
|
@ -101,8 +100,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class LockEntityDescription(EntityDescription):
|
||||
class LockEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes lock entities."""
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import asyncio
|
|||
import collections
|
||||
from collections.abc import Callable
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
import datetime as dt
|
||||
from enum import StrEnum
|
||||
import functools as ft
|
||||
|
@ -449,8 +448,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class MediaPlayerEntityDescription(EntityDescription):
|
||||
class MediaPlayerEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes media player entities."""
|
||||
|
||||
device_class: MediaPlayerDeviceClass | None = None
|
||||
|
|
|
@ -120,8 +120,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class NumberEntityDescription(EntityDescription):
|
||||
class NumberEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes number entities."""
|
||||
|
||||
device_class: NumberDeviceClass | None = None
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import IntFlag
|
||||
import functools as ft
|
||||
|
@ -155,8 +154,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RemoteEntityDescription(ToggleEntityDescription):
|
||||
class RemoteEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes remote entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to allow selecting an option from a list as platforms."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any, final
|
||||
|
@ -118,8 +117,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SelectEntityDescription(EntityDescription):
|
||||
class SelectEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes select entities."""
|
||||
|
||||
options: list[str] | None = None
|
||||
|
|
|
@ -136,8 +136,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SensorEntityDescription(EntityDescription):
|
||||
class SensorEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes sensor entities."""
|
||||
|
||||
device_class: SensorDeviceClass | None = None
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to interface with various sirens/chimes."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any, TypedDict, cast, final
|
||||
|
@ -149,8 +148,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SirenEntityDescription(ToggleEntityDescription):
|
||||
class SirenEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes siren entities."""
|
||||
|
||||
available_tones: list[int | str] | dict[int, str] | None = None
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to interface with switches that can be controlled remotely."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
@ -89,8 +88,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SwitchEntityDescription(ToggleEntityDescription):
|
||||
class SwitchEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes switch entities."""
|
||||
|
||||
device_class: SwitchDeviceClass | None = None
|
||||
|
|
|
@ -98,8 +98,7 @@ class TextMode(StrEnum):
|
|||
TEXT = "text"
|
||||
|
||||
|
||||
@dataclass
|
||||
class TextEntityDescription(EntityDescription):
|
||||
class TextEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes text entities."""
|
||||
|
||||
native_min: int = 0
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to allow setting time as platforms."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import time, timedelta
|
||||
import logging
|
||||
from typing import final
|
||||
|
@ -62,8 +61,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TimeEntityDescription(EntityDescription):
|
||||
class TimeEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes time entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Component to allow for providing device or service updates."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import StrEnum
|
||||
from functools import lru_cache
|
||||
|
@ -175,8 +174,7 @@ async def async_clear_skipped(entity: UpdateEntity, service_call: ServiceCall) -
|
|||
await entity.async_clear_skipped()
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpdateEntityDescription(EntityDescription):
|
||||
class UpdateEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes update entities."""
|
||||
|
||||
device_class: UpdateDeviceClass | None = None
|
||||
|
|
|
@ -3,7 +3,6 @@ from __future__ import annotations
|
|||
|
||||
import asyncio
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import IntFlag
|
||||
from functools import partial
|
||||
|
@ -367,8 +366,7 @@ class _BaseVacuum(Entity):
|
|||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class VacuumEntityDescription(ToggleEntityDescription):
|
||||
class VacuumEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes vacuum entities."""
|
||||
|
||||
|
||||
|
@ -490,8 +488,7 @@ class VacuumEntity(_BaseVacuum, ToggleEntity):
|
|||
await self.hass.async_add_executor_job(partial(self.start_pause, **kwargs))
|
||||
|
||||
|
||||
@dataclass
|
||||
class StateVacuumEntityDescription(EntityDescription):
|
||||
class StateVacuumEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes vacuum entities."""
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from enum import IntFlag
|
||||
import functools as ft
|
||||
|
@ -156,8 +155,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class WaterHeaterEntityEntityDescription(EntityDescription):
|
||||
class WaterHeaterEntityEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes water heater entities."""
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import abc
|
|||
import asyncio
|
||||
from collections.abc import Callable, Iterable
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from functools import partial
|
||||
import logging
|
||||
|
@ -251,8 +250,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return await component.async_unload_entry(entry)
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeatherEntityDescription(EntityDescription):
|
||||
class WeatherEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes weather entities."""
|
||||
|
||||
|
||||
|
|
|
@ -1313,8 +1313,7 @@ class Entity(ABC):
|
|||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(slots=True)
|
||||
class ToggleEntityDescription(EntityDescription):
|
||||
class ToggleEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||
"""A class that describes toggle entities."""
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue