Files
qwen21-nsfw-pose-skill/scripts/validate_package.py
T
Arekejoker 8f3242ff64 chore: rename placeholder pose '1'; validate README image files are non-empty
The curated pose shipped as '1' with no tags; rename it to a
descriptive name (Laying Back on Elbows) and add browse tags. Also
extend validate_package.py to reject empty README-referenced images,
matching the existing non-empty check for pose previews.
2026-10-15 16:25:06 +08:00

81 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""Offline integrity checks for the shareable Qwen-Image pose package."""
from __future__ import annotations
import ast
import json
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
errors: list[str] = []
def check(condition: bool, message: str) -> None:
if not condition:
errors.append(message)
python_files = sorted((ROOT / "scripts").glob("*.py"))
for path in python_files:
try:
ast.parse(path.read_text(encoding="utf-8"), filename=str(path.relative_to(ROOT)))
except (SyntaxError, UnicodeDecodeError) as exc:
errors.append(f"Python syntax error in {path.relative_to(ROOT)}: {exc}")
json_dirs = (
ROOT / "workflows",
ROOT / "prompts",
ROOT / "downloads" / "samples",
ROOT / "pose_library" / "local_user_poses",
)
json_files = sorted(path for directory in json_dirs for path in directory.rglob("*.json"))
for path in json_files:
try:
json.loads(path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, UnicodeDecodeError) as exc:
errors.append(f"Invalid JSON in {path.relative_to(ROOT)}: {exc}")
pose_dir = ROOT / "pose_library" / "local_user_poses" / "Uncategorized"
pose_jsons = sorted(pose_dir.glob("*.json"))
pose_previews = sorted(pose_dir.glob("*.webp"))
check(len(pose_jsons) == 55, f"expected 55 curated pose JSONs, found {len(pose_jsons)}")
check(len(pose_previews) == 55, f"expected 55 pose previews, found {len(pose_previews)}")
for path in pose_jsons:
check(path.with_suffix(".webp").is_file(), f"missing pose preview for {path.name}")
for path in pose_previews:
check(path.with_suffix(".json").is_file(), f"missing pose JSON for {path.name}")
check(path.stat().st_size > 0, f"empty pose preview file: {path.name}")
readme = ROOT / "README.md"
check(readme.is_file(), "missing README.md")
image_paths: list[str] = []
if readme.is_file():
image_paths = re.findall(r'<img\s+[^>]*src="([^"]+)"', readme.read_text(encoding="utf-8"))
check(bool(image_paths), "README.md has no embedded showcase images")
for image_path in image_paths:
local_path = image_path.split("?", 1)[0] # strip cache-busting query
target = ROOT / local_path
check(target.is_file(), f"README image does not exist: {local_path}")
if target.is_file():
check(target.stat().st_size > 0, f"empty README image: {local_path}")
for relative in (
"SKILL.md",
"install/setup.md",
"references/src_standing.png",
"downloads/samples/phase5_meta.json",
):
check((ROOT / relative).is_file(), f"missing required package file: {relative}")
if errors:
for error in errors:
print(f"FAIL: {error}", file=sys.stderr)
raise SystemExit(1)
print(
f"OK: {len(python_files)} Python files, {len(json_files)} JSON files, "
f"{len(pose_jsons)} pose JSON/preview pairs, {len(image_paths)} README images"
)