_fix_toc_and_numbering.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. # -*- coding: utf-8 -*-
  2. """补章节编号缺口,并用 Word 刷新带页码的目录。"""
  3. from __future__ import annotations
  4. import hashlib
  5. import sys
  6. import tempfile
  7. import time
  8. from pathlib import Path
  9. HERE = Path(__file__).resolve().parent
  10. if str(HERE) not in sys.path:
  11. sys.path.insert(0, str(HERE))
  12. from _delivery_docx_polish import latest_formal_files, polish_file
  13. from _unify_ab_delivery_vnext import BASE
  14. TMP = Path(tempfile.gettempdir()) / "aidop_toc_word"
  15. WD_COLOR_BLACK = 0
  16. WD_STAT_PAGES = 2
  17. def refresh_one(src: Path) -> str:
  18. import subprocess
  19. worker = HERE / "_word_toc_one.py"
  20. last = ""
  21. timeout = 240 if src.stat().st_size < 8_000_000 else 600
  22. for attempt in range(3):
  23. proc = subprocess.run(
  24. [sys.executable, str(worker), str(src)],
  25. capture_output=True,
  26. text=True,
  27. timeout=timeout,
  28. check=False,
  29. )
  30. out = (proc.stdout or "").strip()
  31. err = (proc.stderr or "").strip()
  32. if proc.returncode == 0 and out:
  33. return out
  34. last = err or out or f"exit {proc.returncode}"
  35. time.sleep(2 + attempt * 2)
  36. raise RuntimeError(last)
  37. def main() -> None:
  38. files = latest_formal_files(BASE)
  39. flags = {x for x in sys.argv[1:] if x.startswith("-")}
  40. only = [x for x in sys.argv[1:] if not x.startswith("-")]
  41. if only:
  42. files = [p for p in files if any(k in p.name or k in str(p) for k in only)]
  43. files = sorted(files, key=lambda p: p.stat().st_size)
  44. if "--refresh-only" not in flags:
  45. print("prepare", len(files), flush=True)
  46. for p in files:
  47. try:
  48. print(polish_file(p), flush=True)
  49. except Exception as exc:
  50. print(f"FAIL prepare {p.parent.name}/{p.name}: {exc}", flush=True)
  51. print("word-refresh", len(files), flush=True)
  52. for p in files:
  53. t0 = time.time()
  54. try:
  55. msg = refresh_one(p)
  56. print(f"OK {p.parent.name}/{p.name} {msg} {time.time()-t0:.0f}s", flush=True)
  57. except Exception as exc:
  58. print(f"FAIL word {p.parent.name}/{p.name}: {exc}", flush=True)
  59. if __name__ == "__main__":
  60. main()