From cdf4ce4d162a07e172dfffe2e7d858c5549a9f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <40151420+ldericher@users.noreply.github.com> Date: Thu, 26 Oct 2023 17:46:12 +0200 Subject: [PATCH] refac: fix calendar router --- api/ovdashboard_api/core/caldav.py | 4 +- api/ovdashboard_api/routers/v1/__init__.py | 4 +- api/ovdashboard_api/routers/v1/_common.py | 75 +++++++++++----------- api/ovdashboard_api/routers/v1/calendar.py | 60 ++++++++--------- 4 files changed, 71 insertions(+), 72 deletions(-) diff --git a/api/ovdashboard_api/core/caldav.py b/api/ovdashboard_api/core/caldav.py index 7b24072..8b62093 100644 --- a/api/ovdashboard_api/core/caldav.py +++ b/api/ovdashboard_api/core/caldav.py @@ -21,8 +21,8 @@ class CalDAV: password=SETTINGS.caldav.password, ) - @property @classmethod + @property def principal(cls) -> Principal: """ Gets the `Principal` object of the main CalDAV client. @@ -31,6 +31,7 @@ class CalDAV: _logger.debug("principal") return cls._caldav_client.principal() + @classmethod @property @AsyncTTL( time_to_live=SETTINGS.caldav.cache_ttl, @@ -38,7 +39,6 @@ class CalDAV: skip_args=1, ) @asyncify - @classmethod def calendars(cls) -> list[str]: """ Asynchroneously lists all calendars using the main WebDAV client. diff --git a/api/ovdashboard_api/routers/v1/__init__.py b/api/ovdashboard_api/routers/v1/__init__.py index 5e1ae55..d56e629 100644 --- a/api/ovdashboard_api/routers/v1/__init__.py +++ b/api/ovdashboard_api/routers/v1/__init__.py @@ -7,7 +7,7 @@ This file: Main API router definition. from fastapi import APIRouter # 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") @@ -18,7 +18,7 @@ router.include_router(ticker.router) router.include_router(image.router) router.include_router(file.router) -# router.include_router(calendar.router) +router.include_router(calendar.router) # router.include_router(aggregate.router) __all__ = ["router"] diff --git a/api/ovdashboard_api/routers/v1/_common.py b/api/ovdashboard_api/routers/v1/_common.py index 5bc673c..79046d5 100644 --- a/api/ovdashboard_api/routers/v1/_common.py +++ b/api/ovdashboard_api/routers/v1/_common.py @@ -3,19 +3,17 @@ Dependables for defining Routers. """ import re -from dataclasses import dataclass +from dataclasses import dataclass, field 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 webdav3.exceptions import RemoteResourceNotFound +from ...core.caldav import CalDAV from ...core.config import get_config from ...core.webdav import WebDAV -# from ...core.caldav import CalDAV -# from ...core.config import Config, get_config - _logger = getLogger(__name__) _RESPONSE_OK = { @@ -33,42 +31,34 @@ type _Dependable[**Params, Return] = Callable[Params, Awaitable[Return]] @dataclass(slots=True, frozen=True) class Dependable(Generic[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: lister: Dependable[[], list[str]] filter: Dependable[[str], list[str]] getter: Dependable[[str], str] - def __init__( - self, - lister: Dependable[[], list[str]], - ) -> None: - object.__setattr__(self, "lister", lister) - - async def _filter( + @classmethod + def from_lister(cls, lister: Dependable[[], list[str]]) -> Self: + async def _filter_fn( prefix: str, - names: list[str] = Depends(self.lister.func), + names: list[str] = Depends(lister.func), ) -> list[str]: if isinstance(names, params.Depends): - names = await self.lister.func() + names = await lister.func() _logger.debug("filter %s from %s", repr(prefix), repr(names)) return [item for item in names if item.lower().startswith(prefix.lower())] - object.__setattr__( - self, "filter", Dependable(func=_filter, responses=_RESPONSE_OK) - ) - - async def _getter( + async def _getter_fn( prefix: str, - names: list[str] = Depends(self.filter.func), + names: list[str] = Depends(_filter_fn), ) -> str: 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)) @@ -82,11 +72,11 @@ class ListManager: case _: raise HTTPException(status_code=status.HTTP_409_CONFLICT) - object.__setattr__( - self, - "getter", - Dependable( - func=_getter, + return cls( + lister=lister, + filter=Dependable(_filter_fn), + getter=Dependable( + func=_getter_fn, responses={ **_RESPONSE_OK, 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( 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)) ) -LM_IMAGE = ListManager( +LM_IMAGE = ListManager.from_lister( get_file_lister( 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)) ) -# async def list_calendar_names() -> list[str]: -# """ -# List calendar names -# """ -# return await CalDAV.calendars + +async def list_calendar_names() -> list[str]: + """ + List calendar names + """ + + return await CalDAV.calendars + + +LM_CALENDARS = ListManager.from_lister_fn(list_calendar_names) # async def list_aggregate_names( @@ -178,4 +177,8 @@ LM_TEXT = ListManager( # """ # List aggregate calendar names # """ + # return list(cfg.calendar.aggregates.keys()) + + +# LM_AGGREGATES = ListManager.from_lister_fn(list_aggregate_names) diff --git a/api/ovdashboard_api/routers/v1/calendar.py b/api/ovdashboard_api/routers/v1/calendar.py index 72328d4..4d1dc92 100644 --- a/api/ovdashboard_api/routers/v1/calendar.py +++ b/api/ovdashboard_api/routers/v1/calendar.py @@ -7,54 +7,50 @@ Router "calendar" provides: """ from logging import getLogger -from typing import Iterator from fastapi import APIRouter, Depends -from ...config import CalendarUIConfig, Config -from ...dav_calendar import CalEvent, DavCalendar -from ._common import CalendarNameLister, PrefixFinder, PrefixUnique +from ...core.caldav import CalDAV, CalEvent +from ...core.config import CalendarUIConfig, Config, get_config +from ._common import LM_CALENDARS _logger = getLogger(__name__) router = APIRouter(prefix="/calendar", tags=["calendar"]) -calendar_lister = CalendarNameLister() -calendar_finder = PrefixFinder(calendar_lister) -calendar_unique = PrefixUnique(calendar_finder) - @router.on_event("startup") async def start_router() -> None: _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( - "/config", - response_model=CalendarUIConfig, + "/list", + 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( - cfg: Config = Depends(Config.get), + cfg: Config = Depends(get_config), ) -> CalendarUIConfig: return cfg.calendar