Skip to content

FIX remaining dependency declarations and repair the conda recipe (#43) - #59

Merged
mkiani12 merged 1 commit into
mainfrom
hotfix/dependency-bounds-and-ci-matrix
Aug 28, 2026
Merged

mkiani12 merged 1 commit into
mainfrom
hotfix/dependency-bounds-and-ci-matrix

Conversation

@mkiani12

Copy link
Copy Markdown
Collaborator

Completes issue #43. Most of it already landed in 1a753dc — lower bounds, the dev-dependency cleanup, and the 3 OS × 3 Python matrix. Three declarations were still wrong, and one of them breaks an advertised install route.

1. pydantic was still published as a runtime dependency

It is imported nowhere. This is the same defect the issue reports for the dev requirements, and it survived the earlier loosening because only the version specifier changed (==2.13.4 → >=2.0), not the entry itself. Removed from requirements.txt and requirements-lock.txt.

2. The conda recipe was never updated, and the conda install is broken

recip/meta.yaml declares fastapi — which the package does not use — while omitting pandas, rasterio, pillow and imagecodecs, all of which are loaded at import fezrs time:

imported at `import fezrs` time: PIL cv2 imagecodecs matplotlib numpy pandas rasterio skimage sklearn
conda recipe provides         : cv2 matplotlib numpy skimage sklearn
MISSING from conda recipe     : PIL imagecodecs pandas rasterio

So conda install -c FEZtool fezrs followed by import fezrs fails with ModuleNotFoundError: rasterio. The recipe also declared python >=3.10 against setup.py's >=3.11. All corrected. The README advertises conda as one of two install routes, so this belongs with the packaging fix.

I left the recipe's run dependencies unversioned, matching its existing style — I have no conda toolchain here to test a solve against, and adding bounds I cannot verify seemed the riskier change. The new test asserts the set of names stays in step with requirements.txt.

3. Smaller items

requirements-dev.txt still pinned pytest==9.0.3 exactly, which is the pattern this issue is about; reproducible installs are what requirements-lock.txt is for. Now pytest>=8.0.

setup.py gains 3.11/3.12/3.13 classifiers, so advertised support matches the matrix rather than being implied by python_requires alone.

On imagecodecs

Worth stating explicitly since it looks like another unused dependency: it is not imported by FEZrs code, but it is loaded at import fezrs time through scikit-image/tifffile, and it is what decodes compressed (LZW, deflate, JPEG) GeoTIFFs on the input path. The bundled example data is uncompressed; most real Landsat and Sentinel deliveries are not. Kept, and the reason is now a comment in requirements.txt rather than something to rediscover.

Guards

tests/setup_test.py gains seven tests so none of this regresses silently:

  • every declared runtime requirement must actually be loaded by import fezrs, checked in a clean subprocess — this is the guard that would have caught pydantic, and it still allows legitimately transitive dependencies like imagecodecs;
  • the lock file must cover the same distributions as requirements.txt and stay exactly pinned;
  • the dev file must stay test-only (explicitly asserting gdal/pyrsgis/tensorflow do not return);
  • the conda recipe must cover every runtime dependency, must not declare fastapi, and must agree with setup.py on the Python floor;
  • classifiers must list every Python version in the CI matrix.

Verification

Built three environments with uv and ran the full suite headless in each:

Python resolved rasterio result
3.11.15 1.4.4 436 passed, 1 skipped
3.12.13 1.5.1 437 passed
3.13.14 1.5.1 436 passed, 1 skipped

(The skip is importorskip("setuptools") in the docs-import test; those two environments have no setuptools.)

The 3.11 row is the point of the whole issue. rasterio==1.5.0 declares requires_python >=3.12 and ships no cp311 wheel, so python_requires=">=3.11" could not be satisfied under the old pins — the advertised support was unreachable. With lower bounds the resolver picks 1.4.4 there and the suite passes.

Published metadata now reads:

['numpy>=1.26', 'Pillow>=10.0', 'pandas>=2.0', 'rasterio>=1.3', 'matplotlib>=3.8',
 'scikit-learn>=1.3', 'scikit-image>=0.22', 'opencv-python>=4.8', 'imagecodecs>=2023.1.1']

Also worth noting the loosened bounds resolve forward, not just backward: on 3.12 they pull numpy 2.5.2, opencv 5.0.0 and scikit-learn 1.9.0 — all newer than the lock file — and the suite is green on those too. That is the upstream-breakage signal a lockfile-only setup would have hidden.

The bulk of this issue was addressed in 1a753dc: runtime pins became lower
bounds, the unused gdal/pyrsgis/tensorflow dev dependencies and the duplicated
rasterio pin were dropped, and CI grew a 3 OS x 3 Python matrix. Three
declarations were still wrong.

pydantic was published as a runtime dependency but is imported nowhere. It is
the same defect the issue reports for the dev requirements, and it survived the
loosening because only the version specifier changed. Removed from
requirements.txt and requirements-lock.txt.

recip/meta.yaml was untouched by that work and is worse than requirements.txt
was. It declared fastapi, which the package does not use, while omitting
pandas, rasterio, pillow and imagecodecs - all of which are loaded at
`import fezrs` time. A conda install from the advertised channel therefore
failed on import with ModuleNotFoundError: rasterio. It also declared
python >=3.10 against setup.py's >=3.11. All corrected.

requirements-dev.txt still pinned pytest==9.0.3 exactly, which is the pattern
this issue is about; reproducible installs are what requirements-lock.txt is
for. Loosened to pytest>=8.0.

setup.py gains Python 3.11/3.12/3.13 classifiers so the advertised support
matches the CI matrix rather than being implied by python_requires alone.

Note imagecodecs is deliberately kept despite not being imported by FEZrs
code: it is loaded through scikit-image/tifffile at import time and is what
decodes compressed GeoTIFFs on the input path. The bundled example data is
uncompressed, most real Landsat and Sentinel deliveries are not. This is now
documented in requirements.txt rather than left to be rediscovered.

Add guards so none of these can regress silently: every declared runtime
requirement must actually be loaded by `import fezrs` (checked in a clean
subprocess, so genuinely transitive dependencies still pass), the lock file
must cover the same distributions and stay exactly pinned, the dev file must
stay test-only, and the conda recipe must cover every runtime dependency,
exclude fastapi and agree with setup.py on the Python floor.

Verified on Python 3.11, 3.12 and 3.13 built with uv, all headless. On 3.11
the resolver selects rasterio 1.4.4, which is the case the previous
rasterio==1.5.0 pin made impossible - that pin required Python >=3.12 and
published no cp311 wheel, so python_requires=">=3.11" could not be satisfied.
@mkiani12
mkiani12 merged commit 83afdf3 into main Aug 28, 2026
9 checks passed
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.

1 participant