2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
Definition of an asyncio compatible WebDAV file.
|
|
|
|
|
|
|
|
Caches files using `timed_alru_cache`.
|
|
|
|
"""
|
|
|
|
|
2022-09-04 14:14:22 +00:00
|
|
|
from dataclasses import dataclass
|
2022-08-29 11:27:18 +00:00
|
|
|
from io import BytesIO
|
2022-09-07 00:29:32 +00:00
|
|
|
from logging import getLogger
|
2022-09-04 17:12:01 +00:00
|
|
|
from typing import Any
|
2022-08-29 11:27:18 +00:00
|
|
|
|
2022-08-31 08:42:17 +00:00
|
|
|
from webdav3.client import Resource
|
2022-08-29 11:27:18 +00:00
|
|
|
|
2022-09-04 22:30:40 +00:00
|
|
|
from .async_helpers import get_ttl_hash, run_in_executor, timed_alru_cache
|
|
|
|
from .dav_common import webdav_resource
|
2022-09-04 23:41:51 +00:00
|
|
|
from .settings import SETTINGS
|
2022-09-02 12:20:29 +00:00
|
|
|
|
2022-09-07 00:29:32 +00:00
|
|
|
_logger = getLogger(__name__)
|
2022-08-29 11:27:18 +00:00
|
|
|
|
|
|
|
|
2022-09-06 07:54:44 +00:00
|
|
|
@timed_alru_cache(maxsize=SETTINGS.cache_size)
|
2022-09-02 12:20:29 +00:00
|
|
|
async def _get_buffer(
|
|
|
|
remote_path: Any,
|
|
|
|
) -> BytesIO:
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
Download file contents into a new `BytesIO` object.
|
|
|
|
"""
|
2022-09-04 17:29:11 +00:00
|
|
|
|
2022-09-03 15:40:46 +00:00
|
|
|
@run_in_executor
|
2022-09-05 12:58:00 +00:00
|
|
|
def _inner() -> BytesIO:
|
2022-09-06 22:55:23 +00:00
|
|
|
_logger.info(f"downloading {remote_path!r} ...")
|
2022-09-05 12:58:00 +00:00
|
|
|
|
|
|
|
resource = webdav_resource(remote_path)
|
2022-09-02 12:20:29 +00:00
|
|
|
buffer = BytesIO()
|
|
|
|
resource.write_to(buffer)
|
|
|
|
return buffer
|
|
|
|
|
2022-09-05 12:58:00 +00:00
|
|
|
return await _inner()
|
2022-09-02 12:20:29 +00:00
|
|
|
|
|
|
|
|
2022-09-04 14:14:22 +00:00
|
|
|
@dataclass(frozen=True)
|
2022-08-29 11:27:18 +00:00
|
|
|
class DavFile:
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
Object representation of a WebDAV file.
|
|
|
|
"""
|
|
|
|
|
2022-09-04 14:14:22 +00:00
|
|
|
remote_path: str
|
2022-09-02 12:20:29 +00:00
|
|
|
|
2022-09-05 12:54:02 +00:00
|
|
|
@property
|
|
|
|
def resource(self) -> Resource:
|
|
|
|
"""
|
|
|
|
WebDAV file handle.
|
|
|
|
"""
|
|
|
|
|
|
|
|
return webdav_resource(self.remote_path)
|
|
|
|
|
2022-09-02 12:20:29 +00:00
|
|
|
@property
|
|
|
|
async def __buffer(self) -> BytesIO:
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
File contents as binary stream.
|
|
|
|
"""
|
|
|
|
|
2022-09-02 12:20:29 +00:00
|
|
|
return await _get_buffer(
|
2022-09-08 00:24:36 +00:00
|
|
|
ttl_hash=get_ttl_hash(), # type: ignore
|
2022-09-04 14:14:22 +00:00
|
|
|
remote_path=self.remote_path,
|
2022-08-31 01:29:44 +00:00
|
|
|
)
|
2022-08-29 11:27:18 +00:00
|
|
|
|
|
|
|
@property
|
2022-09-08 00:24:36 +00:00
|
|
|
async def as_bytes(self) -> bytes:
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
File contents as binary data.
|
|
|
|
"""
|
|
|
|
|
2022-09-02 12:20:29 +00:00
|
|
|
buffer = await self.__buffer
|
|
|
|
|
|
|
|
buffer.seek(0)
|
|
|
|
return buffer.read()
|
2022-08-29 11:27:18 +00:00
|
|
|
|
2022-09-02 12:20:29 +00:00
|
|
|
@property
|
2022-09-08 00:24:36 +00:00
|
|
|
async def as_string(self) -> str:
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
File contents as string.
|
|
|
|
"""
|
|
|
|
|
2022-09-08 00:24:36 +00:00
|
|
|
bytes = await self.as_bytes
|
2022-09-02 12:20:29 +00:00
|
|
|
return bytes.decode(encoding="utf-8")
|
2022-09-04 23:40:56 +00:00
|
|
|
|
2022-09-06 22:55:23 +00:00
|
|
|
async def write(self, content: bytes) -> None:
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
Write bytes into file.
|
|
|
|
"""
|
|
|
|
|
2022-09-04 23:40:56 +00:00
|
|
|
@run_in_executor
|
|
|
|
def _inner() -> None:
|
|
|
|
buffer = BytesIO(content)
|
|
|
|
self.resource.read_from(buffer)
|
|
|
|
|
|
|
|
await _inner()
|