Source code for todays_paper_web.widgets.calendar.ical

from __future__ import print_function

from datetime import date, timedelta

from icalendar import Calendar
import recurring_ical_events
import requests
import logging

from pydantic import Field

from todays_paper_web.widgets import DataSource, registerDataSource
from todays_paper_web.widgets.datasource import DataSourceParams

_LOGGER = logging.getLogger(__name__)


class ICalendarModel:
    """Wraps a parsed calendar. `.walk()` delegates to the underlying
    icalendar.Calendar for existing templates; `.eventsOn()`/`.eventsBetween()`
    additionally expand recurring (RRULE) events into concrete occurrences,
    which a plain `.walk('vevent')` cannot do."""

    def __init__(self, calendar: Calendar):
        self.calendar = calendar

    def walk(self, name=None):
        return self.calendar.walk(name)

    def eventsBetween(self, start: date, end: date):
        occurrences = recurring_ical_events.of(self.calendar).between(start, end)
        occurrences.sort(key=lambda event: event.get("dtstart").dt)
        return occurrences

    def eventsOn(self, day: date):
        return self.eventsBetween(day, day + timedelta(days=1))


[docs] class ICalendarParams(DataSourceParams): url: str = Field(..., description="The .ics feed URL, fetched fresh on every `.fetch()` call.")
@registerDataSource("calendar.ical") class ICalendarDataSource(DataSource): Params = ICalendarParams def fetch(self): r = requests.get(self.params.url) cal = Calendar.from_ical(r.text) return ICalendarModel(cal)