diff --git a/homeassistant/components/deconz/binary_sensor.py b/homeassistant/components/deconz/binary_sensor.py index 02f6ada8fc8aaa..0b3461b7a12d7c 100644 --- a/homeassistant/components/deconz/binary_sensor.py +++ b/homeassistant/components/deconz/binary_sensor.py @@ -4,7 +4,6 @@ from collections.abc import Callable from dataclasses import dataclass -from typing import Generic, TypeVar from pydeconz.interfaces.sensors import SensorResources from pydeconz.models.event import EventType @@ -48,29 +47,28 @@ "water", ) -T = TypeVar( - "T", - Alarm, - CarbonMonoxide, - Fire, - GenericFlag, - OpenClose, - Presence, - Vibration, - Water, - PydeconzSensorBase, -) - @dataclass(frozen=True, kw_only=True) -class DeconzBinarySensorDescription(Generic[T], BinarySensorEntityDescription): +class DeconzBinarySensorDescription[ + _T: ( + Alarm, + CarbonMonoxide, + Fire, + GenericFlag, + OpenClose, + Presence, + Vibration, + Water, + PydeconzSensorBase, + ) +](BinarySensorEntityDescription): """Class describing deCONZ binary sensor entities.""" - instance_check: type[T] | None = None + instance_check: type[_T] | None = None name_suffix: str = "" old_unique_id_suffix: str = "" update_key: str - value_fn: Callable[[T], bool | None] + value_fn: Callable[[_T], bool | None] ENTITY_DESCRIPTIONS: tuple[DeconzBinarySensorDescription, ...] = ( diff --git a/homeassistant/components/traccar_server/binary_sensor.py b/homeassistant/components/traccar_server/binary_sensor.py index 6ee5757dcea7c6..58c46502b53497 100644 --- a/homeassistant/components/traccar_server/binary_sensor.py +++ b/homeassistant/components/traccar_server/binary_sensor.py @@ -4,7 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass -from typing import Generic, Literal, TypeVar, cast +from typing import Any, Literal from pytraccar import DeviceModel @@ -22,13 +22,9 @@ from .coordinator import TraccarServerCoordinator from .entity import TraccarServerEntity -_T = TypeVar("_T") - @dataclass(frozen=True, kw_only=True) -class TraccarServerBinarySensorEntityDescription( - Generic[_T], BinarySensorEntityDescription -): +class TraccarServerBinarySensorEntityDescription[_T](BinarySensorEntityDescription): """Describe Traccar Server sensor entity.""" data_key: Literal["position", "device", "geofence", "attributes"] @@ -37,7 +33,9 @@ class TraccarServerBinarySensorEntityDescription( value_fn: Callable[[_T], bool | None] -TRACCAR_SERVER_BINARY_SENSOR_ENTITY_DESCRIPTIONS = ( +TRACCAR_SERVER_BINARY_SENSOR_ENTITY_DESCRIPTIONS: tuple[ + TraccarServerBinarySensorEntityDescription[Any], ... +] = ( TraccarServerBinarySensorEntityDescription[DeviceModel]( key="attributes.motion", data_key="position", @@ -65,18 +63,18 @@ async def async_setup_entry( TraccarServerBinarySensor( coordinator=coordinator, device=entry["device"], - description=cast(TraccarServerBinarySensorEntityDescription, description), + description=description, ) for entry in coordinator.data.values() for description in TRACCAR_SERVER_BINARY_SENSOR_ENTITY_DESCRIPTIONS ) -class TraccarServerBinarySensor(TraccarServerEntity, BinarySensorEntity): +class TraccarServerBinarySensor[_T](TraccarServerEntity, BinarySensorEntity): """Represent a traccar server binary sensor.""" _attr_has_entity_name = True - entity_description: TraccarServerBinarySensorEntityDescription + entity_description: TraccarServerBinarySensorEntityDescription[_T] def __init__( self, diff --git a/homeassistant/components/traccar_server/sensor.py b/homeassistant/components/traccar_server/sensor.py index 7f46399eb3ff81..9aaf12894244a2 100644 --- a/homeassistant/components/traccar_server/sensor.py +++ b/homeassistant/components/traccar_server/sensor.py @@ -4,7 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass -from typing import Generic, Literal, TypeVar, cast +from typing import Any, Literal from pytraccar import DeviceModel, GeofenceModel, PositionModel @@ -24,11 +24,9 @@ from .coordinator import TraccarServerCoordinator from .entity import TraccarServerEntity -_T = TypeVar("_T") - @dataclass(frozen=True, kw_only=True) -class TraccarServerSensorEntityDescription(Generic[_T], SensorEntityDescription): +class TraccarServerSensorEntityDescription[_T](SensorEntityDescription): """Describe Traccar Server sensor entity.""" data_key: Literal["position", "device", "geofence", "attributes"] @@ -37,7 +35,9 @@ class TraccarServerSensorEntityDescription(Generic[_T], SensorEntityDescription) value_fn: Callable[[_T], StateType] -TRACCAR_SERVER_SENSOR_ENTITY_DESCRIPTIONS = ( +TRACCAR_SERVER_SENSOR_ENTITY_DESCRIPTIONS: tuple[ + TraccarServerSensorEntityDescription[Any], ... +] = ( TraccarServerSensorEntityDescription[PositionModel]( key="attributes.batteryLevel", data_key="position", @@ -91,18 +91,18 @@ async def async_setup_entry( TraccarServerSensor( coordinator=coordinator, device=entry["device"], - description=cast(TraccarServerSensorEntityDescription, description), + description=description, ) for entry in coordinator.data.values() for description in TRACCAR_SERVER_SENSOR_ENTITY_DESCRIPTIONS ) -class TraccarServerSensor(TraccarServerEntity, SensorEntity): +class TraccarServerSensor[_T](TraccarServerEntity, SensorEntity): """Represent a tracked device.""" _attr_has_entity_name = True - entity_description: TraccarServerSensorEntityDescription + entity_description: TraccarServerSensorEntityDescription[_T] def __init__( self, diff --git a/homeassistant/core.py b/homeassistant/core.py index 640e34cdedd940..64cab7ee5b0b12 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -857,7 +857,7 @@ def async_create_background_task[_R]( return task @callback - def async_add_executor_job[_T, *_Ts]( + def async_add_executor_job[*_Ts, _T]( self, target: Callable[[*_Ts], _T], *args: *_Ts ) -> asyncio.Future[_T]: """Add an executor job from within the event loop.""" @@ -871,7 +871,7 @@ def async_add_executor_job[_T, *_Ts]( return task @callback - def async_add_import_executor_job[_T, *_Ts]( + def async_add_import_executor_job[*_Ts, _T]( self, target: Callable[[*_Ts], _T], *args: *_Ts ) -> asyncio.Future[_T]: """Add an import executor job from within the event loop. diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index a144e95988af03..1e9d98264d8835 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -18,7 +18,7 @@ from socket import ( # type: ignore[attr-defined] # private, not in typeshed _GLOBAL_DEFAULT_TIMEOUT, ) -from typing import Any, TypeVar, cast, overload +from typing import Any, cast, overload from urllib.parse import urlparse from uuid import UUID @@ -140,9 +140,6 @@ class UrlProtocolSchema(StrEnum): sun_event = vol.All(vol.Lower, vol.Any(SUN_EVENT_SUNSET, SUN_EVENT_SUNRISE)) port = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)) -# typing typevar -_T = TypeVar("_T") - def path(value: Any) -> str: """Validate it's a safe path.""" @@ -288,14 +285,14 @@ def ensure_list(value: None) -> list[Any]: ... @overload -def ensure_list(value: list[_T]) -> list[_T]: ... +def ensure_list[_T](value: list[_T]) -> list[_T]: ... @overload -def ensure_list(value: list[_T] | _T) -> list[_T]: ... +def ensure_list[_T](value: list[_T] | _T) -> list[_T]: ... -def ensure_list(value: _T | None) -> list[_T] | list[Any]: +def ensure_list[_T](value: _T | None) -> list[_T] | list[Any]: """Wrap value in list if it is not one.""" if value is None: return [] @@ -540,7 +537,7 @@ def time_period_seconds(value: float | str) -> timedelta: time_period = vol.Any(time_period_str, time_period_seconds, timedelta, time_period_dict) -def match_all(value: _T) -> _T: +def match_all[_T](value: _T) -> _T: """Validate that matches all values.""" return value @@ -556,7 +553,7 @@ def positive_timedelta(value: timedelta) -> timedelta: positive_time_period = vol.All(time_period, positive_timedelta) -def remove_falsy(value: list[_T]) -> list[_T]: +def remove_falsy[_T](value: list[_T]) -> list[_T]: """Remove falsy values from a list.""" return [v for v in value if v] diff --git a/tests/typing.py b/tests/typing.py index dc0c35d5dba171..3938383d37f4e9 100644 --- a/tests/typing.py +++ b/tests/typing.py @@ -30,6 +30,6 @@ class MockHAClientWebSocket(ClientWebSocketResponse): """MagicMock for `homeassistant.components.mqtt.MQTT`.""" MqttMockHAClientGenerator = Callable[..., Coroutine[Any, Any, MqttMockHAClient]] """MagicMock generator for `homeassistant.components.mqtt.MQTT`.""" -type RecorderInstanceGenerator = Callable[..., Coroutine[Any, Any, "Recorder"]] +type RecorderInstanceGenerator = Callable[..., Coroutine[Any, Any, Recorder]] """Instance generator for `homeassistant.components.recorder.Recorder`.""" WebSocketGenerator = Callable[..., Coroutine[Any, Any, MockHAClientWebSocket]]