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:
151
.venv/lib/python3.9/site-packages/recurring_ical_events/pages.py
Normal file
151
.venv/lib/python3.9/site-packages/recurring_ical_events/pages.py
Normal file
@@ -0,0 +1,151 @@
|
||||
"""Pagination for recurring ical events.
|
||||
|
||||
See https://github.com/niccokunzmann/python-recurring-ical-events/issues/211
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Iterator, Optional
|
||||
|
||||
from recurring_ical_events.util import compare_greater
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from icalendar import Component
|
||||
|
||||
from recurring_ical_events.occurrence import Occurrence
|
||||
from recurring_ical_events.types import Time
|
||||
|
||||
|
||||
class Page:
|
||||
"""One page in a series of pages.
|
||||
|
||||
Examples:
|
||||
Check if the page has components.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if page:
|
||||
print(f"We have {len(page)} components.")
|
||||
|
||||
Go though the components:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
for component in page:
|
||||
print(component)
|
||||
"""
|
||||
|
||||
def __init__(self, components: list[Component], next_page_id: str = ""):
|
||||
""" "Create a new page."""
|
||||
self._components = components
|
||||
self._next_page_id = next_page_id
|
||||
|
||||
@property
|
||||
def components(self) -> list[Component]:
|
||||
"""All the components of this page."""
|
||||
return self._components
|
||||
|
||||
def has_next_page(self) -> bool:
|
||||
"""Wether there is a page following this one."""
|
||||
return self.next_page_id != ""
|
||||
|
||||
@property
|
||||
def next_page_id(self) -> str:
|
||||
"""The id of the next page or ``''``."""
|
||||
return self._next_page_id
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""The number of components."""
|
||||
return len(self.components)
|
||||
|
||||
def is_last(self) -> bool:
|
||||
"""Wether this is the last page and there is no other page following."""
|
||||
return self._next_page_id == ""
|
||||
|
||||
def __iter__(self) -> Iterator[Component]:
|
||||
"""Return an iterator over the components."""
|
||||
return iter(self.components)
|
||||
|
||||
|
||||
class Pages:
|
||||
"""A pagination configuration to iterate over pages.
|
||||
|
||||
This is an :class:`Iterator` that returns :class:`Page` objects.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
occurrence_iterator: Iterator[Occurrence],
|
||||
size: int,
|
||||
stop: Optional[Time] = None,
|
||||
keep_recurrence_attributes: bool = False, # noqa: FBT001
|
||||
):
|
||||
"""Create a new paginated iterator over components."""
|
||||
self._iterator = occurrence_iterator
|
||||
self._stop = stop
|
||||
self._size = size
|
||||
if self._size <= 0:
|
||||
raise ValueError(
|
||||
f"A page must have at least one component, not {self._size}."
|
||||
)
|
||||
self._keep_recurrence_attributes = keep_recurrence_attributes
|
||||
self._next_occurrence: Optional[Occurrence] = None
|
||||
for occurrence in self._iterator:
|
||||
if self._stop is None or compare_greater(self._stop, occurrence.start):
|
||||
self._next_occurrence = occurrence
|
||||
break
|
||||
|
||||
@property
|
||||
def size(self) -> int:
|
||||
"""The maximum number of components per page."""
|
||||
return self._size
|
||||
|
||||
def generate_next_page(self) -> Page:
|
||||
"""Generate the next page.
|
||||
|
||||
In contrast to ``next(pages)``, this does not raise :class:`StopIteration`.
|
||||
But it works the same: the next page is generated and returned.
|
||||
The last page is empty.
|
||||
"""
|
||||
for page in self:
|
||||
return page
|
||||
return Page([])
|
||||
|
||||
def __next__(self) -> Page:
|
||||
"""Return the next page."""
|
||||
if self._next_occurrence is None:
|
||||
raise StopIteration
|
||||
last_occurrence = self._next_occurrence
|
||||
occurrences = [last_occurrence]
|
||||
for occurrence in self._iterator:
|
||||
if self._stop is not None and compare_greater(occurrence.start, self._stop):
|
||||
break
|
||||
last_occurrence = occurrence
|
||||
if len(occurrences) < self._size:
|
||||
occurrences.append(occurrence)
|
||||
else:
|
||||
break
|
||||
if occurrences[-1] == last_occurrence:
|
||||
self._next_occurrence = None
|
||||
else:
|
||||
self._next_occurrence = last_occurrence
|
||||
return self._create_page_from_occurrences(occurrences)
|
||||
|
||||
def _create_page_from_occurrences(self, occurrences: list[Occurrence]) -> Page:
|
||||
"""Create a new page from the occurrences listed."""
|
||||
return Page(
|
||||
[
|
||||
occurrence.as_component(self._keep_recurrence_attributes)
|
||||
for occurrence in occurrences
|
||||
],
|
||||
next_page_id=self._next_occurrence.id.to_string()
|
||||
if self._next_occurrence is not None
|
||||
else "",
|
||||
)
|
||||
|
||||
def __iter__(self) -> Pages:
|
||||
"""Return the iterator."""
|
||||
return self
|
||||
|
||||
|
||||
__all__ = ["Page", "Pages"]
|
||||
Reference in New Issue
Block a user