From 19bee11a018a26117f567bec76f7af0f075d7eb3 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Mon, 12 Sep 2022 21:34:35 +0200 Subject: [PATCH] Improve sun typing (#78298) --- homeassistant/components/sun/__init__.py | 69 +++++++++++++----------- homeassistant/components/sun/trigger.py | 4 +- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/homeassistant/components/sun/__init__.py b/homeassistant/components/sun/__init__.py index a30b18befd5..256df2f8971 100644 --- a/homeassistant/components/sun/__init__.py +++ b/homeassistant/components/sun/__init__.py @@ -1,6 +1,11 @@ """Support for functionality to keep track of the sun.""" -from datetime import timedelta +from __future__ import annotations + +from datetime import datetime, timedelta import logging +from typing import Any + +from astral.location import Elevation, Location from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import ( @@ -9,7 +14,7 @@ from homeassistant.const import ( SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET, ) -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback from homeassistant.helpers import event from homeassistant.helpers.entity import Entity from homeassistant.helpers.integration_platform import ( @@ -24,8 +29,6 @@ from homeassistant.util import dt as dt_util from .const import DOMAIN -# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs - _LOGGER = logging.getLogger(__name__) ENTITY_ID = "sun.sun" @@ -114,32 +117,40 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: class Sun(Entity): """Representation of the Sun.""" + _attr_name = "Sun" entity_id = ENTITY_ID - def __init__(self, hass): + location: Location + elevation: Elevation + next_rising: datetime + next_setting: datetime + next_dawn: datetime + next_dusk: datetime + next_midnight: datetime + next_noon: datetime + solar_elevation: float + solar_azimuth: float + rising: bool + _next_change: datetime + + def __init__(self, hass: HomeAssistant) -> None: """Initialize the sun.""" self.hass = hass - self.location = None - self.elevation = 0.0 - self._state = self.next_rising = self.next_setting = None - self.next_dawn = self.next_dusk = None - self.next_midnight = self.next_noon = None - self.solar_elevation = self.solar_azimuth = None - self.rising = self.phase = None - self._next_change = None - self._config_listener = None - self._update_events_listener = None - self._update_sun_position_listener = None + self.phase: str | None = None + + self._config_listener: CALLBACK_TYPE | None = None + self._update_events_listener: CALLBACK_TYPE | None = None + self._update_sun_position_listener: CALLBACK_TYPE | None = None self._config_listener = self.hass.bus.async_listen( EVENT_CORE_CONFIG_UPDATE, self.update_location ) - self.update_location() + self.update_location(initial=True) @callback - def update_location(self, *_): + def update_location(self, _: Event | None = None, initial: bool = False) -> None: """Update location.""" location, elevation = get_astral_location(self.hass) - if location == self.location: + if not initial and location == self.location: return self.location = location self.elevation = elevation @@ -148,7 +159,7 @@ class Sun(Entity): self.update_events() @callback - def remove_listeners(self): + def remove_listeners(self) -> None: """Remove listeners.""" if self._config_listener: self._config_listener() @@ -158,12 +169,7 @@ class Sun(Entity): self._update_sun_position_listener() @property - def name(self): - """Return the name.""" - return "Sun" - - @property - def state(self): + def state(self) -> str: """Return the state of the sun.""" # 0.8333 is the same value as astral uses if self.solar_elevation > -0.833: @@ -172,7 +178,7 @@ class Sun(Entity): return STATE_BELOW_HORIZON @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, Any]: """Return the state attributes of the sun.""" return { STATE_ATTR_NEXT_DAWN: self.next_dawn.isoformat(), @@ -186,7 +192,9 @@ class Sun(Entity): STATE_ATTR_RISING: self.rising, } - def _check_event(self, utc_point_in_time, sun_event, before): + def _check_event( + self, utc_point_in_time: datetime, sun_event: str, before: str | None + ) -> datetime: next_utc = get_location_astral_event_next( self.location, self.elevation, sun_event, utc_point_in_time ) @@ -196,7 +204,7 @@ class Sun(Entity): return next_utc @callback - def update_events(self, now=None): + def update_events(self, now: datetime | None = None) -> None: """Update the attributes containing solar events.""" # Grab current time in case system clock changed since last time we ran. utc_point_in_time = dt_util.utcnow() @@ -266,7 +274,7 @@ class Sun(Entity): _LOGGER.debug("next time: %s", self._next_change.isoformat()) @callback - def update_sun_position(self, now=None): + def update_sun_position(self, now: datetime | None = None) -> None: """Calculate the position of the sun.""" # Grab current time in case system clock changed since last time we ran. utc_point_in_time = dt_util.utcnow() @@ -286,6 +294,7 @@ class Sun(Entity): self.async_write_ha_state() # Next update as per the current phase + assert self.phase delta = _PHASE_UPDATES[self.phase] # if the next update is within 1.25 of the next # position update just drop it diff --git a/homeassistant/components/sun/trigger.py b/homeassistant/components/sun/trigger.py index 86af51f0283..3cc3cabfbd3 100644 --- a/homeassistant/components/sun/trigger.py +++ b/homeassistant/components/sun/trigger.py @@ -15,8 +15,6 @@ from homeassistant.helpers.event import async_track_sunrise, async_track_sunset from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo from homeassistant.helpers.typing import ConfigType -# mypy: allow-untyped-defs, no-check-untyped-defs - TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend( { vol.Required(CONF_PLATFORM): "sun", @@ -42,7 +40,7 @@ async def async_attach_trigger( job = HassJob(action) @callback - def call_action(): + def call_action() -> None: """Call action with right context.""" hass.async_run_hass_job( job,