fix: 포트 충돌 회피 — note_bridge 8098, intent_service 8099

Jellyfin(8096), OrbStack(8097) 포트 충돌으로 변경.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-19 13:53:55 +09:00
parent dc08d29509
commit c2257d3a86
2709 changed files with 619549 additions and 10 deletions

View File

@@ -0,0 +1,13 @@
"""Select components for calculation."""
from .alarm import Alarms
from .all import AllKnownComponents
from .base import SelectComponents
from .name import ComponentsWithName
__all__ = [
"Alarms",
"AllKnownComponents",
"ComponentsWithName",
"SelectComponents",
]

View File

@@ -0,0 +1,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"]

View File

@@ -0,0 +1,62 @@
"""Selection of all components with the correct adapters."""
from __future__ import annotations
from typing import TYPE_CHECKING, Sequence
from recurring_ical_events.occurrence import Occurrence
from recurring_ical_events.selection.base import SelectComponents
from recurring_ical_events.selection.name import ComponentsWithName
from recurring_ical_events.series import Series
if TYPE_CHECKING:
from icalendar.cal import Component
from recurring_ical_events.adapters.component import ComponentAdapter
class AllKnownComponents(SelectComponents):
"""Group all known components into series."""
@property
def _component_adapters(self) -> Sequence[ComponentAdapter]:
"""Return all known component adapters."""
return ComponentsWithName.component_adapters
@property
def names(self) -> list[str]:
"""Return the names of the components to collect."""
result = [adapter.component_name() for adapter in self._component_adapters]
result.sort()
return result
def __init__(
self,
series: type[Series] = Series,
occurrence: type[Occurrence] = Occurrence,
collector: type[ComponentsWithName] = ComponentsWithName,
) -> None:
"""Collect all known components and overide the series and occurrence.
series - the Series class to override that is queried for Occurrences
occurrence - the occurrence class that creates the resulting components
collector - if you want to override the SelectComponentsByName class
"""
self._series = series
self._occurrence = occurrence
self._collector = collector
def collect_series_from(
self, source: Component, suppress_errors: tuple[Exception]
) -> Sequence[Series]:
"""Collect the components from the source groups into a series."""
result = []
for name in self.names:
collector = self._collector(
name, series=self._series, occurrence=self._occurrence
)
result.extend(collector.collect_series_from(source, suppress_errors))
return result
__all__ = ["AllKnownComponents"]

View File

@@ -0,0 +1,33 @@
"""Base interface for selection of components."""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Sequence
if TYPE_CHECKING:
from icalendar.cal import Component
from recurring_ical_events.series import Series
class SelectComponents(ABC):
"""Abstract class to select components from a calendar."""
@staticmethod
def component_name():
"""The name of the component if there is only one."""
raise NotImplementedError("This should be implemented in subclasses.")
@abstractmethod
def collect_series_from(
self, source: Component, suppress_errors: tuple[Exception]
) -> Sequence[Series]:
"""Collect all components from the source grouped together into a series.
suppress_errors - a list of errors that should be suppressed.
A Series of events with such an error is removed from all results.
"""
__all__ = ["SelectComponents"]

View File

@@ -0,0 +1,100 @@
"""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"]