Skip to content

Unit-test results depend on the Python version: unbounded upper pins let 3.12 resolve dependencies CI never sees #9069

Description

@hjmjohnson

Describe the bug

Whether the unit-test suite passes depends on which Python version the environment was built with, because [project.optional-dependencies].all has no upper bounds. Several dependencies have moved to requires-python >= 3.11 or >= 3.12, so a Python 3.10 environment simply cannot reach the releases that break MONAI, while a 3.12 environment installs them by default.

CI pins PYTHON_VER1: '3.10' and uses it for static-checks and full-dep, so CI never resolves the versions that fail. A contributor following CONTRIBUTING.md on a current interpreter does.

To Reproduce

uv venv --python 3.12 /tmp/env312 && VIRTUAL_ENV=/tmp/env312 uv pip install -e ".[all,testing]"
uv venv --python 3.10 /tmp/env310 && VIRTUAL_ENV=/tmp/env310 uv pip install -e ".[all,testing]"
./runtests.sh -u --net --coverage

What each interpreter resolves, from the same unbounded specifiers:

dependency Python 3.12 Python 3.10 why 3.10 cannot reach it
zarr 3.3.0 2.18.3 requires-python >= 3.12
scipy 1.18.1 1.15.3 requires-python >= 3.12
matplotlib 3.11.1 3.10.9 requires-python >= 3.11

Full suite, unmodified dev (c1240a2d4), Python 3.12: 18196 tests, 15 failures, 26 errors. Rebuilding the same tree on Python 3.10 clears five of the seven affected modules.

Which modules fail on 3.12 and why
module cause 3.10
tests.inferers.test_zarr_avg_merger (20 errors) zarr 3.3.0: ValueError: True is not a valid chunk input. Use chunks=None or chunks="auto" ... from zarr/core/chunk_grids.py:781 passes
tests.metrics.test_compute_fid_metric scipy 1.18 removed disp from scipy.linalg.sqrtm; monai/metrics/fid.py:85 calls sqrtm(..., disp=False) and unpacks two return values passes
tests.data.test_threadcontainer matplotlib baseline-image comparison, RMS 23.6 vs tolerance 0.05 (the baseline PNG dates from 2021) passes
tests.visualize.utils.test_matshow3d same passes
tests.transforms.test_orientation 'LIP' != 'LPS', 'RSP' != 'RAS' passes
tests.data.test_nifti_rw, tests.data.test_image_rw unrelated — a genuine bug, filed separately as #9068 still fails

Note the zarr failure here is not the one in #8476 (compressor cannot be used for arrays with zarr_format 3); zarr 3.3.0 also rejects chunks=True. Related: #8380, #8459, #8476.

QUICKTEST=True, which full-dep sets, does not skip any of these — I checked. CI avoids them purely through the Python pin.

torch has the same shape of gap: torch>=2.8.0 is unbounded, while CI tests 2.8.0–2.11.0 (PYTORCH_VER1..PYTORCH_VER4). A fresh environment installs 2.13.0, two minor versions past anything exercised.

Expected behavior

A contributor who follows CONTRIBUTING.md should get an environment where the suite passes, or a clear failure at install time — not green-or-red depending on the interpreter they happened to use.

Additional context

Two directions, not mutually exclusive:

  1. Bound what is known to break. Upper caps for zarr, scipy and matplotlib state the supported range explicitly instead of leaving it to interpreter-driven resolution. This is bookkeeping and it goes stale, but it makes the constraint visible.
  2. Test a modern Python. The min-dep matrix covers 3.10–3.13 with pinned torch, but full-dep — the job that installs [all] — runs only PYTHON_VER1 (3.10). A full-dep leg on PYTHON_VER3/PYTHON_VER4 would surface these at the same time contributors hit them, rather than after the fact.

The matplotlib case may want handling on its own terms: a 2021 baseline PNG compared at 0.05 tolerance will drift with any renderer change, independent of pinning policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions