1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
"""Selection for alarms."""
from __future__ import annotations
import contextlib
import datetime
from typing import TYPE_CHECKING, Sequence
from recurring_ical_events.adapters.event import EventAdapter
from recurring_ical_events.adapters.todo import TodoAdapter
from recurring_ical_events.selection.base import SelectComponents
if TYPE_CHECKING:
from icalendar.cal import Component
from recurring_ical_events.adapters.component import ComponentAdapter
from recurring_ical_events.series import Series
class Alarms(SelectComponents):
"""Select alarms and find their times.
By default, alarms from TODOs and events are collected.
You can use this to change which alarms are collected:
Alarms((EventAdapter,))
Alarms((TodoAdapter,))
"""
def __init__(
self,
parents: tuple[type[ComponentAdapter] | SelectComponents] = (
EventAdapter,
TodoAdapter,
),
):
self.parents = parents
@staticmethod
def component_name():
"""The name of the component we calculate."""
return "VALARM"
def collect_parent_series_from(
self, source: Component, suppress_errors: tuple[Exception]
) -> Sequence[Series]:
"""Collect the parent components of alarms."""
return [
s
for parent in self.parents
for s in parent.collect_series_from(source, suppress_errors)
]
def collect_series_from(
self, source: Component, suppress_errors: tuple[Exception]
) -> Sequence[Series]:
"""Collect all TODOs and Alarms from VEVENTs and VTODOs.
suppress_errors - a list of errors that should be suppressed.
A Series of events with such an error is removed from all results.
"""
from recurring_ical_events.series.alarm import (
AbsoluteAlarmSeries,
AlarmSeriesRelativeToEnd,
AlarmSeriesRelativeToStart,
)
absolute_alarms = AbsoluteAlarmSeries()
result = []
# alarms might be copied several times. We only compute them once.
for series in self.collect_parent_series_from(source, suppress_errors):
used_alarms = []
for component in series.components:
for alarm in component.alarms:
with contextlib.suppress(suppress_errors):
trigger = alarm.TRIGGER
if trigger is None or alarm in used_alarms:
continue
if isinstance(trigger, datetime.datetime):
absolute_alarms.add(alarm, component)
used_alarms.append(alarm)
elif alarm.TRIGGER_RELATED == "START":
result.append(AlarmSeriesRelativeToStart(alarm, series))
used_alarms.append(alarm)
elif alarm.TRIGGER_RELATED == "END":
result.append(AlarmSeriesRelativeToEnd(alarm, series))
used_alarms.append(alarm)
if not absolute_alarms.is_empty():
result.append(absolute_alarms)
return result
__all__ = ["Alarms"]
|