Eureka/tools/bloom-sheet/test_theme.py

52 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""What a theme must be. Run: python3 test_theme.py
Needs python3-markdown-it and python3-numpy (bloom_sheet imports them); no LaTeX."""
import re, sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
from bloom_sheet import FONTS, MARKS, check_markers, fill, page_source
fails = 0
def check(name, ok):
global fails
print(("ok " if ok else "FAIL"), name)
fails += not ok
def refused(name, thunk, reason):
try:
thunk()
check(f"{name}: refused", False)
except SystemExit as e:
check(f"{name}: refused for {reason}", reason in str(e))
def defined(tex):
"""Every macro, font family and colour a page file defines."""
return set(re.findall(r"\\(?:newcommand|DeclareRobustCommand|renewcommand)\{(\\\w+)\}", tex)
+ re.findall(r"\\newfontfamily(\\\w+)", tex)
+ re.findall(r"\\(?:definecolor|colorlet)\{(\w+)\}", tex))
default = page_source(None)
check("default is page.tex, unchanged", default == (HERE / "page.tex").read_text(encoding="utf8"))
themes = sorted((HERE / "themes").glob("*.tex"))
check("at least one theme ships", bool(themes))
for t in themes:
text = page_source(t.stem)
check(f"{t.stem}: markers once (fonts at most once)", all(text.count(m) == 1 for m in MARKS[1:]) and text.count(MARKS[0]) <= 1)
missing = sorted((defined(default) | defined(FONTS)) - defined(text))
check(f"{t.stem}: defines what page.tex does (missing: {missing})", not missing)
good = "@@CONTENTS@@ @@TITLE@@"
check_markers(good, "good.tex")
refused("marker in a comment", lambda: check_markers(good + "\n% fills @@TITLE@@ here", "bad.tex"), "@@TITLE@@ 2 times")
refused("marker missing", lambda: check_markers("@@CONTENTS@@", "bad.tex"), "@@TITLE@@ 0 times")
refused("split marker", lambda: check_markers("@@CONTENTS@@ @@CONT@@TITLE@@ENTS@@", "bad.tex"), "@@CONTENTS@@ split by")
check("fill is one pass", fill("@@CONTENTS@@ @@TITLE@@", {"@@CONTENTS@@": "x@@TITLE@@", "@@TITLE@@": "T"}) == "x@@TITLE@@ T")
refused("unknown theme", lambda: page_source("nope"), "no theme 'nope'")
refused("path as theme", lambda: page_source("../page"), "no theme")
sys.exit(1 if fails else 0)