Improve devolo_home_network generic typing (#85328)

This commit is contained in:
Marc Mueller 2023-01-07 14:12:03 +01:00 committed by GitHub
parent b27e89b40e
commit e99840f82c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 25 deletions

View file

@ -2,6 +2,7 @@
from __future__ import annotations
import logging
from typing import Any
import async_timeout
from devolo_plc_api import Device
@ -80,7 +81,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Disconnect from device."""
await device.async_disconnect()
coordinators: dict[str, DataUpdateCoordinator] = {}
coordinators: dict[str, DataUpdateCoordinator[Any]] = {}
if device.plcnet:
coordinators[CONNECTED_PLC_DEVICES] = DataUpdateCoordinator(
hass,

View file

@ -3,8 +3,10 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from devolo_plc_api import Device
from devolo_plc_api.plcnet_api import LogicalNetwork
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
@ -62,9 +64,9 @@ async def async_setup_entry(
) -> None:
"""Get all devices and sensors and setup them via config entry."""
device: Device = hass.data[DOMAIN][entry.entry_id]["device"]
coordinators: dict[str, DataUpdateCoordinator] = hass.data[DOMAIN][entry.entry_id][
"coordinators"
]
coordinators: dict[str, DataUpdateCoordinator[Any]] = hass.data[DOMAIN][
entry.entry_id
]["coordinators"]
entities: list[BinarySensorEntity] = []
if device.plcnet:
@ -79,12 +81,12 @@ async def async_setup_entry(
async_add_entities(entities)
class DevoloBinarySensorEntity(DevoloEntity, BinarySensorEntity):
class DevoloBinarySensorEntity(DevoloEntity[LogicalNetwork], BinarySensorEntity):
"""Representation of a devolo binary sensor."""
def __init__(
self,
coordinator: DataUpdateCoordinator,
coordinator: DataUpdateCoordinator[LogicalNetwork],
description: DevoloBinarySensorEntityDescription,
device: Device,
device_name: str,

View file

@ -88,7 +88,10 @@ class DevoloScannerEntity(
"""Representation of a devolo device tracker."""
def __init__(
self, coordinator: DataUpdateCoordinator, device: Device, mac: str
self,
coordinator: DataUpdateCoordinator[list[ConnectedStationInfo]],
device: Device,
mac: str,
) -> None:
"""Initialize entity."""
super().__init__(coordinator)

View file

@ -1,7 +1,11 @@
"""Generic platform."""
from __future__ import annotations
from typing import TypeVar, Union
from devolo_plc_api.device import Device
from devolo_plc_api.device_api import ConnectedStationInfo, NeighborAPInfo
from devolo_plc_api.plcnet_api import LogicalNetwork
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import (
@ -11,14 +15,26 @@ from homeassistant.helpers.update_coordinator import (
from .const import DOMAIN
_DataT = TypeVar(
"_DataT",
bound=Union[
LogicalNetwork,
list[ConnectedStationInfo],
list[NeighborAPInfo],
],
)
class DevoloEntity(CoordinatorEntity):
class DevoloEntity(CoordinatorEntity[DataUpdateCoordinator[_DataT]]):
"""Representation of a devolo home network device."""
_attr_has_entity_name = True
def __init__(
self, coordinator: DataUpdateCoordinator, device: Device, device_name: str
self,
coordinator: DataUpdateCoordinator[_DataT],
device: Device,
device_name: str,
) -> None:
"""Initialize a devolo home network device."""
super().__init__(coordinator)

View file

@ -3,9 +3,11 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from typing import Any, Generic, TypeVar, Union
from devolo_plc_api.device import Device
from devolo_plc_api.device_api import ConnectedStationInfo, NeighborAPInfo
from devolo_plc_api.plcnet_api import LogicalNetwork
from homeassistant.components.sensor import (
SensorEntity,
@ -26,23 +28,32 @@ from .const import (
)
from .entity import DevoloEntity
_DataT = TypeVar(
"_DataT",
bound=Union[
LogicalNetwork,
list[ConnectedStationInfo],
list[NeighborAPInfo],
],
)
@dataclass
class DevoloSensorRequiredKeysMixin:
class DevoloSensorRequiredKeysMixin(Generic[_DataT]):
"""Mixin for required keys."""
value_func: Callable[[Any], int]
value_func: Callable[[_DataT], int]
@dataclass
class DevoloSensorEntityDescription(
SensorEntityDescription, DevoloSensorRequiredKeysMixin
SensorEntityDescription, DevoloSensorRequiredKeysMixin[_DataT]
):
"""Describes devolo sensor entity."""
SENSOR_TYPES: dict[str, DevoloSensorEntityDescription] = {
CONNECTED_PLC_DEVICES: DevoloSensorEntityDescription(
SENSOR_TYPES: dict[str, DevoloSensorEntityDescription[Any]] = {
CONNECTED_PLC_DEVICES: DevoloSensorEntityDescription[LogicalNetwork](
key=CONNECTED_PLC_DEVICES,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
@ -52,7 +63,7 @@ SENSOR_TYPES: dict[str, DevoloSensorEntityDescription] = {
{device.mac_address_from for device in data.data_rates}
),
),
CONNECTED_WIFI_CLIENTS: DevoloSensorEntityDescription(
CONNECTED_WIFI_CLIENTS: DevoloSensorEntityDescription[list[ConnectedStationInfo]](
key=CONNECTED_WIFI_CLIENTS,
entity_registry_enabled_default=True,
icon="mdi:wifi",
@ -60,7 +71,7 @@ SENSOR_TYPES: dict[str, DevoloSensorEntityDescription] = {
state_class=SensorStateClass.MEASUREMENT,
value_func=len,
),
NEIGHBORING_WIFI_NETWORKS: DevoloSensorEntityDescription(
NEIGHBORING_WIFI_NETWORKS: DevoloSensorEntityDescription[list[NeighborAPInfo]](
key=NEIGHBORING_WIFI_NETWORKS,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
@ -76,11 +87,11 @@ async def async_setup_entry(
) -> None:
"""Get all devices and sensors and setup them via config entry."""
device: Device = hass.data[DOMAIN][entry.entry_id]["device"]
coordinators: dict[str, DataUpdateCoordinator] = hass.data[DOMAIN][entry.entry_id][
"coordinators"
]
coordinators: dict[str, DataUpdateCoordinator[Any]] = hass.data[DOMAIN][
entry.entry_id
]["coordinators"]
entities: list[DevoloSensorEntity] = []
entities: list[DevoloSensorEntity[Any]] = []
if device.plcnet:
entities.append(
DevoloSensorEntity(
@ -110,18 +121,20 @@ async def async_setup_entry(
async_add_entities(entities)
class DevoloSensorEntity(DevoloEntity, SensorEntity):
class DevoloSensorEntity(DevoloEntity[_DataT], SensorEntity):
"""Representation of a devolo sensor."""
entity_description: DevoloSensorEntityDescription[_DataT]
def __init__(
self,
coordinator: DataUpdateCoordinator,
description: DevoloSensorEntityDescription,
coordinator: DataUpdateCoordinator[_DataT],
description: DevoloSensorEntityDescription[_DataT],
device: Device,
device_name: str,
) -> None:
"""Initialize entity."""
self.entity_description: DevoloSensorEntityDescription = description
self.entity_description = description
super().__init__(coordinator, device, device_name)
@property