Skip to content

Commit

Permalink
Merge pull request #794 from dermotduffy/parallel-puffin
Browse files Browse the repository at this point in the history
fix: Don't block on loading tzinfo objects
  • Loading branch information
dermotduffy authored Nov 28, 2024
2 parents 747af40 + a87ed86 commit bf1f132
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 18 deletions.
2 changes: 1 addition & 1 deletion custom_components/frigate/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"documentation": "https://github.com/blakeblackshear/frigate",
"iot_class": "local_push",
"issue_tracker": "https://github.com/blakeblackshear/frigate-hass-integration/issues",
"requirements": ["hass-web-proxy-lib==0.0.7", "pytz"],
"requirements": ["hass-web-proxy-lib==0.0.7"],
"version": "5.5.1"
}
24 changes: 14 additions & 10 deletions custom_components/frigate/media_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import attr
from dateutil.relativedelta import relativedelta
import pytz

from homeassistant.components.media_player.const import MediaClass, MediaType
from homeassistant.components.media_source.error import MediaSourceError, Unresolvable
Expand All @@ -22,7 +21,7 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers import system_info
from homeassistant.helpers.template import DATE_STR_FORMAT
from homeassistant.util.dt import DEFAULT_TIME_ZONE
from homeassistant.util.dt import DEFAULT_TIME_ZONE, async_get_time_zone

from . import get_friendly_name
from .api import FrigateApiClient, FrigateApiClientError
Expand Down Expand Up @@ -118,7 +117,7 @@ def get_identifier_type(cls) -> str:
"""Get the identifier type."""
raise NotImplementedError

def get_integration_proxy_path(self, timezone: str) -> str:
def get_integration_proxy_path(self, tz_info: dt.tzinfo) -> str:
"""Get the proxy (Home Assistant view) path for this identifier."""
raise NotImplementedError

Expand Down Expand Up @@ -240,7 +239,7 @@ def get_identifier_type(cls) -> str:
"""Get the identifier type."""
return "event"

def get_integration_proxy_path(self, timezone: str) -> str:
def get_integration_proxy_path(self, tz_info: dt.tzinfo) -> str:
"""Get the equivalent Frigate server path."""
if self.frigate_media_type == FrigateMediaType.CLIPS:
return f"vod/event/{self.id}/index.{self.frigate_media_type.extension}"
Expand Down Expand Up @@ -444,7 +443,7 @@ def get_identifier_type(cls) -> str:
"""Get the identifier type."""
return "recordings"

def get_integration_proxy_path(self, timezone: str) -> str:
def get_integration_proxy_path(self, tz_info: dt.tzinfo) -> str:
"""Get the integration path that will proxy this identifier."""

if (
Expand All @@ -460,8 +459,8 @@ def get_integration_proxy_path(self, timezone: str) -> str:
int(month),
int(day),
int(self.hour),
tzinfo=dt.timezone.utc,
) - (dt.datetime.now(pytz.timezone(timezone)).utcoffset() or dt.timedelta())
tzinfo=dt.UTC,
) - (dt.datetime.now(tz_info).utcoffset() or dt.timedelta())

parts = [
"vod",
Expand Down Expand Up @@ -565,9 +564,14 @@ async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia:
identifier.frigate_instance_id
):
info = await system_info.async_get_system_info(self.hass)
server_path = identifier.get_integration_proxy_path(
info.get("timezone", "utc")
)
tz_name = info.get("timezone", "utc")
tz_info = await async_get_time_zone(tz_name)
if not tz_info:
raise Unresolvable(
f"Could not get timezone object for timezone: {tz_name}"
)

server_path = identifier.get_integration_proxy_path(tz_info)
return PlayMedia(
f"/api/frigate/{identifier.frigate_instance_id}/{server_path}",
identifier.mime_type,
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ homeassistant==2024.11.3
paho-mqtt
python-dateutil
yarl
pytz
hass-web-proxy-lib==0.0.7
1 change: 0 additions & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ pylint
pytest-aiohttp
pytest-asyncio
types-python-dateutil
types-pytz
24 changes: 19 additions & 5 deletions tests/test_media_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from unittest.mock import AsyncMock, Mock, call, patch

import pytest
import pytz

from custom_components.frigate.api import FrigateApiClient, FrigateApiClientError
from custom_components.frigate.const import (
Expand All @@ -37,6 +36,7 @@
from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant
from homeassistant.helpers import system_info
from homeassistant.util.dt import DEFAULT_TIME_ZONE, async_get_time_zone

from . import (
TEST_CONFIG,
Expand Down Expand Up @@ -624,7 +624,7 @@ async def test_async_browse_media_clip_search_multi_month_drilldown(
async def test_async_resolve_media(
frigate_client: AsyncMock, hass: HomeAssistant
) -> None:
"""Test successful resolve media."""
"""Test resolving media."""

await setup_mock_frigate_config_entry(hass, client=frigate_client)

Expand Down Expand Up @@ -652,7 +652,9 @@ async def test_async_resolve_media(
# Convert from HA local timezone to UTC.
info = await system_info.async_get_system_info(hass)
date = datetime.datetime(2021, 5, 30, 15, 46, 8, 0, datetime.timezone.utc) - (
datetime.datetime.now(pytz.timezone(info.get("timezone", "utc"))).utcoffset()
datetime.datetime.now(
await async_get_time_zone(info.get("timezone", "utc"))
).utcoffset()
or datetime.timedelta()
)

Expand Down Expand Up @@ -686,6 +688,18 @@ async def test_async_resolve_media(
target_media_player="media_player.kitchen",
)

# Test resolving when system timezone is not found.
with patch(
"homeassistant.helpers.system_info.async_get_system_info",
return_value={"timezone": "UNKNOWN"},
):
with pytest.raises(Unresolvable):
media = await media_source.async_resolve_media(
hass,
f"{const.URI_SCHEME}{DOMAIN}/{TEST_FRIGATE_INSTANCE_ID}/event/clips/camera/CLIP-FOO",
target_media_player="media_player.kitchen",
)


async def test_async_browse_media_recordings_root(
caplog: Any, frigate_client: AsyncMock, hass: HomeAssistant
Expand Down Expand Up @@ -998,7 +1012,7 @@ async def test_event_search_identifier() -> None:
# Event searches have no equivalent Frigate server path (searches result in
# EventIdentifiers, that do have a Frigate server path).
with pytest.raises(NotImplementedError):
identifier.get_integration_proxy_path("utc")
identifier.get_integration_proxy_path(DEFAULT_TIME_ZONE)

# Invalid "after" time.
assert (
Expand Down Expand Up @@ -1091,7 +1105,7 @@ async def test_recordings_identifier() -> None:
identifier_in = f"{TEST_FRIGATE_INSTANCE_ID}/recordings/front_door//15"
identifier = RecordingIdentifier.from_str(identifier_in)
assert identifier is not None
identifier.get_integration_proxy_path("utc")
identifier.get_integration_proxy_path(DEFAULT_TIME_ZONE)

# Verify a zero hour:
# https://github.com/blakeblackshear/frigate-hass-integration/issues/126
Expand Down

0 comments on commit bf1f132

Please sign in to comment.