Spaces:
Running
Running
| """Paste-anything target resolution (dee/core/resolve.py). | |
| NO NETWORK β Ensembl/NCBI fetchers are monkeypatched. Locks the input | |
| classifier (sequence vs symbol vs accession) and the resolve dispatch, | |
| including the privacy-preserving rule that raw sequences make no calls. | |
| """ | |
| import pytest | |
| from dee.core import resolve as R | |
| from dee.core import exon as E | |
| from dee.core.exon import Exon, GeneStructure | |
| # βββββββββββββββββββββββββββ classifier βββββββββββββββββββββββββββ | |
| def test_classify(text, kind): | |
| assert R.classify(text)[0] == kind | |
| def test_classify_sequence_strips_to_clean_dna(): | |
| kind, val = R.classify("acgt ACGT\nnnNN gtca gtca gtca") | |
| assert kind == "sequence" | |
| assert val == "ACGTACGTNNNNGTCAGTCAGTCA" | |
| # βββββββββββββββββββββββββββ raw sequence (offline) βββββββββββββββββββββββββββ | |
| def test_resolve_raw_sequence_makes_no_network_call(monkeypatch): | |
| # Any network helper firing would be a privacy bug for raw input. | |
| def _boom(*a, **k): | |
| raise AssertionError("network call on raw-sequence path!") | |
| monkeypatch.setattr(E, "_http_get_text", _boom) | |
| monkeypatch.setattr(E, "_http_get_json", _boom) | |
| monkeypatch.setattr(E, "fetch_gene_structure", _boom) | |
| out = R.resolve_target("ACGT" * 20) | |
| assert out["ok"] and out["kind"] == "sequence" | |
| assert out["sequence"] == "ACGT" * 20 | |
| assert "pasted sequence" in out["label"] | |
| def test_resolve_short_sequence_errors(): | |
| out = R.resolve_target("ACGTACGT") # < 23 nt β symbol attempt β fails | |
| assert out["ok"] is False | |
| # βββββββββββββββββββββββββββ gene symbol βββββββββββββββββββββββββββ | |
| def _fake_gene(): | |
| return GeneStructure( | |
| organism="human", gene_symbol="TP53", transcript_id="ENST00000269305", | |
| strand=1, cds_sequence="ATG" + "GCT" * 50 + "TAA", | |
| exons=[Exon(1, 1, 99, 0, 156)], last_junction_cds_pos=0, | |
| ) | |
| def test_resolve_symbol_requires_organism(): | |
| out = R.resolve_target("TP53", organism="") | |
| assert out["ok"] is False and "Human or" in out["error"] | |
| def test_resolve_symbol_with_organism(monkeypatch): | |
| monkeypatch.setattr(E, "fetch_gene_structure", lambda org, sym: _fake_gene()) | |
| out = R.resolve_target("TP53", organism="human") | |
| assert out["ok"] and out["kind"] == "gene" | |
| assert out["gene_symbol"] == "TP53" | |
| assert out["sequence"].startswith("ATG") | |
| assert "ENST00000269305" in out["label"] | |
| def test_resolve_symbol_not_found(monkeypatch): | |
| monkeypatch.setattr(E, "fetch_gene_structure", lambda org, sym: None) | |
| out = R.resolve_target("ZZZ9", organism="mouse") | |
| assert out["ok"] is False and "Couldn't find" in out["error"] | |
| # βββββββββββββββββββββββββββ accessions βββββββββββββββββββββββββββ | |
| def test_resolve_ensembl_transcript(monkeypatch): | |
| monkeypatch.setattr(E, "_http_get_text", | |
| lambda url, **k: ">ENST\nATGAAACCCGGGTTTACGTACGTACGT") | |
| out = R.resolve_target("ENST00000269305") | |
| assert out["ok"] and out["kind"] == "ensembl" | |
| assert out["sequence"] == "ATGAAACCCGGGTTTACGTACGTACGT" | |
| def test_resolve_ensembl_gene_resolves_canonical(monkeypatch): | |
| monkeypatch.setattr(E, "_http_get_json", lambda url, **k: { | |
| "Transcript": [ | |
| {"id": "ENST_other", "is_canonical": 0}, | |
| {"id": "ENST_canon", "is_canonical": 1}, | |
| ]}) | |
| captured = {} | |
| def _seq(url, **k): | |
| captured["url"] = url | |
| return ">x\nATGCGTACGTACGTACGTACGTACG" | |
| monkeypatch.setattr(E, "_http_get_text", _seq) | |
| out = R.resolve_target("ENSG00000141510") | |
| assert out["ok"] and out["kind"] == "ensembl" | |
| assert "ENST_canon" in captured["url"] # used the canonical transcript | |
| def test_resolve_refseq(monkeypatch): | |
| monkeypatch.setattr(E, "_http_get_text", | |
| lambda url, **k: ">NM_000546\nATGGAGGAGCCGCAGTCAGAT") | |
| out = R.resolve_target("NM_000546") | |
| assert out["ok"] and out["kind"] == "refseq" | |
| assert out["sequence"] == "ATGGAGGAGCCGCAGTCAGAT" | |
| def test_resolve_ensembl_fetch_failure(monkeypatch): | |
| monkeypatch.setattr(E, "_http_get_text", lambda url, **k: None) | |
| out = R.resolve_target("ENST00000269305") | |
| assert out["ok"] is False and "Ensembl" in out["error"] | |
| # βββββββββββββββββββββββββββ UniProt / structure (M5) βββββββββββββββββββββββββββ | |
| def test_resolve_uniprot_ok(monkeypatch): | |
| captured = {} | |
| def _json(url, **k): | |
| captured["url"] = url | |
| return {"results": [{"primaryAccession": "P04637"}]} | |
| monkeypatch.setattr(E, "_http_get_json", _json) | |
| out = R.resolve_uniprot("human", "TP53") | |
| assert out["ok"] and out["uniprot"] == "P04637" | |
| assert out["alphafold_url"] == "https://alphafold.ebi.ac.uk/files/AF-P04637-F1-model_v6.pdb" | |
| assert out["alphafold_page"] == "https://alphafold.ebi.ac.uk/entry/P04637" | |
| assert "organism_id%3A9606" in captured["url"] and "reviewed%3Atrue" in captured["url"] | |
| def test_resolve_uniprot_no_hit(monkeypatch): | |
| monkeypatch.setattr(E, "_http_get_json", lambda url, **k: {"results": []}) | |
| out = R.resolve_uniprot("human", "ZZZ9") | |
| assert out["ok"] is False | |
| def test_resolve_uniprot_bad_organism(): | |
| assert R.resolve_uniprot("ecoli", "lacZ")["ok"] is False | |