Use PEP 695 TypeVar syntax for unifi (#147157)

This commit is contained in:
Marc Mueller 2025-06-23 10:34:35 +02:00 committed by GitHub
parent 93030ad48d
commit 10c573bbc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 45 additions and 44 deletions

View File

@ -11,11 +11,11 @@ import secrets
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
import aiounifi import aiounifi
from aiounifi.interfaces.api_handlers import ItemEvent from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
from aiounifi.interfaces.devices import Devices from aiounifi.interfaces.devices import Devices
from aiounifi.interfaces.ports import Ports from aiounifi.interfaces.ports import Ports
from aiounifi.interfaces.wlans import Wlans from aiounifi.interfaces.wlans import Wlans
from aiounifi.models.api import ApiItemT from aiounifi.models.api import ApiItem
from aiounifi.models.device import ( from aiounifi.models.device import (
Device, Device,
DevicePowerCyclePortRequest, DevicePowerCyclePortRequest,
@ -35,7 +35,6 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import UnifiConfigEntry from . import UnifiConfigEntry
from .entity import ( from .entity import (
HandlerT,
UnifiEntity, UnifiEntity,
UnifiEntityDescription, UnifiEntityDescription,
async_device_available_fn, async_device_available_fn,
@ -81,7 +80,7 @@ async def async_regenerate_password_control_fn(
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiButtonEntityDescription( class UnifiButtonEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
ButtonEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT] ButtonEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT]
): ):
"""Class describing UniFi button entity.""" """Class describing UniFi button entity."""
@ -143,7 +142,9 @@ async def async_setup_entry(
) )
class UnifiButtonEntity(UnifiEntity[HandlerT, ApiItemT], ButtonEntity): class UnifiButtonEntity[HandlerT: APIHandler, ApiItemT: ApiItem](
UnifiEntity[HandlerT, ApiItemT], ButtonEntity
):
"""Base representation of a UniFi button.""" """Base representation of a UniFi button."""
entity_description: UnifiButtonEntityDescription[HandlerT, ApiItemT] entity_description: UnifiButtonEntityDescription[HandlerT, ApiItemT]

View File

@ -9,10 +9,10 @@ import logging
from typing import Any from typing import Any
import aiounifi import aiounifi
from aiounifi.interfaces.api_handlers import ItemEvent from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
from aiounifi.interfaces.clients import Clients from aiounifi.interfaces.clients import Clients
from aiounifi.interfaces.devices import Devices from aiounifi.interfaces.devices import Devices
from aiounifi.models.api import ApiItemT from aiounifi.models.api import ApiItem
from aiounifi.models.client import Client from aiounifi.models.client import Client
from aiounifi.models.device import Device from aiounifi.models.device import Device
from aiounifi.models.event import Event, EventKey from aiounifi.models.event import Event, EventKey
@ -31,12 +31,7 @@ from homeassistant.util import dt as dt_util
from . import UnifiConfigEntry from . import UnifiConfigEntry
from .const import DOMAIN from .const import DOMAIN
from .entity import ( from .entity import UnifiEntity, UnifiEntityDescription, async_device_available_fn
HandlerT,
UnifiEntity,
UnifiEntityDescription,
async_device_available_fn,
)
from .hub import UnifiHub from .hub import UnifiHub
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
@ -142,7 +137,7 @@ def async_device_heartbeat_timedelta_fn(hub: UnifiHub, obj_id: str) -> timedelta
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiTrackerEntityDescription( class UnifiTrackerEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
UnifiEntityDescription[HandlerT, ApiItemT], ScannerEntityDescription UnifiEntityDescription[HandlerT, ApiItemT], ScannerEntityDescription
): ):
"""Class describing UniFi device tracker entity.""" """Class describing UniFi device tracker entity."""
@ -229,7 +224,9 @@ async def async_setup_entry(
) )
class UnifiScannerEntity(UnifiEntity[HandlerT, ApiItemT], ScannerEntity): class UnifiScannerEntity[HandlerT: APIHandler, ApiItemT: ApiItem](
UnifiEntity[HandlerT, ApiItemT], ScannerEntity
):
"""Representation of a UniFi scanner.""" """Representation of a UniFi scanner."""
entity_description: UnifiTrackerEntityDescription entity_description: UnifiTrackerEntityDescription

View File

@ -5,7 +5,7 @@ from __future__ import annotations
from abc import abstractmethod from abc import abstractmethod
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import TYPE_CHECKING, Generic, TypeVar from typing import TYPE_CHECKING
import aiounifi import aiounifi
from aiounifi.interfaces.api_handlers import ( from aiounifi.interfaces.api_handlers import (
@ -14,7 +14,7 @@ from aiounifi.interfaces.api_handlers import (
ItemEvent, ItemEvent,
UnsubscribeType, UnsubscribeType,
) )
from aiounifi.models.api import ApiItemT from aiounifi.models.api import ApiItem
from aiounifi.models.event import Event, EventKey from aiounifi.models.event import Event, EventKey
from homeassistant.core import callback from homeassistant.core import callback
@ -32,8 +32,7 @@ from .const import ATTR_MANUFACTURER, DOMAIN
if TYPE_CHECKING: if TYPE_CHECKING:
from .hub import UnifiHub from .hub import UnifiHub
HandlerT = TypeVar("HandlerT", bound=APIHandler) type SubscriptionType = Callable[[CallbackType, ItemEvent], UnsubscribeType]
SubscriptionT = Callable[[CallbackType, ItemEvent], UnsubscribeType]
@callback @callback
@ -95,7 +94,9 @@ def async_client_device_info_fn(hub: UnifiHub, obj_id: str) -> DeviceInfo:
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiEntityDescription(EntityDescription, Generic[HandlerT, ApiItemT]): class UnifiEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
EntityDescription
):
"""UniFi Entity Description.""" """UniFi Entity Description."""
api_handler_fn: Callable[[aiounifi.Controller], HandlerT] api_handler_fn: Callable[[aiounifi.Controller], HandlerT]
@ -128,7 +129,7 @@ class UnifiEntityDescription(EntityDescription, Generic[HandlerT, ApiItemT]):
"""If entity needs to do regular checks on state.""" """If entity needs to do regular checks on state."""
class UnifiEntity(Entity, Generic[HandlerT, ApiItemT]): class UnifiEntity[HandlerT: APIHandler, ApiItemT: ApiItem](Entity):
"""Representation of a UniFi entity.""" """Representation of a UniFi entity."""
entity_description: UnifiEntityDescription[HandlerT, ApiItemT] entity_description: UnifiEntityDescription[HandlerT, ApiItemT]

View File

@ -8,9 +8,9 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from aiounifi.interfaces.api_handlers import ItemEvent from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
from aiounifi.interfaces.wlans import Wlans from aiounifi.interfaces.wlans import Wlans
from aiounifi.models.api import ApiItemT from aiounifi.models.api import ApiItem
from aiounifi.models.wlan import Wlan from aiounifi.models.wlan import Wlan
from homeassistant.components.image import ImageEntity, ImageEntityDescription from homeassistant.components.image import ImageEntity, ImageEntityDescription
@ -21,7 +21,6 @@ from homeassistant.util import dt as dt_util
from . import UnifiConfigEntry from . import UnifiConfigEntry
from .entity import ( from .entity import (
HandlerT,
UnifiEntity, UnifiEntity,
UnifiEntityDescription, UnifiEntityDescription,
async_wlan_available_fn, async_wlan_available_fn,
@ -37,7 +36,7 @@ def async_wlan_qr_code_image_fn(hub: UnifiHub, wlan: Wlan) -> bytes:
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiImageEntityDescription( class UnifiImageEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
ImageEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT] ImageEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT]
): ):
"""Class describing UniFi image entity.""" """Class describing UniFi image entity."""
@ -75,7 +74,9 @@ async def async_setup_entry(
) )
class UnifiImageEntity(UnifiEntity[HandlerT, ApiItemT], ImageEntity): class UnifiImageEntity[HandlerT: APIHandler, ApiItemT: ApiItem](
UnifiEntity[HandlerT, ApiItemT], ImageEntity
):
"""Base representation of a UniFi image.""" """Base representation of a UniFi image."""
entity_description: UnifiImageEntityDescription[HandlerT, ApiItemT] entity_description: UnifiImageEntityDescription[HandlerT, ApiItemT]

View File

@ -13,13 +13,13 @@ from decimal import Decimal
from functools import partial from functools import partial
from typing import TYPE_CHECKING, Literal from typing import TYPE_CHECKING, Literal
from aiounifi.interfaces.api_handlers import ItemEvent from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
from aiounifi.interfaces.clients import Clients from aiounifi.interfaces.clients import Clients
from aiounifi.interfaces.devices import Devices from aiounifi.interfaces.devices import Devices
from aiounifi.interfaces.outlets import Outlets from aiounifi.interfaces.outlets import Outlets
from aiounifi.interfaces.ports import Ports from aiounifi.interfaces.ports import Ports
from aiounifi.interfaces.wlans import Wlans from aiounifi.interfaces.wlans import Wlans
from aiounifi.models.api import ApiItemT from aiounifi.models.api import ApiItem
from aiounifi.models.client import Client from aiounifi.models.client import Client
from aiounifi.models.device import ( from aiounifi.models.device import (
Device, Device,
@ -53,7 +53,6 @@ from homeassistant.util import dt as dt_util, slugify
from . import UnifiConfigEntry from . import UnifiConfigEntry
from .const import DEVICE_STATES from .const import DEVICE_STATES
from .entity import ( from .entity import (
HandlerT,
UnifiEntity, UnifiEntity,
UnifiEntityDescription, UnifiEntityDescription,
async_client_device_info_fn, async_client_device_info_fn,
@ -356,7 +355,7 @@ def make_device_temperatur_sensors() -> tuple[UnifiSensorEntityDescription, ...]
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiSensorEntityDescription( class UnifiSensorEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
SensorEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT] SensorEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT]
): ):
"""Class describing UniFi sensor entity.""" """Class describing UniFi sensor entity."""
@ -652,7 +651,9 @@ async def async_setup_entry(
) )
class UnifiSensorEntity(UnifiEntity[HandlerT, ApiItemT], SensorEntity): class UnifiSensorEntity[HandlerT: APIHandler, ApiItemT: ApiItem](
UnifiEntity[HandlerT, ApiItemT], SensorEntity
):
"""Base representation of a UniFi sensor.""" """Base representation of a UniFi sensor."""
entity_description: UnifiSensorEntityDescription[HandlerT, ApiItemT] entity_description: UnifiSensorEntityDescription[HandlerT, ApiItemT]

View File

@ -15,7 +15,7 @@ from dataclasses import dataclass
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
import aiounifi import aiounifi
from aiounifi.interfaces.api_handlers import ItemEvent from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
from aiounifi.interfaces.clients import Clients from aiounifi.interfaces.clients import Clients
from aiounifi.interfaces.dpi_restriction_groups import DPIRestrictionGroups from aiounifi.interfaces.dpi_restriction_groups import DPIRestrictionGroups
from aiounifi.interfaces.firewall_policies import FirewallPolicies from aiounifi.interfaces.firewall_policies import FirewallPolicies
@ -25,7 +25,7 @@ from aiounifi.interfaces.ports import Ports
from aiounifi.interfaces.traffic_routes import TrafficRoutes from aiounifi.interfaces.traffic_routes import TrafficRoutes
from aiounifi.interfaces.traffic_rules import TrafficRules from aiounifi.interfaces.traffic_rules import TrafficRules
from aiounifi.interfaces.wlans import Wlans from aiounifi.interfaces.wlans import Wlans
from aiounifi.models.api import ApiItemT from aiounifi.models.api import ApiItem
from aiounifi.models.client import Client, ClientBlockRequest from aiounifi.models.client import Client, ClientBlockRequest
from aiounifi.models.device import DeviceSetOutletRelayRequest from aiounifi.models.device import DeviceSetOutletRelayRequest
from aiounifi.models.dpi_restriction_app import DPIRestrictionAppEnableRequest from aiounifi.models.dpi_restriction_app import DPIRestrictionAppEnableRequest
@ -54,8 +54,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import UnifiConfigEntry from . import UnifiConfigEntry
from .const import ATTR_MANUFACTURER, DOMAIN from .const import ATTR_MANUFACTURER, DOMAIN
from .entity import ( from .entity import (
HandlerT, SubscriptionType,
SubscriptionT,
UnifiEntity, UnifiEntity,
UnifiEntityDescription, UnifiEntityDescription,
async_client_device_info_fn, async_client_device_info_fn,
@ -209,7 +208,7 @@ async def async_wlan_control_fn(hub: UnifiHub, obj_id: str, target: bool) -> Non
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiSwitchEntityDescription( class UnifiSwitchEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
SwitchEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT] SwitchEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT]
): ):
"""Class describing UniFi switch entity.""" """Class describing UniFi switch entity."""
@ -218,7 +217,7 @@ class UnifiSwitchEntityDescription(
is_on_fn: Callable[[UnifiHub, ApiItemT], bool] is_on_fn: Callable[[UnifiHub, ApiItemT], bool]
# Optional # Optional
custom_subscribe: Callable[[aiounifi.Controller], SubscriptionT] | None = None custom_subscribe: Callable[[aiounifi.Controller], SubscriptionType] | None = None
"""Callback for additional subscriptions to any UniFi handler.""" """Callback for additional subscriptions to any UniFi handler."""
only_event_for_state_change: bool = False only_event_for_state_change: bool = False
"""Use only UniFi events to trigger state changes.""" """Use only UniFi events to trigger state changes."""
@ -397,7 +396,9 @@ async def async_setup_entry(
) )
class UnifiSwitchEntity(UnifiEntity[HandlerT, ApiItemT], SwitchEntity): class UnifiSwitchEntity[HandlerT: APIHandler, ApiItemT: ApiItem](
UnifiEntity[HandlerT, ApiItemT], SwitchEntity
):
"""Base representation of a UniFi switch.""" """Base representation of a UniFi switch."""
entity_description: UnifiSwitchEntityDescription[HandlerT, ApiItemT] entity_description: UnifiSwitchEntityDescription[HandlerT, ApiItemT]

View File

@ -5,7 +5,7 @@ from __future__ import annotations
from collections.abc import Callable, Coroutine from collections.abc import Callable, Coroutine
from dataclasses import dataclass from dataclasses import dataclass
import logging import logging
from typing import Any, TypeVar from typing import Any
import aiounifi import aiounifi
from aiounifi.interfaces.api_handlers import ItemEvent from aiounifi.interfaces.api_handlers import ItemEvent
@ -31,9 +31,6 @@ from .entity import (
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
_DataT = TypeVar("_DataT", bound=Device)
_HandlerT = TypeVar("_HandlerT", bound=Devices)
async def async_device_control_fn(api: aiounifi.Controller, obj_id: str) -> None: async def async_device_control_fn(api: aiounifi.Controller, obj_id: str) -> None:
"""Control upgrade of device.""" """Control upgrade of device."""
@ -41,7 +38,7 @@ async def async_device_control_fn(api: aiounifi.Controller, obj_id: str) -> None
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiUpdateEntityDescription( class UnifiUpdateEntityDescription[_HandlerT: Devices, _DataT: Device](
UpdateEntityDescription, UnifiEntityDescription[_HandlerT, _DataT] UpdateEntityDescription, UnifiEntityDescription[_HandlerT, _DataT]
): ):
"""Class describing UniFi update entity.""" """Class describing UniFi update entity."""
@ -78,7 +75,9 @@ async def async_setup_entry(
) )
class UnifiDeviceUpdateEntity(UnifiEntity[_HandlerT, _DataT], UpdateEntity): class UnifiDeviceUpdateEntity[_HandlerT: Devices, _DataT: Device](
UnifiEntity[_HandlerT, _DataT], UpdateEntity
):
"""Representation of a UniFi device update entity.""" """Representation of a UniFi device update entity."""
entity_description: UnifiUpdateEntityDescription[_HandlerT, _DataT] entity_description: UnifiUpdateEntityDescription[_HandlerT, _DataT]