Use PEP 695 for class annotations (2) (#117776)

This commit is contained in:
Marc Mueller 2024-05-20 10:43:59 +02:00 committed by GitHub
parent b93312b62c
commit eedce95bc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 49 additions and 76 deletions

View File

@ -6,7 +6,7 @@ from collections import defaultdict
from collections.abc import Mapping from collections.abc import Mapping
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging import logging
from typing import TypeVar, cast from typing import cast
from aiohttp.client_exceptions import ClientError from aiohttp.client_exceptions import ClientError
from pykoplenti import ( from pykoplenti import (
@ -28,7 +28,6 @@ from .const import DOMAIN
from .helper import get_hostname_id from .helper import get_hostname_id
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
_DataT = TypeVar("_DataT")
class Plenticore: class Plenticore:
@ -160,7 +159,7 @@ class DataUpdateCoordinatorMixin:
return True return True
class PlenticoreUpdateCoordinator(DataUpdateCoordinator[_DataT]): class PlenticoreUpdateCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
"""Base implementation of DataUpdateCoordinator for Plenticore data.""" """Base implementation of DataUpdateCoordinator for Plenticore data."""
def __init__( def __init__(
@ -238,7 +237,7 @@ class SettingDataUpdateCoordinator(
return await client.get_setting_values(self._fetch) return await client.get_setting_values(self._fetch)
class PlenticoreSelectUpdateCoordinator(DataUpdateCoordinator[_DataT]): class PlenticoreSelectUpdateCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
"""Base implementation of DataUpdateCoordinator for Plenticore data.""" """Base implementation of DataUpdateCoordinator for Plenticore data."""
def __init__( def __init__(

View File

@ -6,7 +6,6 @@ from collections.abc import Awaitable, Callable
from datetime import timedelta from datetime import timedelta
import logging import logging
import time import time
from typing import TypeVar
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
@ -14,7 +13,6 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import NEVER_TIME, POLLING_FALLBACK_SECONDS from .const import NEVER_TIME, POLLING_FALLBACK_SECONDS
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
_DataT = TypeVar("_DataT")
class LookinPushCoordinator: class LookinPushCoordinator:
@ -42,7 +40,7 @@ class LookinPushCoordinator:
return is_active return is_active
class LookinDataUpdateCoordinator(DataUpdateCoordinator[_DataT]): class LookinDataUpdateCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
"""DataUpdateCoordinator to gather data for a specific lookin devices.""" """DataUpdateCoordinator to gather data for a specific lookin devices."""
def __init__( def __init__(

View File

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, TypeVar from typing import Any
from meteofrance_api.helpers import ( from meteofrance_api.helpers import (
get_warning_text_status_from_indice_color, get_warning_text_status_from_indice_color,
@ -49,8 +49,6 @@ from .const import (
MODEL, MODEL,
) )
_DataT = TypeVar("_DataT", bound=Rain | Forecast | CurrentPhenomenons)
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class MeteoFranceSensorEntityDescription(SensorEntityDescription): class MeteoFranceSensorEntityDescription(SensorEntityDescription):
@ -226,7 +224,9 @@ async def async_setup_entry(
async_add_entities(entities, False) async_add_entities(entities, False)
class MeteoFranceSensor(CoordinatorEntity[DataUpdateCoordinator[_DataT]], SensorEntity): class MeteoFranceSensor[_DataT: Rain | Forecast | CurrentPhenomenons](
CoordinatorEntity[DataUpdateCoordinator[_DataT]], SensorEntity
):
"""Representation of a Meteo-France sensor.""" """Representation of a Meteo-France sensor."""
entity_description: MeteoFranceSensorEntityDescription entity_description: MeteoFranceSensorEntityDescription

View File

@ -7,7 +7,7 @@ from collections import defaultdict
from collections.abc import Callable, Iterable from collections.abc import Callable, Iterable
from datetime import date, timedelta from datetime import date, timedelta
from functools import cached_property from functools import cached_property
from typing import Any, Generic, TypeVar from typing import Any
from nibe.coil import Coil, CoilData from nibe.coil import Coil, CoilData
from nibe.connection import Connection from nibe.connection import Connection
@ -26,13 +26,8 @@ from homeassistant.helpers.update_coordinator import (
from .const import DOMAIN, LOGGER from .const import DOMAIN, LOGGER
_DataTypeT = TypeVar("_DataTypeT")
_ContextTypeT = TypeVar("_ContextTypeT")
class ContextCoordinator[_DataTypeT, _ContextTypeT](DataUpdateCoordinator[_DataTypeT]):
class ContextCoordinator(
Generic[_DataTypeT, _ContextTypeT], DataUpdateCoordinator[_DataTypeT]
):
"""Update coordinator with context adjustments.""" """Update coordinator with context adjustments."""
@cached_property @cached_property

View File

@ -8,7 +8,6 @@ from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
from http import HTTPStatus from http import HTTPStatus
import logging import logging
from typing import Generic, TypeVar
from aiohttp import web from aiohttp import web
from pynuki import NukiBridge, NukiLock, NukiOpener from pynuki import NukiBridge, NukiLock, NukiOpener
@ -43,8 +42,6 @@ from homeassistant.helpers.update_coordinator import (
from .const import CONF_ENCRYPT_TOKEN, DEFAULT_TIMEOUT, DOMAIN, ERROR_STATES from .const import CONF_ENCRYPT_TOKEN, DEFAULT_TIMEOUT, DOMAIN, ERROR_STATES
from .helpers import NukiWebhookException, parse_id from .helpers import NukiWebhookException, parse_id
_NukiDeviceT = TypeVar("_NukiDeviceT", bound=NukiDevice)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
PLATFORMS = [Platform.BINARY_SENSOR, Platform.LOCK, Platform.SENSOR] PLATFORMS = [Platform.BINARY_SENSOR, Platform.LOCK, Platform.SENSOR]
@ -360,7 +357,7 @@ class NukiCoordinator(DataUpdateCoordinator[None]): # pylint: disable=hass-enfo
return events return events
class NukiEntity(CoordinatorEntity[NukiCoordinator], Generic[_NukiDeviceT]): class NukiEntity[_NukiDeviceT: NukiDevice](CoordinatorEntity[NukiCoordinator]):
"""An entity using CoordinatorEntity. """An entity using CoordinatorEntity.
The CoordinatorEntity class provides: The CoordinatorEntity class provides:

View File

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
from abc import abstractmethod from abc import abstractmethod
from typing import Any, TypeVar from typing import Any
from pynuki import NukiLock, NukiOpener from pynuki import NukiLock, NukiOpener
from pynuki.constants import MODE_OPENER_CONTINUOUS from pynuki.constants import MODE_OPENER_CONTINUOUS
@ -28,8 +28,6 @@ from .const import (
) )
from .helpers import CannotConnect from .helpers import CannotConnect
_NukiDeviceT = TypeVar("_NukiDeviceT", bound=NukiDevice)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
@ -64,7 +62,7 @@ async def async_setup_entry(
) )
class NukiDeviceEntity(NukiEntity[_NukiDeviceT], LockEntity): class NukiDeviceEntity[_NukiDeviceT: NukiDevice](NukiEntity[_NukiDeviceT], LockEntity):
"""Representation of a Nuki device.""" """Representation of a Nuki device."""
_attr_has_entity_name = True _attr_has_entity_name = True

View File

@ -1,6 +1,6 @@
"""Support for the OSO Energy devices and services.""" """Support for the OSO Energy devices and services."""
from typing import Any, Generic, TypeVar from typing import Any
from aiohttp.web_exceptions import HTTPException from aiohttp.web_exceptions import HTTPException
from apyosoenergyapi import OSOEnergy from apyosoenergyapi import OSOEnergy
@ -21,13 +21,6 @@ from homeassistant.helpers.entity import Entity
from .const import DOMAIN from .const import DOMAIN
_OSOEnergyT = TypeVar(
"_OSOEnergyT",
OSOEnergyBinarySensorData,
OSOEnergySensorData,
OSOEnergyWaterHeaterData,
)
MANUFACTURER = "OSO Energy" MANUFACTURER = "OSO Energy"
PLATFORMS = [ PLATFORMS = [
Platform.SENSOR, Platform.SENSOR,
@ -77,7 +70,13 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return unload_ok return unload_ok
class OSOEnergyEntity(Entity, Generic[_OSOEnergyT]): class OSOEnergyEntity[
_OSOEnergyT: (
OSOEnergyBinarySensorData,
OSOEnergySensorData,
OSOEnergyWaterHeaterData,
)
](Entity):
"""Initiate OSO Energy Base Class.""" """Initiate OSO Energy Base Class."""
_attr_has_entity_name = True _attr_has_entity_name = True

View File

@ -1,6 +1,6 @@
"""Managers for each table.""" """Managers for each table."""
from typing import TYPE_CHECKING, Any, Generic, TypeVar from typing import TYPE_CHECKING, Any
from lru import LRU from lru import LRU
@ -9,10 +9,8 @@ from homeassistant.util.event_type import EventType
if TYPE_CHECKING: if TYPE_CHECKING:
from ..core import Recorder from ..core import Recorder
_DataT = TypeVar("_DataT")
class BaseTableManager[_DataT]:
class BaseTableManager(Generic[_DataT]):
"""Base class for table managers.""" """Base class for table managers."""
_id_map: "LRU[EventType[Any] | str, int]" _id_map: "LRU[EventType[Any] | str, int]"
@ -54,7 +52,7 @@ class BaseTableManager(Generic[_DataT]):
self._pending.clear() self._pending.clear()
class BaseLRUTableManager(BaseTableManager[_DataT]): class BaseLRUTableManager[_DataT](BaseTableManager[_DataT]):
"""Base class for LRU table managers.""" """Base class for LRU table managers."""
def __init__(self, recorder: "Recorder", lru_size: int) -> None: def __init__(self, recorder: "Recorder", lru_size: int) -> None:

View File

@ -4,7 +4,6 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import TypeVar
from reolink_aio.api import DUAL_LENS_MODELS, Host from reolink_aio.api import DUAL_LENS_MODELS, Host
@ -18,8 +17,6 @@ from homeassistant.helpers.update_coordinator import (
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
_T = TypeVar("_T")
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class ReolinkChannelEntityDescription(EntityDescription): class ReolinkChannelEntityDescription(EntityDescription):
@ -37,7 +34,9 @@ class ReolinkHostEntityDescription(EntityDescription):
supported: Callable[[Host], bool] = lambda api: True supported: Callable[[Host], bool] = lambda api: True
class ReolinkBaseCoordinatorEntity(CoordinatorEntity[DataUpdateCoordinator[_T]]): class ReolinkBaseCoordinatorEntity[_DataT](
CoordinatorEntity[DataUpdateCoordinator[_DataT]]
):
"""Parent class for Reolink entities.""" """Parent class for Reolink entities."""
_attr_has_entity_name = True _attr_has_entity_name = True
@ -45,7 +44,7 @@ class ReolinkBaseCoordinatorEntity(CoordinatorEntity[DataUpdateCoordinator[_T]])
def __init__( def __init__(
self, self,
reolink_data: ReolinkData, reolink_data: ReolinkData,
coordinator: DataUpdateCoordinator[_T], coordinator: DataUpdateCoordinator[_DataT],
) -> None: ) -> None:
"""Initialize ReolinkBaseCoordinatorEntity.""" """Initialize ReolinkBaseCoordinatorEntity."""
super().__init__(coordinator) super().__init__(coordinator)

View File

@ -8,7 +8,7 @@ from asyncio.exceptions import TimeoutError as AsyncioTimeoutError
from collections.abc import Callable, Iterable, Mapping from collections.abc import Callable, Iterable, Mapping
import contextlib import contextlib
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any, Generic, TypeVar, cast from typing import Any, cast
from samsungctl import Remote from samsungctl import Remote
from samsungctl.exceptions import AccessDenied, ConnectionClosed, UnhandledResponse from samsungctl.exceptions import AccessDenied, ConnectionClosed, UnhandledResponse
@ -85,9 +85,6 @@ ENCRYPTED_MODEL_USES_POWER = {"JU6400", "JU641D"}
REST_EXCEPTIONS = (HttpApiError, AsyncioTimeoutError, ResponseError) REST_EXCEPTIONS = (HttpApiError, AsyncioTimeoutError, ResponseError)
_RemoteT = TypeVar("_RemoteT", SamsungTVWSAsyncRemote, SamsungTVEncryptedWSAsyncRemote)
_CommandT = TypeVar("_CommandT", SamsungTVCommand, SamsungTVEncryptedCommand)
def mac_from_device_info(info: dict[str, Any]) -> str | None: def mac_from_device_info(info: dict[str, Any]) -> str | None:
"""Extract the mac address from the device info.""" """Extract the mac address from the device info."""
@ -393,7 +390,10 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
LOGGER.debug("Could not establish connection") LOGGER.debug("Could not establish connection")
class SamsungTVWSBaseBridge(SamsungTVBridge, Generic[_RemoteT, _CommandT]): class SamsungTVWSBaseBridge[
_RemoteT: (SamsungTVWSAsyncRemote, SamsungTVEncryptedWSAsyncRemote),
_CommandT: (SamsungTVCommand, SamsungTVEncryptedCommand),
](SamsungTVBridge):
"""The Bridge for WebSocket TVs (v1/v2).""" """The Bridge for WebSocket TVs (v1/v2)."""
def __init__( def __init__(

View File

@ -4,7 +4,6 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Generic, TypeVar
from sfrbox_api.models import DslInfo, FtthInfo, SystemInfo, WanInfo from sfrbox_api.models import DslInfo, FtthInfo, SystemInfo, WanInfo
@ -24,11 +23,9 @@ from .const import DOMAIN
from .coordinator import SFRDataUpdateCoordinator from .coordinator import SFRDataUpdateCoordinator
from .models import DomainData from .models import DomainData
_T = TypeVar("_T")
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class SFRBoxBinarySensorEntityDescription(BinarySensorEntityDescription, Generic[_T]): class SFRBoxBinarySensorEntityDescription[_T](BinarySensorEntityDescription):
"""Description for SFR Box binary sensors.""" """Description for SFR Box binary sensors."""
value_fn: Callable[[_T], bool | None] value_fn: Callable[[_T], bool | None]
@ -87,7 +84,7 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
class SFRBoxBinarySensor( class SFRBoxBinarySensor[_T](
CoordinatorEntity[SFRDataUpdateCoordinator[_T]], BinarySensorEntity CoordinatorEntity[SFRDataUpdateCoordinator[_T]], BinarySensorEntity
): ):
"""SFR Box sensor.""" """SFR Box sensor."""

View File

@ -3,7 +3,7 @@
from collections.abc import Callable, Coroutine from collections.abc import Callable, Coroutine
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import Any, TypeVar from typing import Any
from sfrbox_api.bridge import SFRBox from sfrbox_api.bridge import SFRBox
from sfrbox_api.exceptions import SFRBoxError from sfrbox_api.exceptions import SFRBoxError
@ -14,10 +14,8 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
_SCAN_INTERVAL = timedelta(minutes=1) _SCAN_INTERVAL = timedelta(minutes=1)
_T = TypeVar("_T")
class SFRDataUpdateCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
class SFRDataUpdateCoordinator(DataUpdateCoordinator[_T]):
"""Coordinator to manage data updates.""" """Coordinator to manage data updates."""
def __init__( def __init__(
@ -25,14 +23,14 @@ class SFRDataUpdateCoordinator(DataUpdateCoordinator[_T]):
hass: HomeAssistant, hass: HomeAssistant,
box: SFRBox, box: SFRBox,
name: str, name: str,
method: Callable[[SFRBox], Coroutine[Any, Any, _T]], method: Callable[[SFRBox], Coroutine[Any, Any, _DataT]],
) -> None: ) -> None:
"""Initialize coordinator.""" """Initialize coordinator."""
self.box = box self.box = box
self._method = method self._method = method
super().__init__(hass, _LOGGER, name=name, update_interval=_SCAN_INTERVAL) super().__init__(hass, _LOGGER, name=name, update_interval=_SCAN_INTERVAL)
async def _async_update_data(self) -> _T: async def _async_update_data(self) -> _DataT:
"""Update data.""" """Update data."""
try: try:
return await self._method(self.box) return await self._method(self.box)

View File

@ -2,7 +2,6 @@
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Generic, TypeVar
from sfrbox_api.models import DslInfo, SystemInfo, WanInfo from sfrbox_api.models import DslInfo, SystemInfo, WanInfo
@ -30,11 +29,9 @@ from .const import DOMAIN
from .coordinator import SFRDataUpdateCoordinator from .coordinator import SFRDataUpdateCoordinator
from .models import DomainData from .models import DomainData
_T = TypeVar("_T")
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class SFRBoxSensorEntityDescription(SensorEntityDescription, Generic[_T]): class SFRBoxSensorEntityDescription[_T](SensorEntityDescription):
"""Description for SFR Box sensors.""" """Description for SFR Box sensors."""
value_fn: Callable[[_T], StateType] value_fn: Callable[[_T], StateType]
@ -229,7 +226,7 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
class SFRBoxSensor(CoordinatorEntity[SFRDataUpdateCoordinator[_T]], SensorEntity): class SFRBoxSensor[_T](CoordinatorEntity[SFRDataUpdateCoordinator[_T]], SensorEntity):
"""SFR Box sensor.""" """SFR Box sensor."""
entity_description: SFRBoxSensorEntityDescription[_T] entity_description: SFRBoxSensorEntityDescription[_T]

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
from functools import partial from functools import partial
from typing import TYPE_CHECKING, Any, Final, Generic, TypeVar from typing import TYPE_CHECKING, Any, Final
from aioshelly.const import RPC_GENERATIONS from aioshelly.const import RPC_GENERATIONS
@ -26,13 +26,11 @@ from .const import LOGGER, SHELLY_GAS_MODELS
from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
from .utils import get_device_entry_gen from .utils import get_device_entry_gen
_ShellyCoordinatorT = TypeVar(
"_ShellyCoordinatorT", bound=ShellyBlockCoordinator | ShellyRpcCoordinator
)
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class ShellyButtonDescription(ButtonEntityDescription, Generic[_ShellyCoordinatorT]): class ShellyButtonDescription[
_ShellyCoordinatorT: ShellyBlockCoordinator | ShellyRpcCoordinator
](ButtonEntityDescription):
"""Class to describe a Button entity.""" """Class to describe a Button entity."""
press_action: Callable[[_ShellyCoordinatorT], Coroutine[Any, Any, None]] press_action: Callable[[_ShellyCoordinatorT], Coroutine[Any, Any, None]]

View File

@ -6,7 +6,7 @@ import asyncio
from collections.abc import Callable, Coroutine from collections.abc import Callable, Coroutine
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
from typing import Any, Generic, TypeVar, cast from typing import Any, cast
from aioshelly.ble import async_ensure_ble_enabled, async_stop_scanner from aioshelly.ble import async_ensure_ble_enabled, async_stop_scanner
from aioshelly.block_device import BlockDevice, BlockUpdateType from aioshelly.block_device import BlockDevice, BlockUpdateType
@ -70,8 +70,6 @@ from .utils import (
update_device_fw_info, update_device_fw_info,
) )
_DeviceT = TypeVar("_DeviceT", bound="BlockDevice|RpcDevice")
@dataclass @dataclass
class ShellyEntryData: class ShellyEntryData:
@ -86,7 +84,9 @@ class ShellyEntryData:
type ShellyConfigEntry = ConfigEntry[ShellyEntryData] type ShellyConfigEntry = ConfigEntry[ShellyEntryData]
class ShellyCoordinatorBase(DataUpdateCoordinator[None], Generic[_DeviceT]): class ShellyCoordinatorBase[_DeviceT: BlockDevice | RpcDevice](
DataUpdateCoordinator[None]
):
"""Coordinator for a Shelly device.""" """Coordinator for a Shelly device."""
def __init__( def __init__(