Generalize phasing API; remove Isovar-named identifiers - #379
Merged
Conversation
Closes #378. The phasing Protocol bundled two unrelated concerns (read-phasing + mutant-transcript construction) and named them after Isovar, even though varcode imports nothing isovar-shaped. That made the dependency direction look circular (isovar already declares varcode>=4.15) and forced any non-Isovar source to either lie about its identity or build a wrapper. Split into two narrow Protocols, both fully generic: - ReadPhasingSource: has_evidence(variant) + partners_in_cis(variant). - MutantTranscriptSource: mutant_transcript(variant, transcript). IsovarPhaseResolver renamed to ReadPhaseResolver. Accepts any ReadPhasingSource; routes mutant_transcript() to the wrapped source when it also satisfies MutantTranscriptSource (otherwise returns None silently rather than raising). Source tag flipped from "isovar" to "read_phasing". The actual implementation classes (Isovar's IsovarReadPhasing in openvax/isovar#183; the heavier mutant-transcript adapter tracked in openvax/isovar#184) stay in isovar, where the dependency direction already supports them. Varcode no longer mentions Isovar by name on any public symbol. Hard rename, no deprecation alias. Test suite: tests/test_isovar_phase_resolver.py renamed to tests/test_read_phase_resolver.py with the stub updated to satisfy both new Protocols. test_haplotype_effect.py + test_vcf_phase_resolver.py updated to match. 1188/1190 pass; 2 pre-existing skips.
iskandr
added a commit
to openvax/isovar
that referenced
this pull request
May 14, 2026
Varcode is dropping Isovar-named identifiers from its public surface (openvax/varcode#378, openvax/varcode#379). Replace the docstring reference to the old `IsovarAssemblyProvider` Protocol with the new `ReadPhasingSource` + `MutantTranscriptSource` split, name the matching consumer (`ReadPhaseResolver`), and point at #184 for the companion heavy-adapter rework that will split `VarcodeAdapter` into two narrower classes. No code change; the adapter's method names (`has_evidence`, `partners_in_cis`) already match the new `ReadPhasingSource` Protocol.
2 tasks
….source; trim Isovar-named examples from docstrings
3 tasks
5 tasks
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.
Summary
Closes #378. Filed companion isovar tickets: openvax/isovar#184.
Varcode's phasing API named one upstream tool (Isovar) on every public identifier —
IsovarPhaseResolver,IsovarAssemblyProvider— even though varcode imports nothing isovar-shaped and isovar already declaresvarcode>=4.15. This made the dependency direction read as circular, forced non-Isovar sources to lie about their identity, and bundled two unrelated concerns (read-phasing + mutant-transcript construction) into a single Protocol.This PR makes varcode's phasing surface fully generic. Implementations of the Protocols live in the packages that produce the underlying evidence (Isovar, long-read tools, custom assemblers, test stubs).
Renames
IsovarAssemblyProvider(single Protocol)has_contig(variant, transcript)has_evidence(variant)onReadPhasingSourcevariants_in_contig(variant, transcript)partners_in_cis(variant)onReadPhasingSourcemutant_transcript(variant, transcript)MutantTranscriptSourceIsovarPhaseResolverReadPhaseResolverresolver.source == "isovar"resolver.source == "read_phasing"ReadPhaseResolverrequires aReadPhasingSource. Themutant_transcript(...)method on the resolver is optional — it returnsNonesilently when the wrapped source doesn't also satisfyMutantTranscriptSource, instead of raising. So a phasing-only source (e.g. the newisovar.IsovarReadPhasingfrom openvax/isovar#183) plugs in cleanly without needing to fabricate transcript reconstruction.Why these names
ReadPhasingSource— generic across data sources (Isovar, long-read tools, hand-rolled). Doesn't pretend any one upstream is special.has_evidence/partners_in_cis— neutral. The oldhas_contigwas Isovar-vocabulary; long-read tools don't have "contigs," they have fragments. The phasing question is just "do you have evidence for this variant?" and "who's in cis with it?".MutantTranscriptSource— separate concern. A consumer that only needs phasing shouldn't be forced to also build transcripts.Dependency direction stays one-way
varcode/: zeroimport isovar. Zero Isovar-named identifiers on the public surface. Confirmed via grep.isovar/: continues to declarevarcode>=4.15.0and ship implementations of the new generic Protocols (Add IsovarReadPhasing adapter for RNA-read variant phasing isovar#183 already does this; Split VarcodeAdapter into two narrower providers; drop Varcode-named API isovar#184 covers the heavierVarcodeAdapterrework).Files touched
varcode/phasing.py— full rewrite of Protocol definitions +ReadPhaseResolver.VCFPhaseResolverand helpers untouched.varcode/__init__.py— updated re-exports +__all__.varcode/variant.py,varcode/variant_collection.py—phase_resolver=docstrings updated.tests/test_isovar_phase_resolver.py→tests/test_read_phase_resolver.py(git rename + body update). 18 tests, all on the new Protocol shape.tests/test_haplotype_effect.py— stub provider renamed to_StubReadPhasingSourcematching the new shape; 4 tests on the resolver-driven path.tests/test_vcf_phase_resolver.py— interface-symmetry test now referencesReadPhaseResolver.docs/germline.md— recipe and resolver list updated.docs/api.md— adds entries forReadPhasingSourceandMutantTranscriptSource; renames the resolver entry.CHANGELOG.md— Breaking entry.varcode/version.py— 4.23.0 → 4.24.0.Test plan
pytest tests/test_read_phase_resolver.py— 18 cases (Protocol conformance, phasing semantics, optional MutantTranscript channel, effect-attachment end-to-end). All pass.pytest tests/test_haplotype_effect.py— 7 cases (joint cDNA building, HaplotypeEffect emission via the new resolver). All pass.pytest tests/test_vcf_phase_resolver.py— 25 cases, unchanged behavior. All pass.pytest tests/test_germline_effects.py— 34 cases, unchanged behavior. All pass.pytest tests/— 1188 passed, 2 pre-existing skips.Out of scope
VarcodeAdapter— tracked in Split VarcodeAdapter into two narrower providers; drop Varcode-named API isovar#184. Until that lands, downstream users ofVarcodeAdaptersee a runtime error when wiring it intoReadPhaseResolver(the methods no longer match the Protocol). The new isovar adapter PR is small.IsovarPhaseResolveris the only public-surface rename in this PR; lower-level helper names are unchanged.References
PhaseAmbiguousEffect→PhaseCandidateSetrename (same hard-rename precedent).IsovarReadPhasingalready matchesReadPhasingSource.VarcodeAdapterrework.