Enable strict static type checking for nest integration (#53535)

This commit is contained in:
Allen Porter 2021-07-28 00:12:32 -07:00 committed by GitHub
parent 9e219d9b6e
commit 68945e8814
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 40 additions and 13 deletions

View File

@ -63,6 +63,7 @@ homeassistant.components.mailbox.*
homeassistant.components.media_player.* homeassistant.components.media_player.*
homeassistant.components.mysensors.* homeassistant.components.mysensors.*
homeassistant.components.nam.* homeassistant.components.nam.*
homeassistant.components.nest.*
homeassistant.components.netatmo.* homeassistant.components.netatmo.*
homeassistant.components.network.* homeassistant.components.network.*
homeassistant.components.no_ip.* homeassistant.components.no_ip.*

View File

@ -94,7 +94,7 @@ async def async_get_image(
input_source: str, input_source: str,
output_format: str = IMAGE_JPEG, output_format: str = IMAGE_JPEG,
extra_cmd: str | None = None, extra_cmd: str | None = None,
): ) -> bytes | None:
"""Get an image from a frame of an RTSP stream.""" """Get an image from a frame of an RTSP stream."""
manager = hass.data[DATA_FFMPEG] manager = hass.data[DATA_FFMPEG]
ffmpeg = ImageFrame(manager.binary) ffmpeg = ImageFrame(manager.binary)

View File

@ -1,6 +1,7 @@
"""API for Google Nest Device Access bound to Home Assistant OAuth.""" """API for Google Nest Device Access bound to Home Assistant OAuth."""
import datetime import datetime
from typing import cast
from aiohttp import ClientSession from aiohttp import ClientSession
from google.oauth2.credentials import Credentials from google.oauth2.credentials import Credentials
@ -33,7 +34,7 @@ class AsyncConfigEntryAuth(AbstractAuth):
"""Return a valid access token for SDM API.""" """Return a valid access token for SDM API."""
if not self._oauth_session.valid_token: if not self._oauth_session.valid_token:
await self._oauth_session.async_ensure_token_valid() await self._oauth_session.async_ensure_token_valid()
return self._oauth_session.token["access_token"] return cast(str, self._oauth_session.token["access_token"])
async def async_get_creds(self) -> Credentials: async def async_get_creds(self) -> Credentials:
"""Return an OAuth credential for Pub/Sub Subscriber.""" """Return an OAuth credential for Pub/Sub Subscriber."""

View File

@ -9,10 +9,11 @@ from google_nest_sdm.camera_traits import (
CameraEventImageTrait, CameraEventImageTrait,
CameraImageTrait, CameraImageTrait,
CameraLiveStreamTrait, CameraLiveStreamTrait,
CameraMotionTrait, EventImageGenerator,
RtspStream, RtspStream,
) )
from google_nest_sdm.device import Device from google_nest_sdm.device import Device
from google_nest_sdm.event import ImageEventBase
from google_nest_sdm.exceptions import GoogleNestException from google_nest_sdm.exceptions import GoogleNestException
from haffmpeg.tools import IMAGE_JPEG from haffmpeg.tools import IMAGE_JPEG
@ -121,6 +122,7 @@ class NestCamera(Camera):
_LOGGER.debug("Fetching stream url") _LOGGER.debug("Fetching stream url")
self._stream = await trait.generate_rtsp_stream() self._stream = await trait.generate_rtsp_stream()
self._schedule_stream_refresh() self._schedule_stream_refresh()
assert self._stream
if self._stream.expires_at < utcnow(): if self._stream.expires_at < utcnow():
_LOGGER.warning("Stream already expired") _LOGGER.warning("Stream already expired")
return self._stream.rtsp_stream_url return self._stream.rtsp_stream_url
@ -198,7 +200,11 @@ class NestCamera(Camera):
if not trait: if not trait:
return None return None
# Reuse image bytes if they have already been fetched # Reuse image bytes if they have already been fetched
event = trait.last_event if not isinstance(trait, EventImageGenerator):
return None
event: ImageEventBase | None = trait.last_event
if not event:
return None
if self._event_id is not None and self._event_id == event.event_id: if self._event_id is not None and self._event_id == event.event_id:
return self._event_image_bytes return self._event_image_bytes
_LOGGER.debug("Generating event image URL for event_id %s", event.event_id) _LOGGER.debug("Generating event image URL for event_id %s", event.event_id)
@ -211,7 +217,7 @@ class NestCamera(Camera):
return image_bytes return image_bytes
async def _async_fetch_active_event_image( async def _async_fetch_active_event_image(
self, trait: CameraMotionTrait self, trait: EventImageGenerator
) -> bytes | None: ) -> bytes | None:
"""Return image bytes for an active event.""" """Return image bytes for an active event."""
try: try:

View File

@ -1,13 +1,14 @@
"""Support for Google Nest SDM climate devices.""" """Support for Google Nest SDM climate devices."""
from __future__ import annotations from __future__ import annotations
from typing import Any from typing import Any, cast
from google_nest_sdm.device import Device from google_nest_sdm.device import Device
from google_nest_sdm.device_traits import FanTrait, TemperatureTrait from google_nest_sdm.device_traits import FanTrait, TemperatureTrait
from google_nest_sdm.exceptions import GoogleNestException from google_nest_sdm.exceptions import GoogleNestException
from google_nest_sdm.thermostat_traits import ( from google_nest_sdm.thermostat_traits import (
ThermostatEcoTrait, ThermostatEcoTrait,
ThermostatHeatCoolTrait,
ThermostatHvacTrait, ThermostatHvacTrait,
ThermostatModeTrait, ThermostatModeTrait,
ThermostatTemperatureSetpointTrait, ThermostatTemperatureSetpointTrait,
@ -184,15 +185,20 @@ class ThermostatEntity(ClimateEntity):
@property @property
def _target_temperature_trait( def _target_temperature_trait(
self, self,
) -> ThermostatEcoTrait | ThermostatTemperatureSetpointTrait | None: ) -> ThermostatHeatCoolTrait | None:
"""Return the correct trait with a target temp depending on mode.""" """Return the correct trait with a target temp depending on mode."""
if ( if (
self.preset_mode == PRESET_ECO self.preset_mode == PRESET_ECO
and ThermostatEcoTrait.NAME in self._device.traits and ThermostatEcoTrait.NAME in self._device.traits
): ):
return self._device.traits[ThermostatEcoTrait.NAME] return cast(
ThermostatEcoTrait, self._device.traits[ThermostatEcoTrait.NAME]
)
if ThermostatTemperatureSetpointTrait.NAME in self._device.traits: if ThermostatTemperatureSetpointTrait.NAME in self._device.traits:
return self._device.traits[ThermostatTemperatureSetpointTrait.NAME] return cast(
ThermostatTemperatureSetpointTrait,
self._device.traits[ThermostatTemperatureSetpointTrait.NAME],
)
return None return None
@property @property

View File

@ -61,4 +61,6 @@ class NestDeviceInfo:
# The API intentionally returns minimal information about specific # The API intentionally returns minimal information about specific
# devices, instead relying on traits, but we can infer a generic model # devices, instead relying on traits, but we can infer a generic model
# name based on the type # name based on the type
return DEVICE_TYPE_MAP.get(self._device.type, "Unknown") if self._device.type in DEVICE_TYPE_MAP:
return DEVICE_TYPE_MAP[self._device.type]
return "Unknown"

View File

@ -4,7 +4,7 @@
"config_flow": true, "config_flow": true,
"dependencies": ["ffmpeg", "http"], "dependencies": ["ffmpeg", "http"],
"documentation": "https://www.home-assistant.io/integrations/nest", "documentation": "https://www.home-assistant.io/integrations/nest",
"requirements": ["python-nest==4.1.0", "google-nest-sdm==0.3.0"], "requirements": ["python-nest==4.1.0", "google-nest-sdm==0.3.4"],
"codeowners": ["@allenporter"], "codeowners": ["@allenporter"],
"quality_scale": "platinum", "quality_scale": "platinum",
"dhcp": [ "dhcp": [

View File

@ -704,6 +704,17 @@ no_implicit_optional = true
warn_return_any = true warn_return_any = true
warn_unreachable = true warn_unreachable = true
[mypy-homeassistant.components.nest.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
no_implicit_optional = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.netatmo.*] [mypy-homeassistant.components.netatmo.*]
check_untyped_defs = true check_untyped_defs = true
disallow_incomplete_defs = true disallow_incomplete_defs = true

View File

@ -707,7 +707,7 @@ google-cloud-pubsub==2.1.0
google-cloud-texttospeech==0.4.0 google-cloud-texttospeech==0.4.0
# homeassistant.components.nest # homeassistant.components.nest
google-nest-sdm==0.3.0 google-nest-sdm==0.3.4
# homeassistant.components.google_travel_time # homeassistant.components.google_travel_time
googlemaps==2.5.1 googlemaps==2.5.1

View File

@ -404,7 +404,7 @@ google-api-python-client==1.6.4
google-cloud-pubsub==2.1.0 google-cloud-pubsub==2.1.0
# homeassistant.components.nest # homeassistant.components.nest
google-nest-sdm==0.3.0 google-nest-sdm==0.3.4
# homeassistant.components.google_travel_time # homeassistant.components.google_travel_time
googlemaps==2.5.1 googlemaps==2.5.1