from __future__ import annotations import shutil from pathlib import Path import anyio class LocalStorageAdapter: def __init__(self, base_path: str) -> None: self.base_path = Path(base_path) async def ensure_base_path(self) -> Path: await anyio.to_thread.run_sync(lambda: self.base_path.mkdir(parents=True, exist_ok=True)) return self.base_path async def check(self) -> dict[str, str]: path = await self.ensure_base_path() is_dir = await anyio.to_thread.run_sync(path.is_dir) if not is_dir: raise NotADirectoryError(str(path)) return {"status": "healthy", "detail": str(path)} async def put_file(self, source_path: str, storage_key: str) -> str: destination = self.base_path / storage_key await anyio.to_thread.run_sync(lambda: destination.parent.mkdir(parents=True, exist_ok=True)) def _copy_if_needed() -> None: if not destination.exists(): shutil.copyfile(source_path, destination) await anyio.to_thread.run_sync(_copy_if_needed) return str(destination) async def resolve_path(self, storage_key: str) -> Path: destination = self.base_path / storage_key exists = await anyio.to_thread.run_sync(destination.exists) if not exists: raise FileNotFoundError(storage_key) return destination async def object_exists(self, storage_key: str) -> bool: destination = self.base_path / storage_key return await anyio.to_thread.run_sync(destination.exists)