From 6709284ed9432f89d0a212c6068adb88e90f78c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Mon, 16 Oct 2023 20:06:55 +0200 Subject: [PATCH] py3.11: fix basic linter errors --- api/ovdashboard_api/__init__.py | 13 ++--- api/ovdashboard_api/app.py | 54 +++++++++----------- api/ovdashboard_api/config.py | 6 +-- api/ovdashboard_api/dav_calendar.py | 26 +++------- api/ovdashboard_api/{__main__.py => main.py} | 2 +- api/ovdashboard_api/settings.py | 3 +- 6 files changed, 43 insertions(+), 61 deletions(-) rename api/ovdashboard_api/{__main__.py => main.py} (89%) diff --git a/api/ovdashboard_api/__init__.py b/api/ovdashboard_api/__init__.py index fcdec95..eceaae6 100644 --- a/api/ovdashboard_api/__init__.py +++ b/api/ovdashboard_api/__init__.py @@ -9,11 +9,8 @@ from logging.config import dictConfig from pydantic import BaseModel -from .app import app from .settings import SETTINGS -__all__ = ["app"] - class LogConfig(BaseModel): """ @@ -22,23 +19,23 @@ class LogConfig(BaseModel): """ # Logging config - version = 1 - disable_existing_loggers = False - formatters = { + version: int = 1 + disable_existing_loggers: bool = False + formatters: dict = { "default": { "()": "uvicorn.logging.DefaultFormatter", "fmt": "%(levelprefix)s [%(asctime)s] %(name)s: %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S", }, } - handlers = { + handlers: dict = { "default": { "formatter": "default", "class": "logging.StreamHandler", "stream": "ext://sys.stderr", }, } - loggers = { + loggers: dict = { "ovdashboard_api": { "handlers": ["default"], "level": SETTINGS.log_level, diff --git a/api/ovdashboard_api/app.py b/api/ovdashboard_api/app.py index 8e8264f..74db30e 100644 --- a/api/ovdashboard_api/app.py +++ b/api/ovdashboard_api/app.py @@ -30,33 +30,29 @@ app = FastAPI( redoc_url=SETTINGS.redoc_url, ) -app.add_event_handler("startup", webdav_check) - - -@app.on_event("startup") -async def add_middlewares() -> None: - if SETTINGS.production_mode: - # Mount frontend in production mode - app.mount( - path="/", - app=StaticFiles( - directory=SETTINGS.ui_directory, - html=True, - ), - name="frontend", - ) - - else: - # Allow CORS in debug mode - app.add_middleware( - CORSMiddleware, - allow_origins=[ - "*", - ], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - expose_headers=["*"], - ) - app.include_router(v1_router) +webdav_check() + +if SETTINGS.production_mode: + # Mount frontend in production mode + app.mount( + path="/", + app=StaticFiles( + directory=SETTINGS.ui_directory, + html=True, + ), + name="frontend", + ) + +else: + # Allow CORS in debug mode + app.add_middleware( + CORSMiddleware, + allow_origins=[ + "*", + ], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + expose_headers=["*"], + ) diff --git a/api/ovdashboard_api/config.py b/api/ovdashboard_api/config.py index 6093806..35eb98b 100644 --- a/api/ovdashboard_api/config.py +++ b/api/ovdashboard_api/config.py @@ -4,10 +4,10 @@ Python representation of the "config.txt" file inside the WebDAV directory. from io import BytesIO from logging import getLogger +from tomllib import loads as toml_loads from typing import Any from pydantic import BaseModel -from tomli import loads as toml_loads from tomli_w import dump as toml_dump from webdav3.exceptions import RemoteResourceNotFound @@ -119,9 +119,7 @@ class Config(BaseModel): dav_file = DavFile(SETTINGS.config_path) try: - cfg = cls.parse_obj( - toml_loads(await dav_file.as_string) - ) + cfg = cls.parse_obj(toml_loads(await dav_file.as_string)) except RemoteResourceNotFound: _logger.warning( diff --git a/api/ovdashboard_api/dav_calendar.py b/api/ovdashboard_api/dav_calendar.py index a5f4683..e3f2eda 100644 --- a/api/ovdashboard_api/dav_calendar.py +++ b/api/ovdashboard_api/dav_calendar.py @@ -8,12 +8,12 @@ from dataclasses import dataclass from datetime import datetime, timedelta from functools import total_ordering from logging import getLogger -from typing import Iterator +from typing import Annotated, Iterator from cache import AsyncTTL from caldav import Calendar from caldav.lib.error import ReportError -from pydantic import BaseModel, validator +from pydantic import AfterValidator, BaseModel from vobject.base import Component from .async_helpers import run_in_executor @@ -33,6 +33,9 @@ def _string_strip(in_str: str) -> str: return in_str.strip() +StrippedStr = Annotated[str, AfterValidator(lambda s: s.strip())] + + @total_ordering class CalEvent(BaseModel): """ @@ -44,8 +47,8 @@ class CalEvent(BaseModel): https://icalendar.org/iCalendar-RFC-5545/3-6-1-event-component.html """ - summary: str = "" - description: str = "" + summary: StrippedStr = "" + description: StrippedStr = "" dtstart: datetime = datetime.utcnow() dtend: datetime = datetime.utcnow() @@ -66,16 +69,6 @@ class CalEvent(BaseModel): return self.dict() == other.dict() - _validate_summary = validator( - "summary", - allow_reuse=True, - )(_string_strip) - - _validate_description = validator( - "description", - allow_reuse=True, - )(_string_strip) - @classmethod def from_vevent(cls, event: Component) -> "CalEvent": """ @@ -178,10 +171,7 @@ async def _get_calendar_events( vobject: Component = event.vobject_instance # type: ignore yield from vobject.vevent_list - return sorted([ - CalEvent.from_vevent(vevent) - for vevent in await _inner() - ]) + return sorted([CalEvent.from_vevent(vevent) for vevent in await _inner()]) @dataclass(frozen=True) diff --git a/api/ovdashboard_api/__main__.py b/api/ovdashboard_api/main.py similarity index 89% rename from api/ovdashboard_api/__main__.py rename to api/ovdashboard_api/main.py index 68ad6bf..5413937 100644 --- a/api/ovdashboard_api/__main__.py +++ b/api/ovdashboard_api/main.py @@ -9,7 +9,7 @@ def main() -> None: """ uvicorn_run( - app="ovdashboard_api:app", + app="ovdashboard_api.app:app", host="0.0.0.0", port=8000, reload=not SETTINGS.production_mode, diff --git a/api/ovdashboard_api/settings.py b/api/ovdashboard_api/settings.py index 747430a..2a39141 100644 --- a/api/ovdashboard_api/settings.py +++ b/api/ovdashboard_api/settings.py @@ -9,7 +9,8 @@ Pydantic models might have convenience methods attached. from typing import Any, Optional -from pydantic import BaseModel, BaseSettings, root_validator +from pydantic import BaseModel, root_validator +from pydantic_settings import BaseSettings class DavSettings(BaseModel):