Skip to content

Build each load into a Corpus that load() returns, handed explicitly everywhere - #145

Merged
handrews merged 1 commit into
mainfrom
claude/phylogenetics-code-review-55ca0c
Oct 22, 2026
Merged

handrews merged 1 commit into
mainfrom
claude/phylogenetics-code-review-55ca0c

Conversation

@handrews

Copy link
Copy Markdown
Owner

The loader kept its records in class-level registries (Author._authors, Source._sources, Taxon._taxa, Section._sections and the rest), an index every Tree root wrote (_new_index), a repository registry in material.py and a rank-hub cache in claims.py that went stale when a taxon was added. load() filled them as a side effect and returned (data, roots); a second load in one process overwrote and leaked; the extractor and the claims script read the private dicts; and the tests snapshotted and restored all of them by hand before every test.

phylohist/loader/corpus.py holds the Corpus: the five record dicts in insertion order, the repositories, the raw data and the roots, with add_* methods that build a record against the corpus and then store it (a constructor that ends the load stores nothing), copy() for a test's own view, and protologue_sources() walked from the roots in place of the index. Every constructor takes the corpus it resolves records in; a root Tree takes it beside its metadata and its nodes share it; no record keeps a reference to its corpus, and Source.publication is resolved where the record is built. load() builds a fresh corpus per call and returns it; the loader's own checks, the extractor (extract, manifest, names_index, rank_variants, holotype_conflicts) and the claims script take it as their first argument, and claims.py imports no record class and keeps nothing between calls.

The tests take records, a per-test copy of the session corpus, in place of the restored registries; support.with_documents gives a loader check its synthetic documents, and an autouse guard fails a test that changes the session corpus. The three autouse registry fixtures and the snapshot machinery are gone.

The claims, the names index, the manifest and the repositories file are byte-identical, as is the loader's log over the data and drafts.

…everywhere

The loader kept its records in class-level registries (`Author._authors`,
`Source._sources`, `Taxon._taxa`, `Section._sections` and the rest), an
index every `Tree` root wrote (`_new_index`), a repository registry in
`material.py` and a rank-hub cache in `claims.py` that went stale when a
taxon was added. `load()` filled them as a side effect and returned
`(data, roots)`; a second load in one process overwrote and leaked; the
extractor and the claims script read the private dicts; and the tests
snapshotted and restored all of them by hand before every test.

`phylohist/loader/corpus.py` holds the `Corpus`: the five record dicts in
insertion order, the repositories, the raw data and the roots, with
`add_*` methods that build a record against the corpus and then store it
(a constructor that ends the load stores nothing), `copy()` for a test's
own view, and `protologue_sources()` walked from the roots in place of
the index. Every constructor takes the corpus it resolves records in; a
root `Tree` takes it beside its metadata and its nodes share it; no
record keeps a reference to its corpus, and `Source.publication` is
resolved where the record is built. `load()` builds a fresh corpus per
call and returns it; the loader's own checks, the extractor (`extract`,
`manifest`, `names_index`, `rank_variants`, `holotype_conflicts`) and
the claims script take it as their first argument, and `claims.py`
imports no record class and keeps nothing between calls.

The tests take `records`, a per-test copy of the session corpus, in
place of the restored registries; `support.with_documents` gives a
loader check its synthetic documents, and an autouse guard fails a test
that changes the session corpus. The three autouse registry fixtures
and the snapshot machinery are gone.

The claims, the names index, the manifest and the repositories file are
byte-identical, as is the loader's log over the data and drafts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@handrews
handrews merged commit e773dfa into main Oct 22, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant