Skip to content

Commit

Permalink
Call TimezoneFinder.timezone_at in executor
Browse files Browse the repository at this point in the history
Add import_executor to manifest.json.
  • Loading branch information
pnbruckner committed Feb 29, 2024
1 parent 2b2e69f commit 25b78ae
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 11 deletions.
7 changes: 4 additions & 3 deletions custom_components/entity_tz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
etzd.tz_users[entry.entry_id] = 0

loc_cache_size = len(etzd.loc_users) * LOC_CACHE_PER_CONFIG
_get_location._LRUCacheWrapper__maxsize = max( # type: ignore[attr-defined] # pylint: disable=protected-access
_get_location._LRUCacheWrapper__maxsize, loc_cache_size # type: ignore[attr-defined] # pylint: disable=protected-access
_get_location._LRUCacheWrapper__maxsize = max( # pylint: disable=protected-access
_get_location._LRUCacheWrapper__maxsize, # pylint: disable=protected-access
loc_cache_size,
)

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
Expand Down Expand Up @@ -98,7 +99,7 @@ async def update_from_entity(event: Event | None = None) -> None:
else:
entity_loc = None
if etzd.tz_users[entry.entry_id]:
entity_tz = get_tz(hass, new_state)
entity_tz = await get_tz(hass, new_state)
else:
entity_tz = None
async_dispatcher_send(hass, signal(entry), entity_loc, entity_tz)
Expand Down
17 changes: 9 additions & 8 deletions custom_components/entity_tz/helpers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Entity Time Zone Sensor Helpers."""
from __future__ import annotations

import asyncio
from collections.abc import Container, Mapping
from dataclasses import dataclass
from datetime import tzinfo
Expand Down Expand Up @@ -77,13 +76,16 @@ def etz_data(hass: HomeAssistant) -> ETZData:

@lru_cache
def _get_tz_from_loc(tzf: TimezoneFinder, lat: float, lng: float) -> tzinfo | None:
"""Get time zone from a location."""
"""Get time zone from a location.
This must be run in an executor since timezone_at may do file I/O.
"""
if (tz_name := tzf.timezone_at(lat=lat, lng=lng)) is None:
return None
return dt_util.get_time_zone(tz_name)


def get_tz(hass: HomeAssistant, state: State | None) -> tzinfo | str | None:
async def get_tz(hass: HomeAssistant, state: State | None) -> tzinfo | str | None:
"""Get time zone from entity state."""
if not state:
return STATE_UNAVAILABLE
Expand All @@ -93,7 +95,9 @@ def get_tz(hass: HomeAssistant, state: State | None) -> tzinfo | str | None:
lng = state.attributes.get(ATTR_LONGITUDE)
if lat is None or lng is None:
return STATE_UNAVAILABLE
tz = _get_tz_from_loc(etz_data(hass).tzf, round(lat, 4), round(lng, 4))
tz = await hass.async_add_executor_job(
_get_tz_from_loc, etz_data(hass).tzf, round(lat, 4), round(lng, 4)
)
_LOGGER.debug("Time zone cache: %s", _get_tz_from_loc.cache_info())
return tz

Expand Down Expand Up @@ -128,11 +132,8 @@ async def update_zones(event: Event | None = None) -> None:

zones = []
for state in hass.states.async_all(ZONE_DOMAIN):
if not_ha_tz(get_tz(hass, state)):
if not_ha_tz(await get_tz(hass, state)):
zones.append(state.entity_id)
# get_tz, since it might call timezone_at, can take a while, so give other
# tasks a chance to run.
await asyncio.sleep(0)
etzd.zones = zones

@callback
Expand Down
1 change: 1 addition & 0 deletions custom_components/entity_tz/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"config_flow": true,
"dependencies": ["zone"],
"documentation": "https://github.com/pnbruckner/ha-entity-tz/blob/1.1.0/README.md",
"import_executor": true,
"iot_class": "calculated",
"issue_tracker": "https://github.com/pnbruckner/ha-entity-tz/issues",
"loggers": ["geopy"],
Expand Down

0 comments on commit 25b78ae

Please sign in to comment.