Lift the text-append curation helper out of gtdb_ground (#526) - #528
Open
realmarcin wants to merge 1 commit into
Open
Lift the text-append curation helper out of gtdb_ground (#526)#528realmarcin wants to merge 1 commit into
realmarcin wants to merge 1 commit into
Conversation
`_append_curation_event` was the only code here that adds a CurationEvent without a YAML round-trip, and it lived inside one script. The nine writers #325 lists as owing a trace are line editors — splitlines, regex, write_text — so `record_curation_event`, which appends to a parsed dict, does not reach them. Nine private copies would be nine chances to re-hit what this one already knows: that `- timestamp:` is column-0 so a naive scan inserts the event above the existing history, that `curation_history: []` is the same key and matching the bare string appends a second one PyYAML silently drops, and that a trailing comment block belongs to the next key. Now `communitymech.curate.curation_event.append_curation_event_text`, with curator and width as parameters rather than hardcoded. gtdb_ground keeps a thin wrapper so its curator string stays in one place and the existing tests keep exercising the shared code through its original caller. One behaviour change on purpose: the library raises ValueError where the script raised SystemExit. SystemExit does not inherit from Exception, so a caller with `except Exception` would not catch it — it would take the process down mid-sweep, which is exactly what a shared helper must not do. gtdb_ground converts at its own boundary, so its CLI message is unchanged. drop_obsolete_go_bp.py is wired as the first user, and comes off the owed list. Deletions are where a trace matters most: the removed lines are simply not there afterwards. The canary needed building rather than running. The corpus has no droppable annotations left, so a dry run reports zero and proves nothing — the shape of check that passes while persisting nothing. The test constructs a record that does have one, runs the script in a temp tree the way a batch would, and reads the file back off disk. Reverting the wiring reddens it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #527 (base
curation-history-325), which itemises the writers this makes fixable. Review #527 first.Why it had to move
_append_curation_eventwas the only code in the repo that adds aCurationEventwithout a YAML round-trip — and it lived insidescripts/gtdb_ground.py.That matters because the nine writers #325 lists as owing a trace are line editors:
splitlines(), regex,write_text.record_curation_eventappends to a parsed dict, so it does not reach them. And re-dumping is not an option — it would reflow every record they touch, which is whyterm_remapdescribes itself as "text-only edits".Nine private copies would be nine chances to re-hit what this one already knows, each learned from a real failure:
- timestamp:starts at column 0, so a naive "next top-level key" scan treats the history's own first item as the next section and inserts the event above the existing history — which the append-only write guard then correctly refuses.curation_history: []is the same key ascuration_history:. Matching only the bare string appends a second one, which PyYAML resolves by keeping the last — silently dropping the existing history.What changed
Now
communitymech.curate.curation_event.append_curation_event_text, withcuratorandwidthas parameters rather than hardcoded togtdb_ground.py. The script keeps a thin wrapper, so its curator string stays in one place andtests/test_gtdb_curation_history.pykeeps exercising the shared code through its original caller.One deliberate behaviour change: the library raises
ValueErrorwhere the script raisedSystemExit.SystemExitdoes not inherit fromException, so a caller withexcept Exceptionwould not catch it — it would take the process down mid-sweep, which is precisely what a shared helper must not do.gtdb_ground.pyconverts at its own boundary, so its CLI behaviour and message are unchanged.First user
drop_obsolete_go_bp.py, wired and removed from_OWED(9 → 8). Deletions are where a trace matters most — the removed lines are simply not there afterwards, so "what did this and why" is least recoverable from the record itself.The canary had to be built, not run
--dry-runagainst the corpus reports 0 files, because that cleanup already ran. That is the exact shape of check that passes while persisting nothing.So the test constructs a record that does carry a droppable annotation, runs the script in a temp tree the way a batch would, and reads the file back off disk. Reverting the wiring turns it red; the other nine tests stay green, which is why it is worth having separately.
Checks
uv run pytest tests/— 2391 passed, 16 skippedjust lint,just validate-strict— exit 0gtdb_ground.py— the case the existing tests cannot reach, since they only call through the original callerCloses #526. Advances #325 (9 owed → 8).
🤖 Generated with Claude Code