validate_phrases.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. #!/usr/bin/env python3
  2. """词库自检:JSON 合法 / 正则能编译 / 占位符与命名组一一对应 / 候选条数。
  3. 用法:python3 validate_phrases.py [phrases.json]
  4. 每次改完词库都跑一遍——占位符写错(候选用 {n} 而正则组叫 code)不会报错,
  5. 只会在运行时把 {n} 字面量发给用户,肉眼很难发现。
  6. """
  7. import json, re, sys, pathlib
  8. path = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else "phrases.json")
  9. data = json.loads(path.read_text(encoding="utf-8"))
  10. cats = data.get("categories", [])
  11. problems, total, minv = [], 0, 10 ** 9
  12. for c in cats:
  13. cid = c.get("id", "?")
  14. groups = set()
  15. for pat in c.get("patterns", []):
  16. try:
  17. groups |= set(re.compile(pat, re.IGNORECASE).groupindex)
  18. except re.error as exc:
  19. problems.append(f"{cid}: 正则编译失败 {pat!r} -> {exc}")
  20. variants = c.get("variants") or []
  21. total += len(variants)
  22. minv = min(minv, len(variants))
  23. for v in variants:
  24. missing = set(re.findall(r"\{(\w+)\}", v)) - groups
  25. if missing:
  26. problems.append(f"{cid}: 候选用了 {sorted(missing)},正则里没有这些组({sorted(groups)})")
  27. if not c.get("patterns"):
  28. problems.append(f"{cid}: 没有 patterns")
  29. if not variants:
  30. problems.append(f"{cid}: 没有 variants")
  31. print(f"类别 {len(cats)} | 候选 {total} | 最少的一类 {minv} 条")
  32. if problems:
  33. print(f"\n✗ 发现 {len(problems)} 个问题:")
  34. for p in problems:
  35. print(" -", p)
  36. sys.exit(1)
  37. print("✓ 全部通过")