Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Upgrade Astral to 2.2 #48282

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d533e7c
Upgrade Astral to 2.2
FMKaiba Mar 24, 2021
eeecda9
Fix Rej File
FMKaiba Mar 24, 2021
cd1edcf
Fix for black
FMKaiba Mar 24, 2021
7e735da
Fix Typing
FMKaiba Mar 24, 2021
e9cd322
Add Tests
FMKaiba Mar 24, 2021
bb5bbc3
Tests 2
FMKaiba Mar 24, 2021
0f23942
Fix typo and update testes for more accure NOAA info
FMKaiba Mar 24, 2021
0f675c7
Fix typo and update testes for more accure NOAA info p2
FMKaiba Mar 24, 2021
ba61621
Fix for test_track_sunrise_update_location test
FMKaiba Mar 24, 2021
15b7885
Fix formatting
FMKaiba Mar 26, 2021
677c411
Fix tests for more accurate NOAA Values
FMKaiba Mar 26, 2021
bc9e4dc
Fix Tests to update to more accurate NOAA values
FMKaiba Mar 27, 2021
bad986a
Merge pull request #1 from home-assistant/dev
FMKaiba Mar 27, 2021
1775d0b
Revert testing for rounding
FMKaiba Mar 27, 2021
37bd26a
Upgrade Astral to 2.2
FMKaiba Mar 24, 2021
0037b51
Fix Rej File
FMKaiba Mar 24, 2021
604f251
Fix for black
FMKaiba Mar 24, 2021
edfbb86
Add Tests
FMKaiba Mar 24, 2021
7ddc489
Tests 2
FMKaiba Mar 24, 2021
5eb3e80
Fix typo and update testes for more accure NOAA info
FMKaiba Mar 24, 2021
0e4cfc0
Fix typo and update testes for more accure NOAA info p2
FMKaiba Mar 24, 2021
252b22a
Fix for test_track_sunrise_update_location test
FMKaiba Mar 24, 2021
dfef33b
Fix formatting
FMKaiba Mar 26, 2021
d94c381
Fix tests for more accurate NOAA Values
FMKaiba Mar 26, 2021
f93bb3f
Fix Tests to update to more accurate NOAA values
FMKaiba Mar 27, 2021
dc1a490
Revert testing for rounding
FMKaiba Mar 27, 2021
e363b01
Merge branch 'home-assistant-dev' into dev
FMKaiba Mar 30, 2021
a64c5ec
Remove special test designed to solve issues with long day or night c…
FMKaiba Mar 31, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions homeassistant/components/moon/sensor.py
Original file line number Diff line number Diff line change
@@ -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, SensorEntity
Expand Down Expand Up @@ -48,7 +48,6 @@ def __init__(self, name):
"""Initialize the moon sensor."""
self._name = name
self._state = None
self._astral = Astral()

@property
def name(self):
Expand Down Expand Up @@ -87,4 +86,4 @@ def icon(self):
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)
20 changes: 11 additions & 9 deletions homeassistant/components/sun/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def __init__(self, hass):
"""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
Expand All @@ -100,10 +101,11 @@ def __init__(self, hass):
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)
Expand Down Expand Up @@ -140,7 +142,7 @@ def extra_state_attributes(self):

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
Expand Down Expand Up @@ -169,7 +171,7 @@ def update_events(self, now=None):
)
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
Expand All @@ -180,17 +182,15 @@ def update_events(self, now=None):
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
# be None. Solar noon doesn't always happen when the sun is
# 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:
Expand Down Expand Up @@ -222,9 +222,11 @@ def update_sun_position(self, now=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()
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(
Expand Down
14 changes: 0 additions & 14 deletions homeassistant/components/tod/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,20 +173,6 @@ def _calculate_initial_boudary_time(self):

self._time_before = before_event_date

# We are calculating the _time_after value assuming that it will happen today
# But that is not always true, e.g. after 23:00, before 12:00 and now is 10:00
# If _time_before and _time_after are ahead of current_datetime:
# _time_before is set to 12:00 next day
# _time_after is set to 23:00 today
# current_datetime is set to 10:00 today
if (
self._time_after > self.current_datetime
and self._time_before > self.current_datetime + timedelta(days=1)
):
# remove one day from _time_before and _time_after
self._time_after -= timedelta(days=1)
self._time_before -= timedelta(days=1)

# Add offset to utc boundaries according to the configuration
self._time_after += self._after_offset
self._time_before += self._before_offset
Expand Down
47 changes: 30 additions & 17 deletions homeassistant/helpers/sun.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,32 @@

DATA_LOCATION_CACHE = "astral_location_cache"

ELEVATION_AGNOSTIC_EVENTS = ("noon", "midnight")


@callback
@bind_hass
def get_astral_location(hass: HomeAssistant) -> astral.Location:
def get_astral_location(
hass: HomeAssistant
) -> 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
Expand All @@ -46,40 +51,46 @@ def get_astral_event_next(
offset: datetime.timedelta | None = 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: datetime.datetime | None = None,
offset: datetime.timedelta | None = 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:
next_dt: datetime.datetime = (
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

Expand All @@ -92,19 +103,21 @@ def get_astral_event_date(
date: datetime.date | datetime.datetime | None = None,
) -> datetime.datetime | None:
"""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()

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

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PyNaCl==1.3.0
aiodiscover==1.3.2
aiohttp==3.7.4.post0
aiohttp_cors==0.7.0
astral==1.10.1
astral==2.2
async-upnp-client==0.14.13
async_timeout==3.0.1
attrs==20.3.0
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Home Assistant Core
aiohttp==3.7.4.post0
astral==1.10.1
astral==2.2
async_timeout==3.0.1
attrs==20.3.0
awesomeversion==21.2.3
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

REQUIRES = [
"aiohttp==3.7.4.post0",
"astral==1.10.1",
"astral==2.2",
"async_timeout==3.0.1",
"attrs==20.3.0",
"awesomeversion==21.2.3",
Expand Down
34 changes: 19 additions & 15 deletions tests/components/sun/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,61 +22,65 @@ async def test_setting_rising(hass, legacy_patchable_time):
await hass.async_block_till_done()
state = hass.states.get(sun.ENTITY_ID)

from astral import Astral
from astral import LocationInfo
import astral.sun

astral = Astral()
utc_today = utc_now.date()

latitude = hass.config.latitude
longitude = hass.config.longitude

location = LocationInfo(latitude=latitude, longitude=longitude)

mod = -1
while True:
next_dawn = astral.dawn_utc(
utc_today + timedelta(days=mod), latitude, longitude
next_dawn = astral.sun.dawn(
location.observer, date=utc_today + timedelta(days=mod)
)
if next_dawn > utc_now:
break
mod += 1

mod = -1
while True:
next_dusk = astral.dusk_utc(
utc_today + timedelta(days=mod), latitude, longitude
next_dusk = astral.sun.dusk(
location.observer, date=utc_today + timedelta(days=mod)
)
if next_dusk > utc_now:
break
mod += 1

mod = -1
while True:
next_midnight = astral.solar_midnight_utc(
utc_today + timedelta(days=mod), longitude
next_midnight = astral.sun.midnight(
location.observer, date=utc_today + timedelta(days=mod)
)
if next_midnight > utc_now:
break
mod += 1

mod = -1
while True:
next_noon = astral.solar_noon_utc(utc_today + timedelta(days=mod), longitude)
next_noon = astral.sun.noon(
location.observer, date=utc_today + timedelta(days=mod)
)
if next_noon > utc_now:
break
mod += 1

mod = -1
while True:
next_rising = astral.sunrise_utc(
utc_today + timedelta(days=mod), latitude, longitude
next_rising = astral.sun.sunrise(
location.observer, date=utc_today + timedelta(days=mod)
)
if next_rising > utc_now:
break
mod += 1

mod = -1
while True:
next_setting = astral.sunset_utc(
utc_today + timedelta(days=mod), latitude, longitude
next_setting = astral.sun.sunset(
location.observer, date=utc_today + timedelta(days=mod)
)
if next_setting > utc_now:
break
Expand Down Expand Up @@ -152,10 +156,10 @@ async def test_norway_in_june(hass):

assert dt_util.parse_datetime(
state.attributes[sun.STATE_ATTR_NEXT_RISING]
) == datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC)
) == datetime(2016, 7, 24, 22, 59, 45, 689645, tzinfo=dt_util.UTC)
assert dt_util.parse_datetime(
state.attributes[sun.STATE_ATTR_NEXT_SETTING]
) == datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC)
) == datetime(2016, 7, 25, 22, 17, 13, 503932, tzinfo=dt_util.UTC)

assert state.state == sun.STATE_ABOVE_HORIZON

Expand Down
Loading