ovdashboard/api/ovdashboard_api/core/dav/webdav.py

103 lines
2.7 KiB
Python
Raw Permalink Normal View History

import logging
import re
from io import BytesIO
from asyncify import asyncify
2023-11-09 11:13:48 +00:00
from cachetools import cachedmethod
2023-11-09 11:13:48 +00:00
from ..settings import SETTINGS
2023-11-09 11:16:25 +00:00
from .helpers import REDIS, RedisCache, WebDAVclient, davkey
_logger = logging.getLogger(__name__)
class WebDAV:
2023-11-09 11:13:48 +00:00
_webdav_client = WebDAVclient(
{
"webdav_hostname": SETTINGS.webdav.url,
"webdav_login": SETTINGS.webdav.username,
"webdav_password": SETTINGS.webdav.password,
}
)
2023-11-09 11:13:48 +00:00
_cache = RedisCache(
2023-11-09 11:16:25 +00:00
cache=REDIS,
2023-10-26 20:42:26 +00:00
ttl=SETTINGS.webdav.cache_ttl,
)
2023-10-26 20:42:26 +00:00
@classmethod
@asyncify
2023-11-09 11:16:25 +00:00
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("list_files"))
2023-10-26 20:42:26 +00:00
def list_files(
cls,
directory: str = "",
*,
regex: re.Pattern[str] = re.compile(""),
) -> list[str]:
"""
List files in directory `directory` matching RegEx `regex`
"""
_logger.debug(f"list_files {directory!r}")
2023-10-26 20:42:26 +00:00
ls = cls._webdav_client.list(directory)
2023-10-22 10:49:34 +00:00
return [path for path in ls if regex.search(path)]
@classmethod
2023-10-26 20:42:26 +00:00
@asyncify
2023-11-09 11:16:25 +00:00
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("exists"))
2023-10-26 20:42:26 +00:00
def exists(cls, path: str) -> bool:
"""
`True` iff there is a WebDAV resource at `path`
"""
_logger.debug(f"file_exists {path!r}")
2023-10-26 20:42:26 +00:00
return cls._webdav_client.check(path)
@classmethod
2023-10-26 20:42:26 +00:00
@asyncify
2023-11-09 11:16:25 +00:00
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("read_bytes"))
2023-10-26 20:42:26 +00:00
def read_bytes(cls, path: str) -> bytes:
"""
Load WebDAV file from `path` as bytes
"""
_logger.debug(f"read_bytes {path!r}")
buffer = BytesIO()
2023-10-26 20:42:26 +00:00
cls._webdav_client.download_from(buffer, path)
2023-10-22 10:49:04 +00:00
buffer.seek(0)
return buffer.read()
@classmethod
async def read_str(cls, path: str, encoding="utf-8") -> str:
"""
Load WebDAV file from `path` as string
"""
_logger.debug(f"read_str {path!r}")
return (await cls.read_bytes(path)).decode(encoding=encoding).strip()
@classmethod
2023-10-26 20:42:26 +00:00
@asyncify
def write_bytes(cls, path: str, buffer: bytes) -> None:
"""
Write bytes from `buffer` into WebDAV file at `path`
"""
_logger.debug(f"write_bytes {path!r}")
2023-10-26 20:42:26 +00:00
cls._webdav_client.upload_to(buffer, path)
2023-10-26 20:42:26 +00:00
# invalidate cache entry
# explicit slice as there is no "cls" argument
del cls._cache[davkey("read_bytes", slice(0, None))(path)]
@classmethod
async def write_str(cls, path: str, content: str, encoding="utf-8") -> None:
"""
Write string from `content` into WebDAV file at `path`
"""
_logger.debug(f"write_str {path!r}")
await cls.write_bytes(path, content.encode(encoding=encoding))