Improve controller behavior and update project requirements
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
"""Regenerable BLE library previews, isolated from user-owned media."""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import re
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from app.persistence import atomic_write_bytes
|
||||
|
||||
|
||||
_PREVIEW_FILE = re.compile(r"[0-9a-f]{64}\.png\Z")
|
||||
|
||||
|
||||
class PreviewCache:
|
||||
def __init__(self, data_dir: Path):
|
||||
self.root = Path(data_dir) / "mobile" / "previews"
|
||||
self.root.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@staticmethod
|
||||
def name(item: dict) -> str:
|
||||
identity = "\0".join(str(item[key]) for key in ("type", "id", "revision"))
|
||||
return hashlib.sha256(identity.encode("utf-8")).hexdigest() + ".png"
|
||||
|
||||
def reconcile(self, items: list[dict]) -> None:
|
||||
expected = {self.name(item) for item in items}
|
||||
for path in self.root.iterdir():
|
||||
if path.is_file() and _PREVIEW_FILE.fullmatch(path.name) and path.name not in expected:
|
||||
path.unlink(missing_ok=True)
|
||||
|
||||
def get(self, item: dict, image: Image.Image) -> bytes:
|
||||
path = self.root / self.name(item)
|
||||
if path.exists():
|
||||
try:
|
||||
data = path.read_bytes()
|
||||
with Image.open(BytesIO(data)) as cached:
|
||||
cached.verify()
|
||||
if cached.format == "PNG" and cached.size == (16, 16):
|
||||
return data
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
output = BytesIO()
|
||||
image.convert("RGB").resize((16, 16), Image.Resampling.LANCZOS).save(output, format="PNG", optimize=True)
|
||||
data = output.getvalue()
|
||||
atomic_write_bytes(path, data)
|
||||
return data
|
||||
Reference in New Issue
Block a user