52 lines
1.5 KiB
Python
52 lines
1.5 KiB
Python
|
|
"""Persistent sandbox status store (JSON file)."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
from datetime import UTC, datetime
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from sandboxer.models import SandboxStatus
|
||
|
|
|
||
|
|
|
||
|
|
def _default_store_path() -> Path:
|
||
|
|
base = Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local" / "share"))
|
||
|
|
return base / "sandboxer" / "sandboxes.json"
|
||
|
|
|
||
|
|
|
||
|
|
class SandboxStore:
|
||
|
|
def __init__(self, path: Path | None = None) -> None:
|
||
|
|
self.path = path or _default_store_path()
|
||
|
|
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
|
|
||
|
|
def _read(self) -> dict[str, dict]:
|
||
|
|
if not self.path.exists():
|
||
|
|
return {}
|
||
|
|
return json.loads(self.path.read_text())
|
||
|
|
|
||
|
|
def _write(self, data: dict[str, dict]) -> None:
|
||
|
|
self.path.write_text(json.dumps(data, indent=2, default=str))
|
||
|
|
|
||
|
|
def save(self, status: SandboxStatus) -> None:
|
||
|
|
data = self._read()
|
||
|
|
data[status.sandbox_id] = status.model_dump(mode="json")
|
||
|
|
self._write(data)
|
||
|
|
|
||
|
|
def get(self, sandbox_id: str) -> SandboxStatus | None:
|
||
|
|
raw = self._read().get(sandbox_id)
|
||
|
|
if not raw:
|
||
|
|
return None
|
||
|
|
return SandboxStatus.model_validate(raw)
|
||
|
|
|
||
|
|
def list_all(self) -> list[SandboxStatus]:
|
||
|
|
return [SandboxStatus.model_validate(v) for v in self._read().values()]
|
||
|
|
|
||
|
|
def delete(self, sandbox_id: str) -> None:
|
||
|
|
data = self._read()
|
||
|
|
data.pop(sandbox_id, None)
|
||
|
|
self._write(data)
|
||
|
|
|
||
|
|
|
||
|
|
def utcnow() -> datetime:
|
||
|
|
return datetime.now(UTC)
|