From c50af6847944e591d0e5dd8760f139b2bb3da33e Mon Sep 17 00:00:00 2001 From: Giovanni Harting <539@idlegandalf.com> Date: Mon, 22 Mar 2021 18:35:14 +0100 Subject: [PATCH] bump astral to 2.2 --- homeassistant/components/moon/sensor.py | 5 +-- homeassistant/components/sun/__init__.py | 20 +++++----- homeassistant/helpers/sun.py | 50 +++++++++++++++--------- homeassistant/package_constraints.txt | 2 +- requirements.txt | 2 +- setup.py | 2 +- 6 files changed, 47 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/moon/sensor.py b/homeassistant/components/moon/sensor.py index 9e0f8ef51d..9b29b071ee 100644 --- a/homeassistant/components/moon/sensor.py +++ b/homeassistant/components/moon/sensor.py @@ -1,5 +1,5 @@ """Support for tracking the moon phases.""" -from astral import Astral +from astral import moon import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA @@ -49,7 +49,6 @@ class MoonSensor(Entity): """Initialize the moon sensor.""" self._name = name self._state = None - self._astral = Astral() @property def name(self): @@ -88,4 +87,4 @@ class MoonSensor(Entity): async def async_update(self): """Get the time and updates the states.""" today = dt_util.as_local(dt_util.utcnow()).date() - self._state = self._astral.moon_phase(today) + self._state = moon.phase(today) diff --git a/homeassistant/components/sun/__init__.py b/homeassistant/components/sun/__init__.py index 2d921da4a4..ec8f4b325a 100644 --- a/homeassistant/components/sun/__init__.py +++ b/homeassistant/components/sun/__init__.py @@ -92,6 +92,7 @@ class Sun(Entity): """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 @@ -100,10 +101,11 @@ class Sun(Entity): self._next_change = None def update_location(_event): - location = get_astral_location(self.hass) + location, elevation = get_astral_location(self.hass) if location == self.location: return self.location = location + self.elevation = elevation self.update_events() update_location(None) @@ -140,7 +142,7 @@ class Sun(Entity): def _check_event(self, utc_point_in_time, sun_event, before): next_utc = get_location_astral_event_next( - self.location, sun_event, utc_point_in_time + self.location, self.elevation, sun_event, utc_point_in_time ) if next_utc < self._next_change: self._next_change = next_utc @@ -169,7 +171,7 @@ class Sun(Entity): ) self.location.solar_depression = -10 self._check_event(utc_point_in_time, "dawn", PHASE_SMALL_DAY) - self.next_noon = self._check_event(utc_point_in_time, "solar_noon", None) + self.next_noon = self._check_event(utc_point_in_time, "noon", None) self._check_event(utc_point_in_time, "dusk", PHASE_DAY) self.next_setting = self._check_event( utc_point_in_time, SUN_EVENT_SUNSET, PHASE_SMALL_DAY @@ -180,9 +182,7 @@ class Sun(Entity): self._check_event(utc_point_in_time, "dusk", PHASE_NAUTICAL_TWILIGHT) self.location.solar_depression = "astronomical" self._check_event(utc_point_in_time, "dusk", PHASE_ASTRONOMICAL_TWILIGHT) - self.next_midnight = self._check_event( - utc_point_in_time, "solar_midnight", None - ) + self.next_midnight = self._check_event(utc_point_in_time, "midnight", None) self.location.solar_depression = "civil" # if the event was solar midday or midnight, phase will now @@ -190,7 +190,7 @@ class Sun(Entity): # even in the day at the poles, so we can't rely on it. # Need to calculate phase if next is noon or midnight if self.phase is None: - elevation = self.location.solar_elevation(self._next_change) + elevation = self.location.solar_elevation(self._next_change, self.elevation) if elevation >= 10: self.phase = PHASE_DAY elif elevation >= 0: @@ -222,9 +222,11 @@ class Sun(Entity): """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() - self.solar_azimuth = round(self.location.solar_azimuth(utc_point_in_time), 2) + self.solar_azimuth = round( + self.location.solar_azimuth(utc_point_in_time, self.elevation), 2 + ) self.solar_elevation = round( - self.location.solar_elevation(utc_point_in_time), 2 + self.location.solar_elevation(utc_point_in_time, self.elevation), 2 ) _LOGGER.debug( diff --git a/homeassistant/helpers/sun.py b/homeassistant/helpers/sun.py index 2b82e19b8c..a4c16833e4 100644 --- a/homeassistant/helpers/sun.py +++ b/homeassistant/helpers/sun.py @@ -2,7 +2,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Optional, Union +from typing import TYPE_CHECKING, Optional, Tuple, Union from homeassistant.const import SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET from homeassistant.core import callback @@ -16,27 +16,32 @@ if TYPE_CHECKING: DATA_LOCATION_CACHE = "astral_location_cache" +ELEVATION_AGNOSTIC_EVENTS = ("noon", "midnight") + @callback @bind_hass -def get_astral_location(hass: HomeAssistantType) -> astral.Location: +def get_astral_location( + hass: HomeAssistantType, +) -> Tuple["astral.location.Location", "astral.Elevation"]: """Get an astral location for the current Home Assistant configuration.""" - from astral import Location # pylint: disable=import-outside-toplevel + from astral import LocationInfo # pylint: disable=import-outside-toplevel + from astral.location import Location # pylint: disable=import-outside-toplevel + timezone = str(hass.config.time_zone) latitude = hass.config.latitude longitude = hass.config.longitude - timezone = str(hass.config.time_zone) elevation = hass.config.elevation - info = ("", "", latitude, longitude, timezone, elevation) + info = ("", "", timezone, latitude, longitude) # Cache astral locations so they aren't recreated with the same args if DATA_LOCATION_CACHE not in hass.data: hass.data[DATA_LOCATION_CACHE] = {} if info not in hass.data[DATA_LOCATION_CACHE]: - hass.data[DATA_LOCATION_CACHE][info] = Location(info) + hass.data[DATA_LOCATION_CACHE][info] = Location(LocationInfo(*info)) - return hass.data[DATA_LOCATION_CACHE][info] + return hass.data[DATA_LOCATION_CACHE][info], elevation @callback @@ -48,26 +53,31 @@ def get_astral_event_next( offset: Optional[datetime.timedelta] = None, ) -> datetime.datetime: """Calculate the next specified solar event.""" - location = get_astral_location(hass) - return get_location_astral_event_next(location, event, utc_point_in_time, offset) + location, elevation = get_astral_location(hass) + return get_location_astral_event_next( + location, elevation, event, utc_point_in_time, offset + ) @callback def get_location_astral_event_next( - location: "astral.Location", + location: "astral.location.Location", + elevation: "astral.Elevation", event: str, utc_point_in_time: Optional[datetime.datetime] = None, offset: Optional[datetime.timedelta] = None, ) -> datetime.datetime: """Calculate the next specified solar event.""" - from astral import AstralError # pylint: disable=import-outside-toplevel - if offset is None: offset = datetime.timedelta() if utc_point_in_time is None: utc_point_in_time = dt_util.utcnow() + kwargs = {"local": False} + if event not in ELEVATION_AGNOSTIC_EVENTS: + kwargs["observer_elevation"] = elevation + mod = -1 while True: try: @@ -75,13 +85,13 @@ def get_location_astral_event_next( getattr(location, event)( dt_util.as_local(utc_point_in_time).date() + datetime.timedelta(days=mod), - local=False, + **kwargs, ) + offset ) if next_dt > utc_point_in_time: return next_dt - except AstralError: + except ValueError: pass mod += 1 @@ -94,9 +104,7 @@ def get_astral_event_date( date: Union[datetime.date, datetime.datetime, None] = None, ) -> Optional[datetime.datetime]: """Calculate the astral event time for the specified date.""" - from astral import AstralError # pylint: disable=import-outside-toplevel - - location = get_astral_location(hass) + location, elevation = get_astral_location(hass) if date is None: date = dt_util.now().date() @@ -104,9 +112,13 @@ def get_astral_event_date( if isinstance(date, datetime.datetime): date = dt_util.as_local(date).date() + kwargs = {"local": False} + if event not in ELEVATION_AGNOSTIC_EVENTS: + kwargs["observer_elevation"] = elevation + try: - return getattr(location, event)(date, local=False) # type: ignore - except AstralError: + return getattr(location, event)(date, **kwargs) # type: ignore + except ValueError: # Event never occurs for specified date. return None diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 7642e14bda..534fa68211 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -2,7 +2,7 @@ PyJWT==1.7.1 PyNaCl==1.3.0 aiohttp==3.7.4 aiohttp_cors==0.7.0 -astral==1.10.1 +astral==2.2 async-upnp-client==0.14.13 async_timeout==3.0.1 attrs==19.3.0 diff --git a/requirements.txt b/requirements.txt index 0a5b754dbf..e3acc1948d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Home Assistant Core aiohttp==3.7.4 -astral==1.10.1 +astral==2.2 async_timeout==3.0.1 attrs==19.3.0 awesomeversion==21.2.3 diff --git a/setup.py b/setup.py index ce7d6b6883..f25250dd95 100755 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ PACKAGES = find_packages(exclude=["tests", "tests.*"]) REQUIRES = [ "aiohttp==3.7.4", - "astral==1.10.1", + "astral==2.2", "async_timeout==3.0.1", "attrs==19.3.0", "awesomeversion==21.2.3", -- 2.31.0