"""Async wrapper for MyGene.info API (https://mygene.info) Exposes `fetch_gene_info` which returns the top hit for a free‑text query. No API‑key required; 500 QPS community quota. """ import httpx, asyncio from functools import lru_cache _BASE = "https://mygene.info/v3" @lru_cache(maxsize=128) async def fetch_gene_info(query: str) -> dict: # noqa: C901 – simple IO fn """Return first hit dict or {} if nothing found. Parameters ---------- query : str – gene symbol / keyword / Entrez id / HGNC etc. """ params = { "q": query, "fields": "symbol,name,summary,alias,entrezgene,clinvar,location,go", "size": 1, } async with httpx.AsyncClient(timeout=10) as client: resp = await client.get(f"{_BASE}/query", params=params) resp.raise_for_status() hits = resp.json().get("hits", []) return hits[0] if hits else {}