from __future__ import annotations import os from pathlib import Path def disk_usage(path: str) -> dict: usage = os.statvfs(path) total = usage.f_frsize * usage.f_blocks free = usage.f_frsize * usage.f_bavail used = total - free return {"total": total, "used": used, "free": free} def drive_stats(config: dict) -> list[dict]: stats = [] for drive in config.get("drives", []): path = Path(drive["path"]) path.mkdir(parents=True, exist_ok=True) usage = disk_usage(str(path)) stats.append({**drive, **usage}) return stats def find_existing_home(config: dict, title: str) -> str | None: normalized = title.lower() for drive in config.get("drives", []): root = Path(drive["path"]) for folder in ("Movies", "Shows"): base = root / folder if not base.exists(): continue for child in base.iterdir(): if child.is_dir() and child.name.lower().startswith(normalized): return str(root) return None def choose_drive(config: dict, title: str) -> dict: existing = find_existing_home(config, title) if existing: for drive in config.get("drives", []): if drive["path"] == existing: return drive candidates = [] for drive in drive_stats(config): min_free = int(drive.get("min_free_gb", 0)) * 1024**3 if drive["free"] >= min_free: candidates.append(drive) if not candidates: raise RuntimeError("No media drive has the configured minimum free space") return max(candidates, key=lambda d: d["free"])