From 698ac4240cae5356f2d48ec7fb836c93b3766efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Miquel?= Date: Sun, 11 Oct 2026 15:03:44 +0200 Subject: [PATCH] Fix small group naming bug --- copienator/commands/annotating_by_label.py | 23 ++++++++++++++-------- copienator/commands/gemini_for_enonce.py | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/copienator/commands/annotating_by_label.py b/copienator/commands/annotating_by_label.py index 0cb614f..4be46ca 100644 --- a/copienator/commands/annotating_by_label.py +++ b/copienator/commands/annotating_by_label.py @@ -234,15 +234,17 @@ def _unique_prefixes(groups: list[list[str]]) -> list[tuple[str, list[str]]]: candidate = f"{safe_labels[0]}+" if natural_key(candidate) > natural_key(previous): base = candidate - prefix = base.removesuffix("i") + base = base.removesuffix("i") + # Keep related groups under the same short stem (I), I)-2, ...). + # Normalize before allocating a suffix so no later rewrite can collide. + if previous and base.startswith(previous): + base = previous + prefix = base counter = 2 while prefix in used: prefix = f"{base}-{counter}" counter += 1 - if counter == 2 and previous and previous in prefix: - prefix = f"{previous}-{counter}" - elif counter == 2: - previous = prefix + previous = base used.add(prefix) result.append((prefix, labels)) return result @@ -250,14 +252,16 @@ def _unique_prefixes(groups: list[list[str]]) -> list[tuple[str, list[str]]]: def _existing_group_state( output_root: Path, - prefix: str, + prefix: str | None = None, ) -> tuple[set[tuple[str, str]], int]: existing_items: set[tuple[str, str]] = set() maximum_group = 0 if not output_root.is_dir(): return existing_items, maximum_group for directory in output_root.iterdir(): - if not directory.is_dir() or not directory.name.startswith(f"{prefix} G"): + if not directory.is_dir(): + continue + if prefix is not None and not directory.name.startswith(f"{prefix} G"): continue try: maximum_group = max(maximum_group, int(directory.name.split(" G")[-1])) @@ -318,8 +322,11 @@ def _generate_groups( ) -> tuple[int, bool]: generated = 0 problems = False + # Resume by answer identity across all prefixes, including legacy names. + # Changing the naming scheme must not regenerate already reviewed PDFs. + existing_items = _existing_group_state(output_root)[0] if resume else set() for prefix, labels in _unique_prefixes(groups): - existing_items, maximum_group = ( + _, maximum_group = ( _existing_group_state(output_root, prefix) if resume else (set(), 0) ) items = [ diff --git a/copienator/commands/gemini_for_enonce.py b/copienator/commands/gemini_for_enonce.py index ce2d5c1..262af83 100644 --- a/copienator/commands/gemini_for_enonce.py +++ b/copienator/commands/gemini_for_enonce.py @@ -716,7 +716,7 @@ def process_exam( with io.StringIO() as f, io.StringIO() as f_full: - header = "# Edit labels. Modify groups (---). Ensure label uniqueness (XX). Duplicate CONTEXT.\n\n" + header = "# Edit labels. Modify groups (---). Ensure label uniqueness (XX). Duplicate/modify CONTEXT.\n\n" f.write(header) f_full.write(header)