Type the caldav warned-calendar cache with HassKey (#176143)

This commit is contained in:
David Wu
2026-08-21 16:19:22 -04:00
committed by GitHub
parent df00965f70
commit 124a081a69
3 changed files with 49 additions and 6 deletions
+2 -5
View File
@@ -1,5 +1,4 @@
"""Library for working with CalDAV api."""
# pylint: disable=home-assistant-use-runtime-data # Uses legacy hass.data[DOMAIN] pattern
import logging
@@ -8,7 +7,7 @@ from caldav.lib.error import DAVError
from homeassistant.core import HomeAssistant
from .const import DOMAIN
from .const import WARNED_CALENDARS
_LOGGER = logging.getLogger(__name__)
@@ -45,9 +44,7 @@ async def async_get_calendars(
calendars, needs_warning = await hass.async_add_executor_job(_get_calendars)
if needs_warning:
warned_calendars: set[tuple[str, str]] = hass.data.setdefault(
DOMAIN, {}
).setdefault("warned_calendars", set())
warned_calendars = hass.data.setdefault(WARNED_CALENDARS, set())
for url, name, comp in needs_warning:
# This workaround and warning can be removed when we upgrade to caldav 3.0
if (url, comp) not in warned_calendars:
+7
View File
@@ -2,5 +2,12 @@
from typing import Final
from homeassistant.util.hass_dict import HassKey
DOMAIN: Final = "caldav"
TIMEOUT: Final = 30
# Calendars we have already warned about, keyed by (url, component). This is
# deliberately not stored on a config entry: the warning is per CalDAV server
# and must survive reloads, and the same server may back more than one entry.
WARNED_CALENDARS: HassKey[set[tuple[str, str]]] = HassKey(f"{DOMAIN}_warned_calendars")
+40 -1
View File
@@ -1,12 +1,14 @@
"""Unit tests for the CalDav integration."""
from unittest.mock import patch
import logging
from unittest.mock import MagicMock, Mock, patch
from caldav.lib.error import AuthorizationError, DAVError
import pytest
import requests
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
@@ -71,3 +73,40 @@ async def test_client_failure(
flows = hass.config_entries.flow.async_progress()
assert [flow.get("step_id") for flow in flows] == expected_flows
@pytest.fixture(name="calendars")
def mock_unsupported_calendar() -> list[Mock]:
"""Fixture for a calendar that does not report its supported components."""
calendar = Mock()
calendar.name = "Example"
calendar.search = MagicMock(return_value=[])
calendar.get_supported_components = MagicMock(side_effect=KeyError())
return [calendar]
@pytest.mark.parametrize("platforms", [[Platform.CALENDAR]])
async def test_supported_components_warning_survives_reload(
hass: HomeAssistant,
config_entry: MockConfigEntry,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the unsupported-components warning is not repeated after a reload.
The de-duplication cache is per CalDAV server rather than per config entry,
so reloading the entry must not warn about the same calendar again.
"""
caplog.set_level(logging.WARNING, logger="homeassistant.components.caldav.api")
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
assert "does not report supported components" in caplog.text
caplog.clear()
await hass.config_entries.async_reload(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
assert "does not report supported components" not in caplog.text