import logging from dataclasses import dataclass from datetime import datetime, timedelta from typing import Iterator from caldav import Calendar from pydantic import BaseModel from vobject.base import VBase from . import caldav_principal, get_ttl_hash, run_in_executor, timed_alru_cache _logger = logging.getLogger(__name__) class CalEvent(BaseModel): summary: str description: str dtstart: datetime dtend: datetime @timed_alru_cache(maxsize=20) async def _get_calendar( calendar_name: str, ) -> Calendar: @run_in_executor def _get_calendar_inner() -> Calendar: _logger.info(f"updating {calendar_name}") print(f"updating {calendar_name}") return caldav_principal().calendar(calendar_name) return await _get_calendar_inner() @dataclass(frozen=True) class DavCalendar: calendar_name: str @property async def calendar(self) -> Calendar: return await _get_calendar( ttl_hash=get_ttl_hash(20), calendar_name=self.calendar_name, ) @property async def events(self) -> Iterator[CalEvent]: async def _find_vevents() -> Iterator[VBase]: calendar = await self.calendar return ( vevent for event in calendar.date_search( start=datetime.now(), end=datetime.now() + timedelta(days=365), expand=True, ) for vevent in event.vobject_instance.contents["vevent"] ) return ( CalEvent( summary=vevent.summary.value, description=vevent.description.value, dtstart=vevent.dtstart.value, dtend=vevent.dtend.value, ) for vevent in await _find_vevents() )