Summary
For a -q/--query run the dataset is defined by two things: the query string and the UniProt release it was resolved against. run.log records the query and the resulting protein count, but never the release — so the run is not reproducible from its own log.
Why this is not theoretical
The same query returns materially different datasets over time. For family:"beta-lactamase":
| when |
proteins |
| original bundle |
127,115 |
| rebuild, May 2026 |
152,738 |
release 2026_02 (10-June-2026) |
113,015 |
A 26% drop between the May rebuild and today, with no change to the query. We hit this while trying to work out which bundle a published figure was built from — the count had moved twice, the derived percentage in the manuscript no longer matched any bundle, and there was no record of the release. It took a full session of archaeology, and the answer turned out not to be recoverable from the repository at all. The release is the one provenance field whose absence actually cost us, and it is the one the run log omits.
The headers are already there
Confirmed against the exact endpoint and parameters query.py uses:
X-UniProt-Release: 2026_02
X-UniProt-Release-Date: 10-June-2026
X-API-Deployment-Date: 29-July-2026
The handling point is query.py, right after response = requests.get(...) / raise_for_status(). Currently the only header read anywhere in the package is content-length.
Two constraints worth knowing before patching
1. The cached-FASTA path skips query_uniprot entirely. --keep-tmp defaults on, so most reruns reuse the cached FASTA and never call the query function. A release captured only in memory would vanish on every resumed run — i.e. on the majority of runs. It needs to be persisted beside the cached FASTA (e.g. uniprot_release.json) and read back on the cached branch.
2. Don't change the return arity. query_uniprot returns a 2-tuple and is unpacked as such by notebooks/ProtSpace_Preparation.ipynb as well as by prepare.py. An optional release_out: dict | None = None out-parameter keeps both working, and still degrades cleanly under --no-keep-tmp where no sidecar can be written.
Suggested output
## Input
query: family:"beta-lactamase"
uniprot_release: 2026_02
uniprot_release_date: 10-June-2026
uniprot_retrieved: 2026-08-11T15:41:00+0000
proteins: 113015
Unrelated but adjacent
query.py reads response.headers.get("content-length", 0) for the download progress bar. UniProt replies Transfer-Encoding: chunked with no Content-Length, so total_size is always 0 and the bar has never had a real total.
Context
Found while preparing datasets for a publication whose Methods section has to state the release per figure. Related: #432, and PRs #430 / #431.
Summary
For a
-q/--queryrun the dataset is defined by two things: the query string and the UniProt release it was resolved against.run.logrecords the query and the resulting protein count, but never the release — so the run is not reproducible from its own log.Why this is not theoretical
The same query returns materially different datasets over time. For
family:"beta-lactamase":2026_02(10-June-2026)A 26% drop between the May rebuild and today, with no change to the query. We hit this while trying to work out which bundle a published figure was built from — the count had moved twice, the derived percentage in the manuscript no longer matched any bundle, and there was no record of the release. It took a full session of archaeology, and the answer turned out not to be recoverable from the repository at all. The release is the one provenance field whose absence actually cost us, and it is the one the run log omits.
The headers are already there
Confirmed against the exact endpoint and parameters
query.pyuses:The handling point is
query.py, right afterresponse = requests.get(...)/raise_for_status(). Currently the only header read anywhere in the package iscontent-length.Two constraints worth knowing before patching
1. The cached-FASTA path skips
query_uniprotentirely.--keep-tmpdefaults on, so most reruns reuse the cached FASTA and never call the query function. A release captured only in memory would vanish on every resumed run — i.e. on the majority of runs. It needs to be persisted beside the cached FASTA (e.g.uniprot_release.json) and read back on the cached branch.2. Don't change the return arity.
query_uniprotreturns a 2-tuple and is unpacked as such bynotebooks/ProtSpace_Preparation.ipynbas well as byprepare.py. An optionalrelease_out: dict | None = Noneout-parameter keeps both working, and still degrades cleanly under--no-keep-tmpwhere no sidecar can be written.Suggested output
Unrelated but adjacent
query.pyreadsresponse.headers.get("content-length", 0)for the download progress bar. UniProt repliesTransfer-Encoding: chunkedwith noContent-Length, sototal_sizeis always 0 and the bar has never had a real total.Context
Found while preparing datasets for a publication whose Methods section has to state the release per figure. Related: #432, and PRs #430 / #431.