import re from io import BytesIO from cache import AsyncTTL from cache.key import KEY from webdav3.client import Client as WebDAVclient from .settings import SETTINGS class WebDAV: _webdav_client = WebDAVclient( { "webdav_hostname": SETTINGS.webdav.url, "webdav_login": SETTINGS.webdav.username, "webdav_password": SETTINGS.webdav.password, } ) @classmethod @AsyncTTL(time_to_live=SETTINGS.webdav.cache_ttl, skip_args=1) async def list_files( cls, directory: str = "", *, regex: re.Pattern[str] = re.compile(""), ) -> list[str]: """ Liste aller Dateien im Ordner `directory`, die zur RegEx `regex` passen """ ls = cls._webdav_client.list(directory) return [f"{directory}/{path}" for path in ls if regex.search(path)] @classmethod @AsyncTTL(time_to_live=SETTINGS.webdav.cache_ttl, skip_args=1) async def file_exists(cls, path: str) -> bool: """ `True`, wenn an Pfad `path` eine Datei existiert """ return cls._webdav_client.check(path) @classmethod @(_rb_ttl := AsyncTTL(time_to_live=SETTINGS.webdav.cache_ttl, skip_args=1)) async def read_bytes(cls, path: str) -> bytes: """ Datei aus Pfad `path` als bytes laden """ buffer = BytesIO() cls._webdav_client.resource(path).write_to(buffer) buffer.seek(0) return buffer.read() @classmethod async def read_str(cls, path: str, encoding="utf-8") -> str: """ Datei aus Pfad `path` als string laden """ return (await cls.read_bytes(path)).decode(encoding=encoding).strip() @classmethod async def write_bytes(cls, path: str, buffer: bytes) -> None: """ Bytes `buffer` in Datei in Pfad `path` schreiben """ cls._webdav_client.resource(path).read_from(buffer) # Cache-Eintrag entfernen (hack: siehe AsyncTTL._TTL.__contains__) del cls._rb_ttl.ttl[KEY((path,), {})] @classmethod async def write_str(cls, path: str, content: str, encoding="utf-8") -> None: """ String `content` in Datei in Pfad `path` schreiben """ await cls.write_bytes(path, content.encode(encoding=encoding))