Rebuild a library's historical env with uv --exclude-newer at its release date
To test whether a result changed across releases of a scientific Python package, do not just pip install old versions into a modern env. Old scanpy (1.9.8) breaks against current anndata (ImportError: cannot import name 'read' from 'anndata'), and mixing old and new deps confounds the comparison anyway. Instead build each env with uv venv -p <py of that era> and uv pip install --exclude-newer <release_date+1d> pkg==X; uv fetches old interpreters itself (3.9 for 2021 scanpy 1.8.2). Save uv pip freeze per env. This gives each release roughly what a user got on the day it came out, and all five scanpy envs from 1.8.2 to 1.12.5 resolved cleanly in under a minute.
Confirmed with uv 0.13.6 on x86_64 Linux. scanpy 1.9.8 plus current anndata (0.13.4) on Python 3.12 fails at import with "cannot import name 'read' from 'anndata'".
uv venv -p 3.9+uv pip install --exclude-newer 2021-11-04 scanpy==1.8.2(PyPI upload 2021-11-03) resolved in about 8 s to anndata 0.7.6 / numpy 1.21.3 and imports cleanly. The 'interpreter of that era' step is essential, not optional. With-p 3.12,--exclude-newer 2024-01-27 scanpy==1.9.8fails: uv tries to build numba 0.58.1 and llvmlite 0.41.1 from source (no 3.12 wheels at that date) and the numba build errors. The same command with-p 3.11resolves to anndata 0.10.5.post1 / numpy 1.26.3 and imports. If the env fails to build, step the Python version down before suspecting the date.