Jellyfin(8096), OrbStack(8097) 포트 충돌으로 변경. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
"""Selecting components by name."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import contextlib
|
|
from collections import defaultdict
|
|
from typing import TYPE_CHECKING, Sequence
|
|
|
|
from recurring_ical_events.adapters.event import EventAdapter
|
|
from recurring_ical_events.adapters.journal import JournalAdapter
|
|
from recurring_ical_events.adapters.todo import TodoAdapter
|
|
from recurring_ical_events.occurrence import Occurrence
|
|
from recurring_ical_events.selection.alarm import Alarms
|
|
from recurring_ical_events.selection.base import SelectComponents
|
|
from recurring_ical_events.series import Series
|
|
from recurring_ical_events.util import cached_property
|
|
|
|
if TYPE_CHECKING:
|
|
from icalendar.cal import Component
|
|
|
|
from recurring_ical_events.adapters.component import ComponentAdapter
|
|
|
|
|
|
class ComponentsWithName(SelectComponents):
|
|
"""This is a component collecttion strategy.
|
|
|
|
Components can be collected in different ways.
|
|
This class allows extension of the functionality by
|
|
- subclassing to filter the resulting components
|
|
- composition to combine collection behavior (see AllKnownComponents)
|
|
"""
|
|
|
|
component_adapters: list[type[ComponentAdapter] | SelectComponents] = [
|
|
EventAdapter,
|
|
TodoAdapter,
|
|
JournalAdapter,
|
|
Alarms(),
|
|
]
|
|
|
|
@cached_property
|
|
def _component_adapters(self) -> dict[str : type[ComponentAdapter]]:
|
|
"""A mapping of component adapters."""
|
|
return {
|
|
adapter.component_name(): adapter for adapter in self.component_adapters
|
|
}
|
|
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
adapter: type[ComponentAdapter] | None = None,
|
|
series: type[Series] = Series,
|
|
occurrence: type[Occurrence] = Occurrence,
|
|
) -> None:
|
|
"""Create a new way of collecting components.
|
|
|
|
name - the name of the component to collect ("VEVENT", "VTODO", "VJOURNAL")
|
|
adapter - the adapter to use for these components with that name
|
|
series - the series class that hold a series of components
|
|
occurrence - the occurrence class that creates the resulting components
|
|
"""
|
|
if adapter is None:
|
|
if name not in self._component_adapters:
|
|
raise ValueError(
|
|
f'"{name}" is an unknown name for a '
|
|
"recurring component. "
|
|
f"I only know these: {', '.join(self._component_adapters)}."
|
|
)
|
|
adapter = self._component_adapters[name]
|
|
if occurrence is not Occurrence:
|
|
_occurrence = occurrence
|
|
|
|
class series(series): # noqa: N801
|
|
occurrence = _occurrence
|
|
|
|
self._name = name
|
|
self._series = series
|
|
self._adapter = adapter
|
|
|
|
def collect_series_from(
|
|
self, source: Component, suppress_errors: tuple[Exception]
|
|
) -> Sequence[Series]:
|
|
"""Collect all components from the source component.
|
|
|
|
suppress_errors - a list of errors that should be suppressed.
|
|
A Series of events with such an error is removed from all results.
|
|
"""
|
|
if isinstance(self._adapter, SelectComponents):
|
|
return self._adapter.collect_series_from(source, suppress_errors)
|
|
components: dict[str, list[Component]] = defaultdict(list) # UID -> components
|
|
for component in source.walk(self._name):
|
|
adapter = self._adapter(component)
|
|
components[adapter.uid].append(adapter)
|
|
result = []
|
|
for components in components.values():
|
|
with contextlib.suppress(suppress_errors):
|
|
result.append(self._series(components))
|
|
return result
|
|
|
|
|
|
__all__ = ["ComponentsWithName"]
|