Standardisation des scripts

This commit is contained in:
2026-08-20 13:01:26 +02:00
parent 2f1cd00e32
commit 352d36e38c
10 changed files with 590 additions and 144 deletions
+42 -22
View File
@@ -1,13 +1,22 @@
import argparse
import os
import json
import re
import sys
import shutil
from pathlib import Path
from collections import defaultdict
from collections.abc import Sequence
from concurrent.futures import ThreadPoolExecutor
from PIL import Image, ImageDraw, ImageFont
from pdf2image import convert_from_path, pdfinfo_from_path
from PIL import Image, ImageDraw, ImageFont
from copienator import (
EvaluationWorkspace,
ExitCode,
atomic_write_json,
evaluation_parser,
execute,
workspace_from_args,
)
# Configuration
DPI = 200 # Good balance for readability and size
@@ -34,7 +43,7 @@ def get_pdf_height(path):
# Return total height
return single_page_px * num_pages
except Exception as e:
except Exception as e: # noqa: BLE001 - pdfinfo may raise backend-specific errors
print(f"Error reading {path}: {e}")
return 0
@@ -78,7 +87,7 @@ def group_files(file_list):
groups = []
for item in sorted_files:
dd, path, height = item
_, _, height = item
placed = False
# 2. Try to fit item into an existing group (First Fit)
@@ -140,7 +149,7 @@ def create_jpg(identifier, group_index, group, root_dir):
combined_img = stitch_pdf_pages(imgs)
if combined_img:
images.append((dd, combined_img))
except Exception as e:
except Exception as e: # noqa: BLE001 - PDF/image backends vary by platform
print(f"Failed to convert {path}: {e}")
if not images:
@@ -159,7 +168,7 @@ def create_jpg(identifier, group_index, group, root_dir):
# Try loading a font, fallback to default
try:
font = ImageFont.truetype("DejaVuSans.ttf", 40)
except IOError:
except OSError:
print("font not found")
font = ImageFont.load_default()
@@ -193,8 +202,7 @@ def create_jpg(identifier, group_index, group, root_dir):
# Save JSON metadata
json_filename = f"Group_{group_index+1}.json"
json_path = os.path.join(target_folder, json_filename)
with open(json_path, 'w') as f:
json.dump(metadata, f)
atomic_write_json(json_path, metadata, indent=None)
# Save with size constraints
output_filename = f"Group_{group_index+1}.jpg"
@@ -227,18 +235,16 @@ def process_identifier(identifier, files_info, output_dir):
for idx, group in enumerate(file_groups):
create_jpg(identifier, idx, group, output_dir)
def main():
if len(sys.argv) < 2:
print("Usage: python app.py <Path_to_Dir>")
sys.exit(1)
def build_parser() -> argparse.ArgumentParser:
return evaluation_parser("Group copy extracts by question label.")
root_dir = Path(sys.argv[1])
copies_dir = root_dir / "Copies"
par_label_dir = root_dir / "Par label"
def run(workspace: EvaluationWorkspace) -> ExitCode:
workspace.require_directories("Copies")
workspace.groups_dir.mkdir(parents=True, exist_ok=True)
print("Scanning files...")
data = collect_files(copies_dir)
data = collect_files(workspace.copies_dir)
print(f"Found {len(data)} identifiers. Processing...")
@@ -247,11 +253,25 @@ def main():
# Process using 8 threads
with ThreadPoolExecutor(max_workers=8) as executor:
for identifier in sorted_identifiers:
executor.submit(process_identifier, identifier, data[identifier],
par_label_dir)
futures = [
executor.submit(
process_identifier,
identifier,
data[identifier],
workspace.groups_dir,
)
for identifier in sorted_identifiers
]
for future in futures:
future.result()
print("Done.")
return ExitCode.SUCCESS
def main(argv: Sequence[str] | None = None) -> int:
parser = build_parser()
return execute(parser, argv, lambda args: run(workspace_from_args(args)))
if __name__ == "__main__":
main()
raise SystemExit(main())