Skip to content

Give every dependency a minimum version and test them in CI - #271

Merged
matth-love merged 3 commits into
mainfrom
deps/minimum-versions
Oct 8, 2026
Merged

matth-love merged 3 commits into
mainfrom
deps/minimum-versions

Conversation

@mmacferrin

@mmacferrin mmacferrin commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Description

Gives every dependency in pyproject.toml a minimum version and adds CI runs that test the suite with each dependency at that minimum and on Python 3.14. No existing issue covers this.

The conda-forge recipe will also need these new minimums when the next release goes out.

Minimum versions

  • Compiled packages: the first release with wheels for Python 3.12, globato's oldest supported Python: scipy>=1.11.2, pyyaml>=6.0.1, matplotlib>=3.8.0. matplotlib has 3.12 wheels from 3.7.3, but 3.8.0 matches IVERT's minimum.
  • Pure-Python packages: the release current when Python 3.12 came out, in fall 2023: laspy[lazrs,laszip]>=2.5.1, pyshp>=2.3.1, click>=8.1.7, requests>=2.31.0.
  • numpy>1.24 becomes numpy>=1.26.0. No numpy release before 1.26.0 has Python 3.12 wheels, and 1.24/1.25 don't build on it.
  • shapely>=2.0.0 becomes shapely>=2.0.3, and pyogrio>=0.7.0 becomes pyogrio>=0.8.0; pandas and h5py get minimums of pandas>=2.1.2 and h5py>=3.11.0 for the same reason. Earlier releases were built against numpy 1 but don't cap it, so a resolver can install them alongside numpy 2, where they fail to import. Each new floor avoids that one of two ways: shapely 2.0.3 and pandas 2.1.2 declare numpy<2, so in a numpy-2 environment the resolver skips them for a later release of each package; h5py 3.11.0 and pyogrio 0.8.0 run on numpy 2 directly, but are backward-compatible with a numpy 1.x environnment.
  • fetchez, transformez, rasterio, geopandas and pyproj already had minimums and are unchanged.

The optional extras and dependency groups are unchanged.

numpy 2.0.0 workaround

numpy 2.0.0, and only that release, returns the inverse from np.unique(..., axis=0, return_inverse=True) with an extra dimension, (n, 1) instead of (n,). 2.0.1 reverted the change. ClaimGridFilter and WaterSurfaceFilter both use that call, so under numpy 2.0.0 they fail ("non-broadcastable output operand" and "object too deep for desired array"). Each now flattens the inverse with .ravel(). That returns the same array on every other numpy version and gives the 1-D result on 2.0.0. With a synthetic water mask, WaterSurfaceFilter's output is byte-for-byte the same on numpy 1.26.0, 2.0.0 and 2.5.3, and the full suite passes under 2.0.0.

CI

The test.yml job becomes a matrix of three runs:

  • Python 3.12, highest dependencies (the newest versions, as the old single run used)
  • Python 3.14, highest dependencies
  • Python 3.12, lowest-direct dependencies: each direct dependency at its minimum, transitive ones at their newest compatible versions. This run fails when globato starts using something newer than a stated minimum, which means that minimum needs raising.

uv sync can't resolve to the lowest versions for the package alone, so the runs install with uv pip install --resolution ... into the environment that setup-uv activates. The test group is then installed under a constraint of what's already there, so it can't lift a dependency off its minimum. Tests run with pytest directly rather than uv run, which would re-sync the environment. Check names become pytest (Python <version>, <resolution> dependencies).

Testing

Replaying each matrix run's install steps in a fresh environment, 294 tests pass (1 skipped) on Python 3.12 and 3.14 with highest and on 3.12 with lowest-direct. zizmor reports the same findings on test.yml as on main, and none new.


Checklist

  • PR title is descriptive
  • PR body contains links to related and resolved issues (e.g. closes #1)
  • If needed, CHANGELOG.md updated
  • If needed, docs and/or README.md updated
  • If needed, unit tests added
  • All checks passing
  • At least one approval

@mmacferrin
mmacferrin requested a review from matth-love October 8, 2026 03:18
@mmacferrin

Copy link
Copy Markdown
Contributor Author

This paragraph was very confusingly worded, making it sound like this arrangement was purely internally incompatible:

shapely>=2.0.0 becomes shapely>=2.0.3, and pyogrio>=0.7.0 becomes pyogrio>=0.8.0. Together with pandas>=2.1.2 and h5py>=3.11.0, these are a little past their first releases with Python 3.12 wheels. Those earlier releases were built against numpy 1 but don't cap it, so they install alongside numpy 2 and then fail to import. shapely 2.0.3 and pandas 2.1.2 declare numpy<2, and h5py 3.11.0 and pyogrio 0.8.0 work with numpy 2.

I rewrote that paragraph to explain the logic there a bit better.

@matth-love
matth-love merged commit c74800d into main Oct 8, 2026
4 checks passed
@matth-love
matth-love deleted the deps/minimum-versions branch October 8, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants