From d27d952d389ba0747ea54102672dd17f8cab8ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Fri, 8 Sep 2023 15:30:52 +0000 Subject: [PATCH] async context manager for WebDAV.read_buffer --- api/advent22_api/core/webdav.py | 21 +++++++------ api/asynccontextmanager.py | 52 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 api/asynccontextmanager.py diff --git a/api/advent22_api/core/webdav.py b/api/advent22_api/core/webdav.py index 0553312..66d1e20 100644 --- a/api/advent22_api/core/webdav.py +++ b/api/advent22_api/core/webdav.py @@ -1,7 +1,7 @@ import re -from contextlib import contextmanager +from contextlib import asynccontextmanager from io import BytesIO, TextIOWrapper -from typing import ContextManager, Iterator +from typing import AsyncContextManager, AsyncIterator from cache import AsyncTTL from webdav3.client import Client as WebDAVclient @@ -44,18 +44,21 @@ class WebDAV: return cls._webdav_client.check(path) - @AsyncTTL(time_to_live=SETTINGS.cache_ttl) @classmethod - async def read_buffer(cls, path: str) -> ContextManager[BytesIO]: + async def read_buffer(cls, path: str) -> AsyncContextManager[BytesIO]: """ Datei aus Pfad `path` in einen `BytesIO` Puffer laden """ - buffer = BytesIO() - cls._webdav_client.resource(path).write_to(buffer) + @AsyncTTL(time_to_live=SETTINGS.cache_ttl) + async def inner() -> BytesIO: + buffer = BytesIO() + cls._webdav_client.resource(path).write_to(buffer) + return buffer - @contextmanager - def ctx() -> Iterator[BytesIO]: + @asynccontextmanager + async def ctx() -> AsyncIterator[BytesIO]: + buffer = await inner() buffer.seek(0) yield buffer @@ -68,7 +71,7 @@ class WebDAV: Datei aus Pfad `path` als string zurückgeben """ - with await cls.read_buffer(path) as buffer: + async with await cls.read_buffer(path) as buffer: tio = TextIOWrapper(buffer, encoding=encoding) tio.seek(0) diff --git a/api/asynccontextmanager.py b/api/asynccontextmanager.py new file mode 100644 index 0000000..fba5832 --- /dev/null +++ b/api/asynccontextmanager.py @@ -0,0 +1,52 @@ +import asyncio +import functools +from contextlib import asynccontextmanager, contextmanager +from io import BytesIO +from typing import AsyncContextManager, AsyncIterator, ContextManager, Iterator + + +def get_buf_sync() -> ContextManager[BytesIO]: + @functools.lru_cache + def inner() -> BytesIO: + with open(__file__, "rb") as file: + return BytesIO(file.readline()) + + @contextmanager + def ctx() -> Iterator[BytesIO]: + buf = inner() + buf.seek(0) + yield buf + + return ctx() + + +def main_sync() -> None: + for _ in range(2): + with get_buf_sync() as buffer: + print(buffer.read()) + + +async def get_buf_async() -> AsyncContextManager[BytesIO]: + @functools.lru_cache + async def inner() -> BytesIO: + with open(__file__, "rb") as file: + return BytesIO(file.readline()) + + @asynccontextmanager + async def ctx() -> AsyncIterator[BytesIO]: + buf = await inner() + buf.seek(0) + yield buf + + return ctx() + + +async def main_async() -> None: + for _ in range(2): + async with await get_buf_async() as buffer: + print(buffer.read()) + + +if __name__ == "__main__": + main_sync() + asyncio.run(main_async())