Enable strict typing for here_travel_time (#83814)

* Enable strict typing for here_travel_time

* Use dict[str, Any] instead of Any

* Use kwargs ctor

* Specify dicts
This commit is contained in:
Kevin Stillhammer 2022-12-18 09:34:47 +01:00 committed by GitHub
parent 119664b55e
commit 487d84c8f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 51 deletions

View File

@ -130,6 +130,7 @@ homeassistant.components.group.*
homeassistant.components.guardian.* homeassistant.components.guardian.*
homeassistant.components.hardkernel.* homeassistant.components.hardkernel.*
homeassistant.components.hardware.* homeassistant.components.hardware.*
homeassistant.components.here_travel_time.*
homeassistant.components.history.* homeassistant.components.history.*
homeassistant.components.homeassistant.triggers.event homeassistant.components.homeassistant.triggers.event
homeassistant.components.homeassistant_alerts.* homeassistant.components.homeassistant_alerts.*

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from datetime import datetime, time, timedelta from datetime import datetime, time, timedelta
import logging import logging
from typing import Any
import here_routing import here_routing
from here_routing import HERERoutingApi, Return, RoutingMode, Spans, TransportMode from here_routing import HERERoutingApi, Return, RoutingMode, Spans, TransportMode
@ -15,7 +16,7 @@ from here_transit import (
) )
import voluptuous as vol import voluptuous as vol
from homeassistant.const import ATTR_ATTRIBUTION, UnitOfLength from homeassistant.const import UnitOfLength
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.location import find_coordinates from homeassistant.helpers.location import find_coordinates
@ -23,18 +24,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
from homeassistant.util import dt from homeassistant.util import dt
from homeassistant.util.unit_conversion import DistanceConverter from homeassistant.util.unit_conversion import DistanceConverter
from .const import ( from .const import DEFAULT_SCAN_INTERVAL, DOMAIN, ROUTE_MODE_FASTEST
ATTR_DESTINATION,
ATTR_DESTINATION_NAME,
ATTR_DISTANCE,
ATTR_DURATION,
ATTR_DURATION_IN_TRAFFIC,
ATTR_ORIGIN,
ATTR_ORIGIN_NAME,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
ROUTE_MODE_FASTEST,
)
from .model import HERETravelTimeConfig, HERETravelTimeData from .model import HERETravelTimeConfig, HERETravelTimeData
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -96,10 +86,10 @@ class HERERoutingDataUpdateCoordinator(DataUpdateCoordinator):
return self._parse_routing_response(response) return self._parse_routing_response(response)
def _parse_routing_response(self, response) -> HERETravelTimeData: def _parse_routing_response(self, response: dict[str, Any]) -> HERETravelTimeData:
"""Parse the routing response dict to a HERETravelTimeData.""" """Parse the routing response dict to a HERETravelTimeData."""
section: dict = response["routes"][0]["sections"][0] section: dict[str, Any] = response["routes"][0]["sections"][0]
summary: dict = section["summary"] summary: dict[str, int] = section["summary"]
mapped_origin_lat: float = section["departure"]["place"]["location"]["lat"] mapped_origin_lat: float = section["departure"]["place"]["location"]["lat"]
mapped_origin_lon: float = section["departure"]["place"]["location"]["lng"] mapped_origin_lon: float = section["departure"]["place"]["location"]["lng"]
mapped_destination_lat: float = section["arrival"]["place"]["location"]["lat"] mapped_destination_lat: float = section["arrival"]["place"]["location"]["lat"]
@ -114,16 +104,14 @@ class HERERoutingDataUpdateCoordinator(DataUpdateCoordinator):
if (names := section["spans"][-1].get("names")) is not None: if (names := section["spans"][-1].get("names")) is not None:
destination_name = names[0]["value"] destination_name = names[0]["value"]
return HERETravelTimeData( return HERETravelTimeData(
{ attribution=None,
ATTR_ATTRIBUTION: None, duration=round(summary["baseDuration"] / 60),
ATTR_DURATION: round(summary["baseDuration"] / 60), # type: ignore[misc] duration_in_traffic=round(summary["duration"] / 60),
ATTR_DURATION_IN_TRAFFIC: round(summary["duration"] / 60), distance=distance,
ATTR_DISTANCE: distance, origin=f"{mapped_origin_lat},{mapped_origin_lon}",
ATTR_ORIGIN: f"{mapped_origin_lat},{mapped_origin_lon}", destination=f"{mapped_destination_lat},{mapped_destination_lon}",
ATTR_DESTINATION: f"{mapped_destination_lat},{mapped_destination_lon}", origin_name=origin_name,
ATTR_ORIGIN_NAME: origin_name, destination_name=destination_name,
ATTR_DESTINATION_NAME: destination_name,
}
) )
@ -182,9 +170,9 @@ class HERETransitDataUpdateCoordinator(DataUpdateCoordinator):
except (HERETransitConnectionError, HERETransitNoRouteFoundError) as error: except (HERETransitConnectionError, HERETransitNoRouteFoundError) as error:
raise UpdateFailed from error raise UpdateFailed from error
def _parse_transit_response(self, response) -> HERETravelTimeData: def _parse_transit_response(self, response: dict[str, Any]) -> HERETravelTimeData:
"""Parse the transit response dict to a HERETravelTimeData.""" """Parse the transit response dict to a HERETravelTimeData."""
sections: dict = response["routes"][0]["sections"] sections: list[dict[str, Any]] = response["routes"][0]["sections"]
attribution: str | None = build_hass_attribution(sections) attribution: str | None = build_hass_attribution(sections)
mapped_origin_lat: float = sections[0]["departure"]["place"]["location"]["lat"] mapped_origin_lat: float = sections[0]["departure"]["place"]["location"]["lat"]
mapped_origin_lon: float = sections[0]["departure"]["place"]["location"]["lng"] mapped_origin_lon: float = sections[0]["departure"]["place"]["location"]["lng"]
@ -203,16 +191,14 @@ class HERETransitDataUpdateCoordinator(DataUpdateCoordinator):
section["travelSummary"]["duration"] for section in sections section["travelSummary"]["duration"] for section in sections
) )
return HERETravelTimeData( return HERETravelTimeData(
{ attribution=attribution,
ATTR_ATTRIBUTION: attribution, duration=round(duration / 60),
ATTR_DURATION: round(duration / 60), # type: ignore[misc] duration_in_traffic=round(duration / 60),
ATTR_DURATION_IN_TRAFFIC: round(duration / 60), distance=distance,
ATTR_DISTANCE: distance, origin=f"{mapped_origin_lat},{mapped_origin_lon}",
ATTR_ORIGIN: f"{mapped_origin_lat},{mapped_origin_lon}", destination=f"{mapped_destination_lat},{mapped_destination_lon}",
ATTR_DESTINATION: f"{mapped_destination_lat},{mapped_destination_lon}", origin_name=sections[0]["departure"]["place"].get("name"),
ATTR_ORIGIN_NAME: sections[0]["departure"]["place"].get("name"), destination_name=sections[-1]["arrival"]["place"].get("name"),
ATTR_DESTINATION_NAME: sections[-1]["arrival"]["place"].get("name"),
}
) )
@ -266,7 +252,7 @@ def prepare_parameters(
return (origin, destination, arrival, departure) return (origin, destination, arrival, departure)
def build_hass_attribution(sections: dict) -> str | None: def build_hass_attribution(sections: list[dict[str, Any]]) -> str | None:
"""Build a hass frontend ready string out of the attributions.""" """Build a hass frontend ready string out of the attributions."""
relevant_attributions = [] relevant_attributions = []
for section in sections: for section in sections:

View File

@ -9,14 +9,14 @@ from typing import TypedDict
class HERETravelTimeData(TypedDict): class HERETravelTimeData(TypedDict):
"""Routing information.""" """Routing information."""
ATTR_ATTRIBUTION: str | None attribution: str | None
ATTR_DURATION: float duration: float
ATTR_DURATION_IN_TRAFFIC: float duration_in_traffic: float
ATTR_DISTANCE: float distance: float
ATTR_ORIGIN: str origin: str
ATTR_DESTINATION: str destination: str
ATTR_ORIGIN_NAME: str origin_name: str | None
ATTR_DESTINATION_NAME: str destination_name: str | None
@dataclass @dataclass

View File

@ -40,7 +40,10 @@ from .const import (
ICON_CAR, ICON_CAR,
ICONS, ICONS,
) )
from .coordinator import HERERoutingDataUpdateCoordinator from .coordinator import (
HERERoutingDataUpdateCoordinator,
HERETransitDataUpdateCoordinator,
)
SCAN_INTERVAL = timedelta(minutes=5) SCAN_INTERVAL = timedelta(minutes=5)
@ -107,7 +110,8 @@ class HERETravelTimeSensor(CoordinatorEntity, RestoreSensor):
unique_id_prefix: str, unique_id_prefix: str,
name: str, name: str,
sensor_description: SensorEntityDescription, sensor_description: SensorEntityDescription,
coordinator: HERERoutingDataUpdateCoordinator, coordinator: HERERoutingDataUpdateCoordinator
| HERETransitDataUpdateCoordinator,
) -> None: ) -> None:
"""Initialize the sensor.""" """Initialize the sensor."""
super().__init__(coordinator) super().__init__(coordinator)
@ -131,7 +135,7 @@ class HERETravelTimeSensor(CoordinatorEntity, RestoreSensor):
await self._async_restore_state() await self._async_restore_state()
await super().async_added_to_hass() await super().async_added_to_hass()
async def _update_at_start(_): async def _update_at_start(_: HomeAssistant) -> None:
await self.async_update() await self.async_update()
self.async_on_remove(async_at_started(self.hass, _update_at_start)) self.async_on_remove(async_at_started(self.hass, _update_at_start))
@ -149,7 +153,8 @@ class HERETravelTimeSensor(CoordinatorEntity, RestoreSensor):
def attribution(self) -> str | None: def attribution(self) -> str | None:
"""Return the attribution.""" """Return the attribution."""
if self.coordinator.data is not None: if self.coordinator.data is not None:
return self.coordinator.data.get(ATTR_ATTRIBUTION) if (attribution := self.coordinator.data.get(ATTR_ATTRIBUTION)) is not None:
return str(attribution)
return None return None

View File

@ -1054,6 +1054,16 @@ disallow_untyped_defs = true
warn_return_any = true warn_return_any = true
warn_unreachable = true warn_unreachable = true
[mypy-homeassistant.components.here_travel_time.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.history.*] [mypy-homeassistant.components.history.*]
check_untyped_defs = true check_untyped_defs = true
disallow_incomplete_defs = true disallow_incomplete_defs = true