CalEvent creation and validation

This commit is contained in:
Jörn-Michael Miehe 2022-09-04 21:41:40 +00:00
parent 9d1329d8da
commit 2deda42194

View file

@ -5,7 +5,8 @@ from functools import total_ordering
from typing import Iterator
from caldav import Calendar
from pydantic import BaseModel
from caldav.lib.error import ReportError
from pydantic import BaseModel, validator
from vobject.icalendar import VEvent
from . import caldav_principal, get_ttl_hash, run_in_executor, timed_alru_cache
@ -13,12 +14,19 @@ from . import caldav_principal, get_ttl_hash, run_in_executor, timed_alru_cache
_logger = logging.getLogger(__name__)
def _string_strip(in_str: str) -> str:
return in_str.strip()
@total_ordering
class CalEvent(BaseModel):
summary: str
description: str
dtstart: datetime
dtend: datetime
summary: str = ""
description: str = ""
dtstart: datetime = datetime.utcnow()
dtend: datetime = datetime.utcnow()
class Config:
frozen = True
def __lt__(self, other: "CalEvent") -> bool:
return self.dtstart < other.dtstart
@ -26,6 +34,29 @@ class CalEvent(BaseModel):
def __eq__(self, other: "CalEvent") -> bool:
return self.dict() == other.dict()
_validate_summary = validator(
"summary",
allow_reuse=True,
)(_string_strip)
_validate_description = validator(
"description",
allow_reuse=True,
)(_string_strip)
@classmethod
def from_vevent(cls, event: VEvent) -> "CalEvent":
data = {}
for key in cls().dict().keys():
try:
data[key] = event.contents[key][0].value
except KeyError:
pass
return cls.parse_obj(data)
@timed_alru_cache(maxsize=20)
async def _get_calendar(
@ -50,23 +81,37 @@ async def _get_calendar_events(
print(f"updating {calendar_name}")
calendar = caldav_principal().calendar(calendar_name)
date_start = datetime.utcnow().date()
time_min = datetime.min.time()
dt_start = datetime.combine(date_start, time_min)
dt_end = dt_start + timedelta(days=365)
try:
search_result = calendar.date_search(
start=dt_start,
end=dt_end,
expand=True,
verify_expand=True,
)
except ReportError:
_logger.warn("CalDAV server does not support expanded search")
search_result = calendar.date_search(
start=dt_start,
end=dt_end,
expand=False,
)
return (
vevent
for event in calendar.date_search(
start=datetime.now(),
end=datetime.now() + timedelta(days=365),
expand=True,
)
for event in search_result
for vevent in event.vobject_instance.contents["vevent"]
)
return sorted([
CalEvent(
summary=vevent.summary.value,
description=vevent.description.value,
dtstart=vevent.dtstart.value,
dtend=vevent.dtend.value,
)
CalEvent.from_vevent(vevent)
for vevent in await _inner()
])