Refaire fixes and GUI support
This commit is contained in:
@@ -14,8 +14,6 @@ matplotlib.use("Agg")
|
||||
from PIL import Image, ImageFont
|
||||
from reportlab.pdfgen import canvas
|
||||
|
||||
from copienator.commands import annotating
|
||||
from copienator import utils
|
||||
from copienator import (
|
||||
CliError,
|
||||
EvaluationWorkspace,
|
||||
@@ -24,9 +22,11 @@ from copienator import (
|
||||
execute,
|
||||
read_json,
|
||||
target_parser,
|
||||
utils,
|
||||
workspace_from_target,
|
||||
)
|
||||
from copienator.annotation_data import load_annotation_data
|
||||
from copienator.commands import annotating
|
||||
from copienator.filesystem import staged_directory
|
||||
from copienator.utils import natural_key
|
||||
|
||||
@@ -46,7 +46,9 @@ except OSError:
|
||||
|
||||
def draw_checkbox(draw, x, y, size=BOX_SIZE, label=None, fill="white"):
|
||||
if label:
|
||||
draw.text((x - BOX_SIZE - 5, y + 2), str(label), fill="black", font=CHECKBOX_FONT)
|
||||
draw.text(
|
||||
(x - BOX_SIZE - 5, y + 2), str(label), fill="black", font=CHECKBOX_FONT
|
||||
)
|
||||
draw.rectangle([x, y, x + size, y + size], fill=fill, outline="black", width=2)
|
||||
return [x, y, x + size, y + size]
|
||||
|
||||
@@ -150,8 +152,13 @@ def _render_student(
|
||||
*,
|
||||
overwrite: bool,
|
||||
output_mode: str,
|
||||
output_root: Path | None = None,
|
||||
) -> str:
|
||||
output_dir = workspace.annotation_dir(output_mode) / f"Copie{student_id}"
|
||||
output_dir = (
|
||||
output_root
|
||||
if output_root is not None
|
||||
else workspace.annotation_dir(output_mode)
|
||||
) / f"Copie{student_id}"
|
||||
if _output_complete(output_dir) and not overwrite:
|
||||
print(f"Skipping {student_id}: output is complete.")
|
||||
return "skipped"
|
||||
@@ -178,6 +185,7 @@ def _render_student(
|
||||
draw_callback=checkbox_renderer.callback,
|
||||
)
|
||||
if final_image is None:
|
||||
problems = True
|
||||
continue
|
||||
label_images.append(final_image)
|
||||
checkbox_groups.append(checkbox_renderer.checkboxes)
|
||||
@@ -280,6 +288,39 @@ def run(
|
||||
|
||||
output_mode = "refaire" if refaire else "checks"
|
||||
tasks = sorted(loaded.data.items(), key=lambda item: natural_key(item[0]))
|
||||
if refaire:
|
||||
output_root = workspace.annotation_dir("refaire")
|
||||
if output_root.exists() and not overwrite:
|
||||
raise CliError(
|
||||
"BRnot already exists; use --overwrite to replace the previous redo."
|
||||
)
|
||||
|
||||
class IncompleteRedo(Exception):
|
||||
pass
|
||||
|
||||
try:
|
||||
with staged_directory(output_root) as staging:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
||||
futures = [
|
||||
executor.submit(
|
||||
_render_student,
|
||||
workspace,
|
||||
student_id,
|
||||
labels,
|
||||
overwrite=True,
|
||||
output_mode="refaire",
|
||||
output_root=staging,
|
||||
)
|
||||
for student_id, labels in tasks
|
||||
]
|
||||
statuses = [future.result() for future in futures]
|
||||
if loaded.warnings or any(status != "success" for status in statuses):
|
||||
raise IncompleteRedo
|
||||
except IncompleteRedo:
|
||||
print("Warning: incomplete redo generation; previous BRnot was preserved.")
|
||||
return ExitCode.PARTIAL
|
||||
return ExitCode.SUCCESS
|
||||
|
||||
statuses: list[str] = []
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
||||
futures = [
|
||||
@@ -302,7 +343,9 @@ def run(
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = target_parser("Generate annotated PDFs with checkboxes.")
|
||||
parser.add_argument("--overwrite", action="store_true", help="Replace existing outputs")
|
||||
parser.add_argument(
|
||||
"--overwrite", action="store_true", help="Replace existing outputs"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--refaire",
|
||||
action="store_true",
|
||||
@@ -328,4 +371,3 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user