65 lines
2.1 KiB
Python
65 lines
2.1 KiB
Python
"""Version only thumbnails that use a bundled font; preserve scene revisions."""
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from app.persistence import atomic_write_bytes
|
|
|
|
STAMP_SUFFIX = ".font-version"
|
|
|
|
|
|
def scene_font_version(scene: dict, resolver) -> str | None:
|
|
owner = getattr(resolver, "__self__", None)
|
|
version_for = getattr(owner, "render_version", None)
|
|
if version_for is None:
|
|
return None
|
|
elements = scene.get("elements", []) if scene.get("version") == 1 else [
|
|
element for layer in scene.get("layers", []) if layer.get("type") == "text"
|
|
for element in layer.get("elements", [])
|
|
]
|
|
versions = sorted({version for element in elements
|
|
if (version := version_for(element.get("font", "default")))})
|
|
if not versions:
|
|
return None
|
|
return hashlib.sha256(json.dumps(versions, separators=(",", ":")).encode("ascii")).hexdigest()[:16]
|
|
|
|
|
|
def stamp_path(path: Path) -> Path:
|
|
return path.with_name(path.name + STAMP_SUFFIX)
|
|
|
|
|
|
def cache_stale(path: Path, scene: dict, resolver) -> bool:
|
|
version = scene_font_version(scene, resolver)
|
|
if version is None:
|
|
return False
|
|
try:
|
|
return stamp_path(path).read_text(encoding="ascii").strip() != version
|
|
except (OSError, UnicodeError):
|
|
return True
|
|
|
|
|
|
def stamp_cache(path: Path, scene: dict, resolver) -> None:
|
|
version = scene_font_version(scene, resolver)
|
|
stamp = stamp_path(path)
|
|
if version is not None:
|
|
atomic_write_bytes(stamp, (version + "\n").encode("ascii"))
|
|
else:
|
|
stamp.unlink(missing_ok=True)
|
|
|
|
|
|
def versioned_url(url: str, scene: dict, resolver) -> str:
|
|
version = scene_font_version(scene, resolver)
|
|
return url + f"&font_v={version}" if version else url
|
|
|
|
|
|
def cached_versioned_url(url: str, path: Path) -> str:
|
|
try:
|
|
version = stamp_path(path).read_text(encoding="ascii").strip()
|
|
except (OSError, UnicodeError):
|
|
return url
|
|
if len(version) == 16 and all(ch in "0123456789abcdef" for ch in version):
|
|
return url + f"&font_v={version}"
|
|
return url
|