Personal tex compilation fixes
This commit is contained in:
1 parent
ec6ac9580b
commit
705db1068f
8 files changed
+217
-21
No files matched your search
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import re
|
||||
@@ -1016,24 +1017,35 @@ def write_exam_outputs(workspace: EvaluationWorkspace, grouped_extraction: Group
|
||||
save_missing(path, '\n\n'.join(contents))
|
||||
|
||||
print(f"Wrote {len(grouped_extraction.groups)} groups; checking PDF compilation...")
|
||||
# ==========================================
|
||||
# PDF COMPILATION (4 Threads)
|
||||
# ==========================================
|
||||
all_tex_files = list(text2_dir.glob("*.tex")) + list(sol2_dir.glob("*.tex"))
|
||||
compilation_status = compile_existing_pdfs(workspace)
|
||||
return ExitCode.PARTIAL if processing_errors or compilation_status != ExitCode.SUCCESS else ExitCode.SUCCESS
|
||||
|
||||
|
||||
def compile_existing_pdfs(workspace: EvaluationWorkspace) -> ExitCode:
|
||||
"""Compile existing fragments without reading checkpoints or calling Gemini."""
|
||||
folder = workspace.root
|
||||
all_tex_files = list(workspace.rendered_text_dir.glob("*.tex")) + list(workspace.rendered_solution_dir.glob("*.tex"))
|
||||
|
||||
def compile_worker(tex_file: Path) -> str | None:
|
||||
"""Helper to read content and call the utility function."""
|
||||
try:
|
||||
pdf_path = tex_file.with_suffix('.pdf')
|
||||
status_path = folder / 'Cache' / 'statement_pdf_status' / tex_file.parent.name / (tex_file.stem + '.json')
|
||||
failed_before = status_path.exists() and not json.loads(status_path.read_text()).get('complete')
|
||||
source_path = (workspace.correction_source_file if tex_file.parent.name == 'Sol2'
|
||||
else workspace.statement_source_file)
|
||||
if not source_path.is_file():
|
||||
source_path = None
|
||||
fingerprint = hashlib.sha256((utils.fragment_latex_header(source_path)
|
||||
+ utils.LATEX_AFTER + str(source_path)).encode()).hexdigest()
|
||||
status = json.loads(status_path.read_text()) if status_path.exists() else {}
|
||||
failed_before = not status.get('complete') or status.get('preamble_hash') != fingerprint
|
||||
if (pdf_path.is_file() and pdf_path.stat().st_size > 0
|
||||
and pdf_path.stat().st_mtime_ns >= tex_file.stat().st_mtime_ns and not failed_before):
|
||||
return None
|
||||
atomic_write_json(status_path, {'complete': False})
|
||||
atomic_write_json(status_path, {'complete': False, 'preamble_hash': fingerprint})
|
||||
content = tex_file.read_text(encoding='utf-8')
|
||||
compile_to_pdf(content, pdf_path, strict=True)
|
||||
atomic_write_json(status_path, {'complete': True})
|
||||
compile_to_pdf(content, pdf_path, strict=True, source_path=source_path)
|
||||
atomic_write_json(status_path, {'complete': True, 'preamble_hash': fingerprint})
|
||||
except Exception as e: # noqa: BLE001 - compiler worker boundary
|
||||
return f"Error compiling {tex_file.name}: {e}"
|
||||
return None
|
||||
@@ -1045,8 +1057,7 @@ def write_exam_outputs(workspace: EvaluationWorkspace, grouped_extraction: Group
|
||||
]
|
||||
for error in compile_errors:
|
||||
report_error(folder, 'PDF compilation', error)
|
||||
processing_errors.extend(compile_errors)
|
||||
return ExitCode.PARTIAL if processing_errors else ExitCode.SUCCESS
|
||||
return ExitCode.PARTIAL if compile_errors else ExitCode.SUCCESS
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
@@ -1056,6 +1067,8 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
help="Regroup existing questions with Gemini; update only label_groups")
|
||||
actions.add_argument("--persp-only", action="store_true",
|
||||
help="Generate only missing Persp rubrics for existing groups")
|
||||
actions.add_argument("--compile-only", action="store_true",
|
||||
help="Retry existing fragment PDFs using source preambles; no Gemini requests")
|
||||
parser.add_argument('--delete-persp', action='store_true',
|
||||
help='Delete current Persp before generation (requires --persp-only)')
|
||||
parser.add_argument(
|
||||
@@ -1071,6 +1084,10 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
def run(args):
|
||||
if args.delete_persp and not args.persp_only:
|
||||
raise CliError('--delete-persp requires --persp-only', ExitCode.INVALID_ARGUMENTS)
|
||||
if args.restart and (args.compile_only or args.groups_only or args.persp_only):
|
||||
raise CliError('--restart cannot be combined with a partial action', ExitCode.INVALID_ARGUMENTS)
|
||||
if args.compile_only:
|
||||
return compile_existing_pdfs(workspace_from_args(args))
|
||||
if args.groups_only or args.persp_only:
|
||||
kwargs = {'delete_persp': True} if args.delete_persp else {}
|
||||
return refine_existing(workspace_from_args(args),
|
||||
|
||||
Reference in new issue
Block a user