Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Erik
d4a283ca16 Silence mypy 2023-12-19 09:51:21 +01:00
Erik
c59a80cfed Freeze base component entity descriptions 2023-12-19 08:48:48 +01:00
32 changed files with 90 additions and 40 deletions

View file

@ -1,6 +1,7 @@
"""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
@ -120,7 +121,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class AlarmControlPanelEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class AlarmControlPanelEntityDescription(EntityDescription):
"""A class that describes alarm control panel entities."""

View file

@ -1,6 +1,7 @@
"""Component to interface with binary sensors."""
from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
from enum import StrEnum
import logging
@ -175,7 +176,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class BinarySensorEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class BinarySensorEntityDescription(EntityDescription):
"""A class that describes binary sensor entities."""
device_class: BinarySensorDeviceClass | None = None

View file

@ -93,11 +93,8 @@ 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):
for field in cached_fields(descriptions_class): # type: ignore[arg-type]
field_name = field.name
# It would be nice if field.type returned the actual
# type instead of a str so we could avoid writing this
@ -117,7 +114,7 @@ def serialize_entity_description(description: EntityDescription) -> dict[str, An
as_dict = dataclasses.asdict(description)
return {
field.name: as_dict[field.name]
for field in cached_fields(type(description))
for field in cached_fields(type(description)) # type: ignore[arg-type]
if field.default != as_dict.get(field.name)
}

View file

@ -1,6 +1,7 @@
"""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
@ -72,7 +73,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class ButtonEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class ButtonEntityDescription(EntityDescription):
"""A class that describes button entities."""
device_class: ButtonDeviceClass | None = None

View file

@ -5,7 +5,7 @@ import asyncio
import collections
from collections.abc import Awaitable, Callable, Iterable
from contextlib import suppress
from dataclasses import asdict
from dataclasses import asdict, dataclass
from datetime import datetime, timedelta
from enum import IntFlag
from functools import partial
@ -132,7 +132,8 @@ CAMERA_SERVICE_RECORD: Final = {
}
class CameraEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class CameraEntityDescription(EntityDescription):
"""A class that describes camera entities."""

View file

@ -1,6 +1,7 @@
"""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
@ -200,7 +201,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class ClimateEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class ClimateEntityDescription(EntityDescription):
"""A class that describes climate entities."""

View file

@ -2,6 +2,7 @@
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
@ -211,7 +212,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class CoverEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class CoverEntityDescription(EntityDescription):
"""A class that describes cover entities."""
device_class: CoverDeviceClass | None = None

View file

@ -1,6 +1,7 @@
"""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
@ -61,7 +62,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class DateEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class DateEntityDescription(EntityDescription):
"""A class that describes date entities."""

View file

@ -1,6 +1,7 @@
"""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
@ -70,7 +71,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class DateTimeEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class DateTimeEntityDescription(EntityDescription):
"""A class that describes date/time entities."""

View file

@ -71,7 +71,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class EventEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class EventEntityDescription(EntityDescription):
"""A class that describes event entities."""
device_class: EventDeviceClass | None = None

View file

@ -1,6 +1,7 @@
"""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
@ -186,7 +187,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class FanEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class FanEntityDescription(ToggleEntityDescription):
"""A class that describes fan entities."""

View file

@ -1,6 +1,7 @@
"""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
@ -123,7 +124,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class HumidifierEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class HumidifierEntityDescription(ToggleEntityDescription):
"""A class that describes humidifier entities."""
device_class: HumidifierDeviceClass | None = None

View file

@ -44,7 +44,8 @@ _RND: Final = SystemRandom()
GET_IMAGE_TIMEOUT: Final = 10
class ImageEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class ImageEntityDescription(EntityDescription):
"""A class that describes image entities."""

View file

@ -2,6 +2,7 @@
from __future__ import annotations
import asyncio
from dataclasses import dataclass
from datetime import timedelta
from enum import StrEnum
import logging
@ -119,7 +120,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
return True
class ImageProcessingEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class ImageProcessingEntityDescription(EntityDescription):
"""A class that describes sensor entities."""
device_class: ImageProcessingDeviceClass | None = None

View file

@ -1,6 +1,7 @@
"""The lawn mower integration."""
from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
import logging
from typing import final
@ -64,7 +65,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class LawnMowerEntityEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class LawnMowerEntityEntityDescription(EntityDescription):
"""A class that describes lawn mower entities."""

View file

@ -816,7 +816,8 @@ class Profiles:
params.setdefault(ATTR_TRANSITION, profile.transition)
class LightEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclasses.dataclass(frozen=True)
class LightEntityDescription(ToggleEntityDescription):
"""A class that describes binary sensor entities."""

View file

@ -1,6 +1,7 @@
"""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
@ -100,7 +101,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class LockEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class LockEntityDescription(EntityDescription):
"""A class that describes lock entities."""

View file

@ -5,6 +5,7 @@ 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
@ -448,7 +449,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class MediaPlayerEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class MediaPlayerEntityDescription(EntityDescription):
"""A class that describes media player entities."""
device_class: MediaPlayerDeviceClass | None = None

View file

@ -120,7 +120,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class NumberEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclasses.dataclass(frozen=True)
class NumberEntityDescription(EntityDescription):
"""A class that describes number entities."""
device_class: NumberDeviceClass | None = None

View file

@ -2,6 +2,7 @@
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
@ -154,7 +155,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class RemoteEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class RemoteEntityDescription(ToggleEntityDescription):
"""A class that describes remote entities."""

View file

@ -1,6 +1,7 @@
"""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
@ -117,7 +118,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class SelectEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class SelectEntityDescription(EntityDescription):
"""A class that describes select entities."""
options: list[str] | None = None

View file

@ -136,7 +136,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class SensorEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class SensorEntityDescription(EntityDescription):
"""A class that describes sensor entities."""
device_class: SensorDeviceClass | None = None

View file

@ -1,6 +1,7 @@
"""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
@ -148,7 +149,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class SirenEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class SirenEntityDescription(ToggleEntityDescription):
"""A class that describes siren entities."""
available_tones: list[int | str] | dict[int, str] | None = None

View file

@ -1,6 +1,7 @@
"""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
@ -88,7 +89,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class SwitchEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class SwitchEntityDescription(ToggleEntityDescription):
"""A class that describes switch entities."""
device_class: SwitchDeviceClass | None = None

View file

@ -98,7 +98,8 @@ class TextMode(StrEnum):
TEXT = "text"
class TextEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class TextEntityDescription(EntityDescription):
"""A class that describes text entities."""
native_min: int = 0

View file

@ -1,6 +1,7 @@
"""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
@ -61,7 +62,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class TimeEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class TimeEntityDescription(EntityDescription):
"""A class that describes time entities."""

View file

@ -564,7 +564,7 @@ class ProtectDeviceBinarySensor(ProtectDeviceEntity, BinarySensorEntity):
updated_device.mount_type, BinarySensorDeviceClass.DOOR
)
else:
self._attr_device_class = self.entity_description.device_class
self._attr_device_class = self.entity_description.device_class # type: ignore[assignment]
class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):

View file

@ -1,6 +1,7 @@
"""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
@ -174,7 +175,8 @@ async def async_clear_skipped(entity: UpdateEntity, service_call: ServiceCall) -
await entity.async_clear_skipped()
class UpdateEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class UpdateEntityDescription(EntityDescription):
"""A class that describes update entities."""
device_class: UpdateDeviceClass | None = None

View file

@ -3,6 +3,7 @@ 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
@ -366,7 +367,8 @@ class _BaseVacuum(Entity):
)
class VacuumEntityDescription(ToggleEntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class VacuumEntityDescription(ToggleEntityDescription):
"""A class that describes vacuum entities."""
@ -488,7 +490,8 @@ class VacuumEntity(_BaseVacuum, ToggleEntity):
await self.hass.async_add_executor_job(partial(self.start_pause, **kwargs))
class StateVacuumEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class StateVacuumEntityDescription(EntityDescription):
"""A class that describes vacuum entities."""

View file

@ -2,6 +2,7 @@
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
@ -155,7 +156,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class WaterHeaterEntityEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class WaterHeaterEntityEntityDescription(EntityDescription):
"""A class that describes water heater entities."""

View file

@ -5,6 +5,7 @@ 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
@ -250,7 +251,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await component.async_unload_entry(entry)
class WeatherEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclass(frozen=True)
class WeatherEntityDescription(EntityDescription):
"""A class that describes weather entities."""

View file

@ -52,7 +52,6 @@ from homeassistant.exceptions import (
)
from homeassistant.loader import async_suggest_report_issue, bind_hass
from homeassistant.util import ensure_unique_string, slugify
from homeassistant.util.frozen_dataclass_compat import FrozenOrThawed
from . import device_registry as dr, entity_registry as er
from .device_registry import DeviceInfo, EventDeviceRegistryUpdatedData
@ -225,7 +224,8 @@ class EntityPlatformState(Enum):
REMOVED = auto()
class EntityDescription(metaclass=FrozenOrThawed, frozen_or_thawed=True):
@dataclasses.dataclass(frozen=True)
class EntityDescription:
"""A class that describes Home Assistant entities."""
# This is the key identifier for this entity
@ -1313,7 +1313,8 @@ class Entity(ABC):
)
class ToggleEntityDescription(EntityDescription, frozen_or_thawed=True):
@dataclasses.dataclass(frozen=True, slots=True)
class ToggleEntityDescription(EntityDescription):
"""A class that describes toggle entities."""