refac: fix calendar router

This commit is contained in:
Jörn-Michael Miehe 2023-10-26 17:46:12 +02:00
parent fc2388dd12
commit cdf4ce4d16
4 changed files with 71 additions and 72 deletions

View file

@ -21,8 +21,8 @@ class CalDAV:
password=SETTINGS.caldav.password, password=SETTINGS.caldav.password,
) )
@property
@classmethod @classmethod
@property
def principal(cls) -> Principal: def principal(cls) -> Principal:
""" """
Gets the `Principal` object of the main CalDAV client. Gets the `Principal` object of the main CalDAV client.
@ -31,6 +31,7 @@ class CalDAV:
_logger.debug("principal") _logger.debug("principal")
return cls._caldav_client.principal() return cls._caldav_client.principal()
@classmethod
@property @property
@AsyncTTL( @AsyncTTL(
time_to_live=SETTINGS.caldav.cache_ttl, time_to_live=SETTINGS.caldav.cache_ttl,
@ -38,7 +39,6 @@ class CalDAV:
skip_args=1, skip_args=1,
) )
@asyncify @asyncify
@classmethod
def calendars(cls) -> list[str]: def calendars(cls) -> list[str]:
""" """
Asynchroneously lists all calendars using the main WebDAV client. Asynchroneously lists all calendars using the main WebDAV client.

View file

@ -7,7 +7,7 @@ This file: Main API router definition.
from fastapi import APIRouter from fastapi import APIRouter
# from . import aggregate, calendar, file, image, misc, text, ticker # from . import aggregate, calendar, file, image, misc, text, ticker
from . import file, image, misc, text, ticker from . import calendar, file, image, misc, text, ticker
router = APIRouter(prefix="/api/v1") router = APIRouter(prefix="/api/v1")
@ -18,7 +18,7 @@ router.include_router(ticker.router)
router.include_router(image.router) router.include_router(image.router)
router.include_router(file.router) router.include_router(file.router)
# router.include_router(calendar.router) router.include_router(calendar.router)
# router.include_router(aggregate.router) # router.include_router(aggregate.router)
__all__ = ["router"] __all__ = ["router"]

View file

@ -3,19 +3,17 @@ Dependables for defining Routers.
""" """
import re import re
from dataclasses import dataclass from dataclasses import dataclass, field
from logging import getLogger from logging import getLogger
from typing import Awaitable, Callable, Generic, ParamSpec, TypeVar from typing import Awaitable, Callable, Generic, ParamSpec, Self, TypeVar
from fastapi import Depends, HTTPException, params, status from fastapi import Depends, HTTPException, params, status
from webdav3.exceptions import RemoteResourceNotFound from webdav3.exceptions import RemoteResourceNotFound
from ...core.caldav import CalDAV
from ...core.config import get_config from ...core.config import get_config
from ...core.webdav import WebDAV from ...core.webdav import WebDAV
# from ...core.caldav import CalDAV
# from ...core.config import Config, get_config
_logger = getLogger(__name__) _logger = getLogger(__name__)
_RESPONSE_OK = { _RESPONSE_OK = {
@ -33,42 +31,34 @@ type _Dependable[**Params, Return] = Callable[Params, Awaitable[Return]]
@dataclass(slots=True, frozen=True) @dataclass(slots=True, frozen=True)
class Dependable(Generic[Params, Return]): class Dependable(Generic[Params, Return]):
func: _Dependable[Params, Return] func: _Dependable[Params, Return]
responses: dict responses: dict = field(default_factory=lambda: _RESPONSE_OK.copy())
@dataclass(init=False, slots=True, frozen=True) @dataclass(slots=True, frozen=True)
class ListManager: class ListManager:
lister: Dependable[[], list[str]] lister: Dependable[[], list[str]]
filter: Dependable[[str], list[str]] filter: Dependable[[str], list[str]]
getter: Dependable[[str], str] getter: Dependable[[str], str]
def __init__( @classmethod
self, def from_lister(cls, lister: Dependable[[], list[str]]) -> Self:
lister: Dependable[[], list[str]], async def _filter_fn(
) -> None:
object.__setattr__(self, "lister", lister)
async def _filter(
prefix: str, prefix: str,
names: list[str] = Depends(self.lister.func), names: list[str] = Depends(lister.func),
) -> list[str]: ) -> list[str]:
if isinstance(names, params.Depends): if isinstance(names, params.Depends):
names = await self.lister.func() names = await lister.func()
_logger.debug("filter %s from %s", repr(prefix), repr(names)) _logger.debug("filter %s from %s", repr(prefix), repr(names))
return [item for item in names if item.lower().startswith(prefix.lower())] return [item for item in names if item.lower().startswith(prefix.lower())]
object.__setattr__( async def _getter_fn(
self, "filter", Dependable(func=_filter, responses=_RESPONSE_OK)
)
async def _getter(
prefix: str, prefix: str,
names: list[str] = Depends(self.filter.func), names: list[str] = Depends(_filter_fn),
) -> str: ) -> str:
if isinstance(names, params.Depends): if isinstance(names, params.Depends):
names = await self.filter.func(prefix) names = await _filter_fn(prefix)
_logger.debug("get %s from %s", repr(prefix), repr(names)) _logger.debug("get %s from %s", repr(prefix), repr(names))
@ -82,11 +72,11 @@ class ListManager:
case _: case _:
raise HTTPException(status_code=status.HTTP_409_CONFLICT) raise HTTPException(status_code=status.HTTP_409_CONFLICT)
object.__setattr__( return cls(
self, lister=lister,
"getter", filter=Dependable(_filter_fn),
Dependable( getter=Dependable(
func=_getter, func=_getter_fn,
responses={ responses={
**_RESPONSE_OK, **_RESPONSE_OK,
status.HTTP_404_NOT_FOUND: { status.HTTP_404_NOT_FOUND: {
@ -101,6 +91,10 @@ class ListManager:
), ),
) )
@classmethod
def from_lister_fn(cls, lister_fn: _Dependable[[], list[str]]) -> Self:
return cls.from_lister(Dependable(lister_fn))
def get_remote_path( def get_remote_path(
path_name: str, path_name: str,
@ -153,23 +147,28 @@ def get_file_lister(
) )
LM_FILE = ListManager( LM_FILE = ListManager.from_lister(
get_file_lister(rp=RP_FILE, re=re.compile(r"[^/]$", flags=re.IGNORECASE)) get_file_lister(rp=RP_FILE, re=re.compile(r"[^/]$", flags=re.IGNORECASE))
) )
LM_IMAGE = ListManager( LM_IMAGE = ListManager.from_lister(
get_file_lister( get_file_lister(
rp=RP_IMAGE, re=re.compile(r"\.(gif|jpe?g|tiff?|png|bmp)$", flags=re.IGNORECASE) rp=RP_IMAGE, re=re.compile(r"\.(gif|jpe?g|tiff?|png|bmp)$", flags=re.IGNORECASE)
) )
) )
LM_TEXT = ListManager( LM_TEXT = ListManager.from_lister(
get_file_lister(rp=RP_TEXT, re=re.compile(r"\.(txt|md)$", flags=re.IGNORECASE)) get_file_lister(rp=RP_TEXT, re=re.compile(r"\.(txt|md)$", flags=re.IGNORECASE))
) )
# async def list_calendar_names() -> list[str]:
# """ async def list_calendar_names() -> list[str]:
# List calendar names """
# """ List calendar names
# return await CalDAV.calendars """
return await CalDAV.calendars
LM_CALENDARS = ListManager.from_lister_fn(list_calendar_names)
# async def list_aggregate_names( # async def list_aggregate_names(
@ -178,4 +177,8 @@ LM_TEXT = ListManager(
# """ # """
# List aggregate calendar names # List aggregate calendar names
# """ # """
# return list(cfg.calendar.aggregates.keys()) # return list(cfg.calendar.aggregates.keys())
# LM_AGGREGATES = ListManager.from_lister_fn(list_aggregate_names)

View file

@ -7,54 +7,50 @@ Router "calendar" provides:
""" """
from logging import getLogger from logging import getLogger
from typing import Iterator
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from ...config import CalendarUIConfig, Config from ...core.caldav import CalDAV, CalEvent
from ...dav_calendar import CalEvent, DavCalendar from ...core.config import CalendarUIConfig, Config, get_config
from ._common import CalendarNameLister, PrefixFinder, PrefixUnique from ._common import LM_CALENDARS
_logger = getLogger(__name__) _logger = getLogger(__name__)
router = APIRouter(prefix="/calendar", tags=["calendar"]) router = APIRouter(prefix="/calendar", tags=["calendar"])
calendar_lister = CalendarNameLister()
calendar_finder = PrefixFinder(calendar_lister)
calendar_unique = PrefixUnique(calendar_finder)
@router.on_event("startup") @router.on_event("startup")
async def start_router() -> None: async def start_router() -> None:
_logger.debug(f"{router.prefix} router starting.") _logger.debug(f"{router.prefix} router starting.")
@router.get("/list", response_model=list[str])
async def list_calendars(
names: Iterator[str] = Depends(calendar_lister),
) -> list[str]:
return list(names)
@router.get("/find/{prefix}", response_model=list[str])
async def find_calendars(
names: Iterator[str] = Depends(calendar_finder),
) -> list[str]:
return list(names)
@router.get("/get/{prefix}", response_model=list[CalEvent])
async def get_calendar(
name: str = Depends(calendar_unique),
) -> list[CalEvent]:
return list(await DavCalendar(name).events)
@router.get( @router.get(
"/config", "/list",
response_model=CalendarUIConfig, responses=LM_CALENDARS.lister.responses,
) )
async def list_all_calendars(
names: list[str] = Depends(LM_CALENDARS.lister.func),
) -> list[str]:
return names
@router.get("/find/{prefix}")
async def find_calendars(
names: list[str] = Depends(LM_CALENDARS.filter.func),
) -> list[str]:
return names
@router.get("/get/{prefix}")
async def get_calendar(
name: str = Depends(LM_CALENDARS.getter.func),
cfg: Config = Depends(get_config),
) -> list[CalEvent]:
return CalDAV.get_events(name, cfg)
@router.get("/config")
async def get_ui_config( async def get_ui_config(
cfg: Config = Depends(Config.get), cfg: Config = Depends(get_config),
) -> CalendarUIConfig: ) -> CalendarUIConfig:
return cfg.calendar return cfg.calendar