107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SCHEMAS = ROOT / "schemas"
|
|
TEMPLATES = ROOT / "templates"
|
|
EXAMPLE_CARD = ROOT / "examples" / "card"
|
|
EXAMPLE_SERIES = ROOT / "examples" / "series" / "series.json"
|
|
|
|
|
|
def load_json(path: Path) -> dict:
|
|
with path.open(encoding="utf-8") as stream:
|
|
value = json.load(stream)
|
|
if not isinstance(value, dict):
|
|
raise AssertionError(f"{path}: korzeń JSON musi być obiektem")
|
|
return value
|
|
|
|
|
|
def check_json_files() -> None:
|
|
for path in sorted(SCHEMAS.glob("*.json")):
|
|
schema = load_json(path)
|
|
assert schema.get("$schema", "").endswith("2020-12/schema"), path
|
|
|
|
for path in sorted(TEMPLATES.glob("*.json")):
|
|
template = load_json(path)
|
|
assert template.get("schema") == "esc-card-template.v1", path
|
|
assert template.get("emitters", {}).get("latex"), path
|
|
assert template.get("emitters", {}).get("html"), path
|
|
|
|
card = load_json(EXAMPLE_CARD / "json" / "card_source.json")
|
|
assert card.get("schema") == "esc-card-source.v1"
|
|
assert card.get("sections")
|
|
assert card.get("educational_requirements")
|
|
|
|
series = load_json(EXAMPLE_SERIES)
|
|
assert series.get("version") == 1
|
|
assert series.get("cards")
|
|
|
|
|
|
def check_optional_json_schema() -> None:
|
|
try:
|
|
import jsonschema
|
|
except ModuleNotFoundError:
|
|
if os.environ.get("CARD_LAYOUTS_REQUIRE_JSONSCHEMA") == "1":
|
|
raise AssertionError("brak pakietu jsonschema wymaganego przez pełną kontrolę")
|
|
print("INFO: jsonschema nie jest zainstalowany; wykonuję walidację generatora.")
|
|
return
|
|
|
|
pairs = [
|
|
(SCHEMAS / "card-source.schema.json", EXAMPLE_CARD / "json" / "card_source.json"),
|
|
(SCHEMAS / "series.schema.json", EXAMPLE_SERIES),
|
|
]
|
|
pairs.extend(
|
|
(SCHEMAS / "card-template.schema.json", path)
|
|
for path in sorted(TEMPLATES.glob("*.json"))
|
|
)
|
|
for schema_path, document_path in pairs:
|
|
jsonschema.Draft202012Validator(load_json(schema_path)).validate(load_json(document_path))
|
|
|
|
|
|
def check_render() -> None:
|
|
subprocess.run(
|
|
[sys.executable, str(ROOT / "tools" / "render_card.py"), str(EXAMPLE_CARD)],
|
|
cwd=ROOT,
|
|
check=True,
|
|
)
|
|
|
|
tex_path = EXAMPLE_CARD / "build" / "tex" / "main.tex"
|
|
html_path = EXAMPLE_CARD / "build" / "html" / "index.html"
|
|
css_path = EXAMPLE_CARD / "build" / "html" / "style.css"
|
|
for path in (tex_path, html_path, css_path):
|
|
if not path.is_file() or path.stat().st_size == 0:
|
|
raise AssertionError(f"brak wygenerowanego pliku: {path}")
|
|
|
|
tex = tex_path.read_text(encoding="utf-8")
|
|
html = html_path.read_text(encoding="utf-8")
|
|
for marker in ("DEMO-01", "IP WO", "INF04", "KARTA PRACY"):
|
|
if marker not in tex:
|
|
raise AssertionError(f"TeX nie zawiera znacznika {marker!r}")
|
|
if marker not in html:
|
|
raise AssertionError(f"HTML nie zawiera znacznika {marker!r}")
|
|
|
|
if r"\qrcode[height=" not in tex:
|
|
raise AssertionError("TeX nie zawiera kodu QR z tabliczki")
|
|
for marker in ('class="title-qr"', 'class="code-subblock"'):
|
|
if marker not in html:
|
|
raise AssertionError(f"HTML nie zawiera znacznika {marker!r}")
|
|
|
|
|
|
def main() -> int:
|
|
check_json_files()
|
|
check_optional_json_schema()
|
|
check_render()
|
|
print("PASS: schematy, layouty, przykład serii oraz render TeX/HTML są spójne.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|