From bc3dcee1979e322035b3e0ee0c556a644fff5400 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:34:52 +0100 Subject: [PATCH 01/41] Refactoring min-dep tests Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/pythonapp-min.yml | 283 ++++++++++++++++++---------- 1 file changed, 179 insertions(+), 104 deletions(-) diff --git a/.github/workflows/pythonapp-min.yml b/.github/workflows/pythonapp-min.yml index 0d147ca264..87b991c532 100644 --- a/.github/workflows/pythonapp-min.yml +++ b/.github/workflows/pythonapp-min.yml @@ -18,23 +18,45 @@ concurrency: cancel-in-progress: true jobs: - # caching of these jobs: - # - docker-py3-pip- (shared) - # - ubuntu py37 pip- - # - os-latest-pip- (shared) - min-dep-os: # min dependencies installed tests for different OS + min-dep: # min dependencies installed tests for different OS runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [windows-latest, macOS-latest, ubuntu-latest] + python-version: ['3.9'] + pytorch-version: ['2.5.1'] + include: + # Test Python versions under Ubuntu with lowest PyTorch version supported + - os: ubuntu-latest + pytorch-version: '2.5.1' + python-version: '3.10' + - os: ubuntu-latest + pytorch-version: '2.5.1' + python-version: '3.11' + - os: ubuntu-latest + pytorch-version: '2.5.1' + python-version: '3.12' + + # test PyTorch versions under Ubuntu and lowest Python version supported + - os: ubuntu-latest + python-version: '3.9' + pytorch-version: '2.6.0' + - os: ubuntu-latest + python-version: '3.9' + pytorch-version: '2.7.1' + - os: ubuntu-latest + python-version: '3.9' + pytorch-version: '2.8.0' + + timeout-minutes: 40 steps: - uses: actions/checkout@v4 - - name: Set up Python 3.9 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: ${{ matrix.python-version }} - name: Prepare pip wheel run: | which python @@ -51,10 +73,10 @@ jobs: with: path: ${{ steps.pip-cache.outputs.dir }} key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install the dependencies + - name: Install the dependencies with PyTorch ${{ matrix.pytorch-version }} run: | # min. requirements - python -m pip install torch --index-url https://download.pytorch.org/whl/cpu + python -m pip install torch==${{ matrix.pytorch-version }} python -m pip install -r requirements-min.txt python -m pip list BUILD_MONAI=0 python setup.py develop # no compile of extensions @@ -63,7 +85,7 @@ jobs: run: | python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' python -c "import monai; monai.config.print_config()" - ./runtests.sh --min + # ./runtests.sh --min shell: bash env: QUICKTEST: True @@ -71,98 +93,151 @@ jobs: NGC_ORG: ${{ secrets.NGC_ORG }} NGC_TEAM: ${{ secrets.NGC_TEAM }} - min-dep-py3: # min dependencies installed tests for different python - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ['3.9', '3.10', '3.11', '3.12'] - timeout-minutes: 40 - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Prepare pip wheel - run: | - which python - python -m pip install --user --upgrade pip setuptools wheel - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - shell: bash - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: ubuntu-latest-latest-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install the dependencies - run: | - # min. requirements - python -m pip install torch --extra-index-url https://download.pytorch.org/whl/cpu - python -m pip install -r requirements-min.txt - python -m pip list - BUILD_MONAI=0 python setup.py develop # no compile of extensions - shell: bash - - name: Run quick tests (CPU ${{ runner.os }}) - run: | - python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' - python -c "import monai; monai.config.print_config()" - ./runtests.sh --min - env: - QUICKTEST: True - NGC_API_KEY: ${{ secrets.NGC_API_KEY }} - NGC_ORG: ${{ secrets.NGC_ORG }} - NGC_TEAM: ${{ secrets.NGC_TEAM }} + # # caching of these jobs: + # # - docker-py3-pip- (shared) + # # - ubuntu py37 pip- + # # - os-latest-pip- (shared) + # min-dep-os: # min dependencies installed tests for different OS + # runs-on: ${{ matrix.os }} + # strategy: + # fail-fast: false + # matrix: + # os: [windows-latest, macOS-latest, ubuntu-latest] + # timeout-minutes: 40 + # steps: + # - uses: actions/checkout@v4 + # - name: Set up Python 3.9 + # uses: actions/setup-python@v5 + # with: + # python-version: '3.9' + # - name: Prepare pip wheel + # run: | + # which python + # python -m pip install --upgrade pip wheel + # - name: cache weekly timestamp + # id: pip-cache + # run: | + # echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + # echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT + # shell: bash + # - name: cache for pip + # uses: actions/cache@v4 + # id: cache + # with: + # path: ${{ steps.pip-cache.outputs.dir }} + # key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} + # - name: Install the dependencies + # run: | + # # min. requirements + # python -m pip install torch --index-url https://download.pytorch.org/whl/cpu + # python -m pip install -r requirements-min.txt + # python -m pip list + # BUILD_MONAI=0 python setup.py develop # no compile of extensions + # shell: bash + # - name: Run quick tests (CPU ${{ runner.os }}) + # run: | + # python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' + # python -c "import monai; monai.config.print_config()" + # ./runtests.sh --min + # shell: bash + # env: + # QUICKTEST: True + # NGC_API_KEY: ${{ secrets.NGC_API_KEY }} + # NGC_ORG: ${{ secrets.NGC_ORG }} + # NGC_TEAM: ${{ secrets.NGC_TEAM }} - min-dep-pytorch: # min dependencies installed tests for different pytorch - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - pytorch-version: ['2.5.1', '2.6.0', '2.7.1', '2.8.0'] - timeout-minutes: 40 - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.9 - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - name: Prepare pip wheel - run: | - which python - python -m pip install --user --upgrade pip setuptools wheel - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - shell: bash - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: ubuntu-latest-latest-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install the dependencies - run: | - # min. requirements - python -m pip install torch==${{ matrix.pytorch-version }} - python -m pip install -r requirements-min.txt - python -m pip list - BUILD_MONAI=0 python setup.py develop # no compile of extensions - shell: bash - - name: Run quick tests (pytorch ${{ matrix.pytorch-version }}) - run: | - python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' - python -c "import monai; monai.config.print_config()" - ./runtests.sh --min - env: - QUICKTEST: True - NGC_API_KEY: ${{ secrets.NGC_API_KEY }} - NGC_ORG: ${{ secrets.NGC_ORG }} - NGC_TEAM: ${{ secrets.NGC_TEAM }} + # min-dep-py3: # min dependencies installed tests for different python + # runs-on: ubuntu-latest + # strategy: + # fail-fast: false + # matrix: + # python-version: ['3.9', '3.10', '3.11', '3.12'] + # timeout-minutes: 40 + # steps: + # - uses: actions/checkout@v4 + # - name: Set up Python ${{ matrix.python-version }} + # uses: actions/setup-python@v5 + # with: + # python-version: ${{ matrix.python-version }} + # - name: Prepare pip wheel + # run: | + # which python + # python -m pip install --user --upgrade pip setuptools wheel + # - name: cache weekly timestamp + # id: pip-cache + # run: | + # echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + # echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT + # shell: bash + # - name: cache for pip + # uses: actions/cache@v4 + # id: cache + # with: + # path: ${{ steps.pip-cache.outputs.dir }} + # key: ubuntu-latest-latest-pip-${{ steps.pip-cache.outputs.datew }} + # - name: Install the dependencies + # run: | + # # min. requirements + # python -m pip install torch --extra-index-url https://download.pytorch.org/whl/cpu + # python -m pip install -r requirements-min.txt + # python -m pip list + # BUILD_MONAI=0 python setup.py develop # no compile of extensions + # shell: bash + # - name: Run quick tests (CPU ${{ runner.os }}) + # run: | + # python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' + # python -c "import monai; monai.config.print_config()" + # ./runtests.sh --min + # env: + # QUICKTEST: True + # NGC_API_KEY: ${{ secrets.NGC_API_KEY }} + # NGC_ORG: ${{ secrets.NGC_ORG }} + # NGC_TEAM: ${{ secrets.NGC_TEAM }} + + # min-dep-pytorch: # min dependencies installed tests for different pytorch + # runs-on: ubuntu-latest + # strategy: + # fail-fast: false + # matrix: + # pytorch-version: ['2.5.1', '2.6.0', '2.7.1', '2.8.0'] + # timeout-minutes: 40 + # steps: + # - uses: actions/checkout@v4 + # - name: Set up Python 3.9 + # uses: actions/setup-python@v5 + # with: + # python-version: '3.9' + # - name: Prepare pip wheel + # run: | + # which python + # python -m pip install --user --upgrade pip setuptools wheel + # - name: cache weekly timestamp + # id: pip-cache + # run: | + # echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + # echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT + # shell: bash + # - name: cache for pip + # uses: actions/cache@v4 + # id: cache + # with: + # path: ${{ steps.pip-cache.outputs.dir }} + # key: ubuntu-latest-latest-pip-${{ steps.pip-cache.outputs.datew }} + # - name: Install the dependencies + # run: | + # # min. requirements + # python -m pip install torch==${{ matrix.pytorch-version }} + # python -m pip install -r requirements-min.txt + # python -m pip list + # BUILD_MONAI=0 python setup.py develop # no compile of extensions + # shell: bash + # - name: Run quick tests (pytorch ${{ matrix.pytorch-version }}) + # run: | + # python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' + # python -c "import monai; monai.config.print_config()" + # ./runtests.sh --min + # env: + # QUICKTEST: True + # NGC_API_KEY: ${{ secrets.NGC_API_KEY }} + # NGC_ORG: ${{ secrets.NGC_ORG }} + # NGC_TEAM: ${{ secrets.NGC_TEAM }} From 2b9a9924d0ea66f272158cd451e477f58edbbb14 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:39:52 +0100 Subject: [PATCH 02/41] Update test Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/pythonapp-min.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/pythonapp-min.yml b/.github/workflows/pythonapp-min.yml index 87b991c532..3b70fb100b 100644 --- a/.github/workflows/pythonapp-min.yml +++ b/.github/workflows/pythonapp-min.yml @@ -1,4 +1,3 @@ -# Jenkinsfile.monai-premerge name: premerge-min on: @@ -29,27 +28,20 @@ jobs: include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest - pytorch-version: '2.5.1' python-version: '3.10' - os: ubuntu-latest - pytorch-version: '2.5.1' python-version: '3.11' - os: ubuntu-latest - pytorch-version: '2.5.1' python-version: '3.12' - # test PyTorch versions under Ubuntu and lowest Python version supported + # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest - python-version: '3.9' pytorch-version: '2.6.0' - os: ubuntu-latest - python-version: '3.9' pytorch-version: '2.7.1' - os: ubuntu-latest - python-version: '3.9' pytorch-version: '2.8.0' - timeout-minutes: 40 steps: - uses: actions/checkout@v4 From 44bc1aedc282140cdc09abe32a1f2879ff7c7814 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:43:34 +0100 Subject: [PATCH 03/41] Update test Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/pythonapp-min.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pythonapp-min.yml b/.github/workflows/pythonapp-min.yml index 3b70fb100b..8f019e1f54 100644 --- a/.github/workflows/pythonapp-min.yml +++ b/.github/workflows/pythonapp-min.yml @@ -23,8 +23,8 @@ jobs: fail-fast: false matrix: os: [windows-latest, macOS-latest, ubuntu-latest] - python-version: ['3.9'] - pytorch-version: ['2.5.1'] + python-version: '3.9' + pytorch-version: '2.5.1' include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest From 0c8c868577549356c8298d5fcc91223142c620e9 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:45:13 +0100 Subject: [PATCH 04/41] Restoring include that worked Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/pythonapp-min.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pythonapp-min.yml b/.github/workflows/pythonapp-min.yml index 8f019e1f54..48f422af26 100644 --- a/.github/workflows/pythonapp-min.yml +++ b/.github/workflows/pythonapp-min.yml @@ -23,23 +23,29 @@ jobs: fail-fast: false matrix: os: [windows-latest, macOS-latest, ubuntu-latest] - python-version: '3.9' - pytorch-version: '2.5.1' + python-version: ['3.9'] + pytorch-version: ['2.5.1'] include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest + pytorch-version: '2.5.1' python-version: '3.10' - os: ubuntu-latest + pytorch-version: '2.5.1' python-version: '3.11' - os: ubuntu-latest + pytorch-version: '2.5.1' python-version: '3.12' # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest + python-version: '3.9' pytorch-version: '2.6.0' - os: ubuntu-latest + python-version: '3.9' pytorch-version: '2.7.1' - os: ubuntu-latest + python-version: '3.9' pytorch-version: '2.8.0' timeout-minutes: 40 From e3616e4e262437f24ddfd260f89c0309b228c8d0 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:57:07 +0100 Subject: [PATCH 05/41] Renaming file Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/{pythonapp-min.yml => cicd_tests.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{pythonapp-min.yml => cicd_tests.yml} (100%) diff --git a/.github/workflows/pythonapp-min.yml b/.github/workflows/cicd_tests.yml similarity index 100% rename from .github/workflows/pythonapp-min.yml rename to .github/workflows/cicd_tests.yml From 53cb0a4f31ec054c57b0a0d59cb1f0dce5ac8a56 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:05:26 +0100 Subject: [PATCH 06/41] Combining tests Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 367 ++++++++++++++++++------------- 1 file changed, 220 insertions(+), 147 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 48f422af26..a8ccc110ec 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -1,4 +1,4 @@ -name: premerge-min +name: tests on: # quick tests for pull requests and the releasing branches @@ -17,6 +17,39 @@ concurrency: cancel-in-progress: true jobs: + static-checks: + runs-on: ubuntu-latest + strategy: + matrix: + opt: ["codeformat", "pytype", "mypy"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: '3.9' + - name: cache weekly timestamp + id: pip-cache + run: | + echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + - name: cache for pip + uses: actions/cache@v4 + id: cache + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} + - name: Install dependencies + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + python -m pip install --upgrade pip wheel + python -m pip install -r requirements-dev.txt + - name: Lint and type check + run: | + # clean up temporary files + $(pwd)/runtests.sh --build --clean + # Github actions have 2 cores, so parallelize pytype + $(pwd)/runtests.sh --build --${{ matrix.opt }} -j 2 + min-dep: # min dependencies installed tests for different OS runs-on: ${{ matrix.os }} strategy: @@ -91,151 +124,191 @@ jobs: NGC_ORG: ${{ secrets.NGC_ORG }} NGC_TEAM: ${{ secrets.NGC_TEAM }} - # # caching of these jobs: - # # - docker-py3-pip- (shared) - # # - ubuntu py37 pip- - # # - os-latest-pip- (shared) - # min-dep-os: # min dependencies installed tests for different OS - # runs-on: ${{ matrix.os }} - # strategy: - # fail-fast: false - # matrix: - # os: [windows-latest, macOS-latest, ubuntu-latest] - # timeout-minutes: 40 - # steps: - # - uses: actions/checkout@v4 - # - name: Set up Python 3.9 - # uses: actions/setup-python@v5 - # with: - # python-version: '3.9' - # - name: Prepare pip wheel - # run: | - # which python - # python -m pip install --upgrade pip wheel - # - name: cache weekly timestamp - # id: pip-cache - # run: | - # echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - # echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - # shell: bash - # - name: cache for pip - # uses: actions/cache@v4 - # id: cache - # with: - # path: ${{ steps.pip-cache.outputs.dir }} - # key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - # - name: Install the dependencies - # run: | - # # min. requirements - # python -m pip install torch --index-url https://download.pytorch.org/whl/cpu - # python -m pip install -r requirements-min.txt - # python -m pip list - # BUILD_MONAI=0 python setup.py develop # no compile of extensions - # shell: bash - # - name: Run quick tests (CPU ${{ runner.os }}) - # run: | - # python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' - # python -c "import monai; monai.config.print_config()" - # ./runtests.sh --min - # shell: bash - # env: - # QUICKTEST: True - # NGC_API_KEY: ${{ secrets.NGC_API_KEY }} - # NGC_ORG: ${{ secrets.NGC_ORG }} - # NGC_TEAM: ${{ secrets.NGC_TEAM }} + full-dep: # full dependencies installed tests for different OS + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-latest, macOS-latest, ubuntu-latest] + timeout-minutes: 120 + steps: + - if: runner.os == 'windows' + name: Config pagefile (Windows only) + uses: al-cheb/configure-pagefile-action@v1.4 + with: + minimum-size: 8GB + maximum-size: 16GB + disk-root: "D:" + - uses: actions/checkout@v4 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: '3.9' + - name: Prepare pip wheel + run: | + which python + python -m pip install --upgrade pip wheel + - name: cache weekly timestamp + id: pip-cache + run: | + echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT + shell: bash + - name: cache for pip + uses: actions/cache@v4 + id: cache + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} + - if: runner.os == 'windows' + name: Install torch cpu from pytorch.org (Windows only) + run: | + python -m pip install torch==2.5.1 torchvision==0.20.1+cpu --index-url https://download.pytorch.org/whl/cpu + - if: runner.os == 'Linux' + name: Install itk pre-release (Linux only) + run: | + python -m pip install --pre -U itk + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + - name: Install the dependencies + run: | + python -m pip install --user --upgrade pip wheel + python -m pip install torch==2.5.1 torchvision==0.20.1 + cat "requirements-dev.txt" + python -m pip install -r requirements-dev.txt + python -m pip list + python setup.py develop # test no compile installation + shell: bash + - name: Run compiled (${{ runner.os }}) + run: | + python setup.py develop --uninstall + BUILD_MONAI=1 python setup.py develop # compile the cpp extensions + shell: bash + - name: Run quick tests (CPU ${{ runner.os }}) + run: | + python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' + python -c "import monai; monai.config.print_config()" + # python -m unittest -v + env: + QUICKTEST: True + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 + + packaging: + runs-on: ubuntu-latest + env: + QUICKTEST: True + shell: bash + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: '3.9' + - name: cache weekly timestamp + id: pip-cache + run: | + echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + - name: cache for pip + uses: actions/cache@v4 + id: cache + with: + path: | + ~/.cache/pip + ~/.cache/torch + key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} + - name: Install dependencies + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + python -m pip install --user --upgrade pip setuptools wheel twine packaging + # install the latest pytorch for testing + # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated + # fresh torch installation according to pyproject.toml + python -m pip install torch>=2.5.1 torchvision + - name: Check packages + run: | + pip uninstall monai + pip list | grep -iv monai + git fetch --depth=1 origin +refs/tags/*:refs/tags/* + set -e - # min-dep-py3: # min dependencies installed tests for different python - # runs-on: ubuntu-latest - # strategy: - # fail-fast: false - # matrix: - # python-version: ['3.9', '3.10', '3.11', '3.12'] - # timeout-minutes: 40 - # steps: - # - uses: actions/checkout@v4 - # - name: Set up Python ${{ matrix.python-version }} - # uses: actions/setup-python@v5 - # with: - # python-version: ${{ matrix.python-version }} - # - name: Prepare pip wheel - # run: | - # which python - # python -m pip install --user --upgrade pip setuptools wheel - # - name: cache weekly timestamp - # id: pip-cache - # run: | - # echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - # echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - # shell: bash - # - name: cache for pip - # uses: actions/cache@v4 - # id: cache - # with: - # path: ${{ steps.pip-cache.outputs.dir }} - # key: ubuntu-latest-latest-pip-${{ steps.pip-cache.outputs.datew }} - # - name: Install the dependencies - # run: | - # # min. requirements - # python -m pip install torch --extra-index-url https://download.pytorch.org/whl/cpu - # python -m pip install -r requirements-min.txt - # python -m pip list - # BUILD_MONAI=0 python setup.py develop # no compile of extensions - # shell: bash - # - name: Run quick tests (CPU ${{ runner.os }}) - # run: | - # python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' - # python -c "import monai; monai.config.print_config()" - # ./runtests.sh --min - # env: - # QUICKTEST: True - # NGC_API_KEY: ${{ secrets.NGC_API_KEY }} - # NGC_ORG: ${{ secrets.NGC_ORG }} - # NGC_TEAM: ${{ secrets.NGC_TEAM }} + # build tar.gz and wheel + python setup.py check -m -s + python setup.py sdist bdist_wheel + python -m twine check dist/* + - run: echo "pwd=$PWD" >> $GITHUB_OUTPUT + id: root + - run: echo "tmp_dir=$(mktemp -d)" >> $GITHUB_OUTPUT + id: mktemp + - name: Move packages + run: | + printf ${{ steps.root.outputs.pwd }} + printf ${{ steps.mktemp.outputs.tmp_dir }} + # move packages to a temp dir + cp dist/monai* "${{ steps.mktemp.outputs.tmp_dir }}" + rm -r build dist monai.egg-info + cd "${{ steps.mktemp.outputs.tmp_dir }}" + ls -al + - name: Install wheel file + working-directory: ${{ steps.mktemp.outputs.tmp_dir }} + run: | + # install from wheel + python -m pip install monai*.whl + python -c 'import monai; monai.config.print_config()' 2>&1 | grep -iv "unknown" + python -c 'import monai; print(monai.__file__)' + python -m pip uninstall -y monai + rm monai*.whl + - name: Install source archive + working-directory: ${{ steps.mktemp.outputs.tmp_dir }} + run: | + # install from tar.gz + name=$(ls *.tar.gz | head -n1) + echo $name + python -m pip install $name[all] + python -c 'import monai; monai.config.print_config()' 2>&1 | grep -iv "unknown" + python -c 'import monai; print(monai.__file__)' + - name: Quick test + working-directory: ${{ steps.mktemp.outputs.tmp_dir }} + run: | + # run min tests + cp ${{ steps.root.outputs.pwd }}/requirements*.txt . + cp -r ${{ steps.root.outputs.pwd }}/tests . + ls -al + python -m pip install -r requirements-dev.txt + python -m unittest -v + env: + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - # min-dep-pytorch: # min dependencies installed tests for different pytorch - # runs-on: ubuntu-latest - # strategy: - # fail-fast: false - # matrix: - # pytorch-version: ['2.5.1', '2.6.0', '2.7.1', '2.8.0'] - # timeout-minutes: 40 - # steps: - # - uses: actions/checkout@v4 - # - name: Set up Python 3.9 - # uses: actions/setup-python@v5 - # with: - # python-version: '3.9' - # - name: Prepare pip wheel - # run: | - # which python - # python -m pip install --user --upgrade pip setuptools wheel - # - name: cache weekly timestamp - # id: pip-cache - # run: | - # echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - # echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - # shell: bash - # - name: cache for pip - # uses: actions/cache@v4 - # id: cache - # with: - # path: ${{ steps.pip-cache.outputs.dir }} - # key: ubuntu-latest-latest-pip-${{ steps.pip-cache.outputs.datew }} - # - name: Install the dependencies - # run: | - # # min. requirements - # python -m pip install torch==${{ matrix.pytorch-version }} - # python -m pip install -r requirements-min.txt - # python -m pip list - # BUILD_MONAI=0 python setup.py develop # no compile of extensions - # shell: bash - # - name: Run quick tests (pytorch ${{ matrix.pytorch-version }}) - # run: | - # python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' - # python -c "import monai; monai.config.print_config()" - # ./runtests.sh --min - # env: - # QUICKTEST: True - # NGC_API_KEY: ${{ secrets.NGC_API_KEY }} - # NGC_ORG: ${{ secrets.NGC_ORG }} - # NGC_TEAM: ${{ secrets.NGC_TEAM }} + build-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: '3.9' + - name: cache weekly timestamp + id: pip-cache + run: | + echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + - name: cache for pip + uses: actions/cache@v4 + id: cache + with: + path: | + ~/.cache/pip + ~/.cache/torch + key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip wheel + python -m pip install -r docs/requirements.txt + - name: Make html + run: | + cd docs/ + make clean + make html 2>&1 | tee tmp_log + if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "found errors"; grep "ERROR:" tmp_log; exit 1; fi + sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 + if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "found warnings"; grep "WARNING:" tmp_log; exit 1; fi + shell: bash From 28f06ff8e75b4c617ccd163f183c78f8cff5e618 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:06:16 +0100 Subject: [PATCH 07/41] Removing combined file Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/pythonapp.yml | 245 -------------------------------- 1 file changed, 245 deletions(-) delete mode 100644 .github/workflows/pythonapp.yml diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml deleted file mode 100644 index c68c879231..0000000000 --- a/.github/workflows/pythonapp.yml +++ /dev/null @@ -1,245 +0,0 @@ -# Jenkinsfile.monai-premerge -name: premerge - -on: - # quick tests for pull requests and the releasing branches - push: - branches: - - dev - - main - - releasing/* - pull_request: - head_ref-ignore: - - dev - -concurrency: - # automatically cancel the previously triggered workflows when there's a newer version - group: build-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - # caching of these jobs: - # - docker-py3-pip- (shared) - # - ubuntu py37 pip- - # - os-latest-pip- (shared) - flake8-py3: - runs-on: ubuntu-latest - strategy: - matrix: - opt: ["codeformat", "pytype", "mypy"] - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.9 - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install dependencies - run: | - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - python -m pip install --upgrade pip wheel - python -m pip install -r requirements-dev.txt - - name: Lint and type check - run: | - # clean up temporary files - $(pwd)/runtests.sh --build --clean - # Github actions have 2 cores, so parallelize pytype - $(pwd)/runtests.sh --build --${{ matrix.opt }} -j 2 - - quick-py3: # full dependencies installed tests for different OS - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [windows-latest, macOS-latest, ubuntu-latest] - timeout-minutes: 120 - steps: - - if: runner.os == 'windows' - name: Config pagefile (Windows only) - uses: al-cheb/configure-pagefile-action@v1.4 - with: - minimum-size: 8GB - maximum-size: 16GB - disk-root: "D:" - - uses: actions/checkout@v4 - - name: Set up Python 3.9 - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - name: Prepare pip wheel - run: | - which python - python -m pip install --upgrade pip wheel - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - shell: bash - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - - if: runner.os == 'windows' - name: Install torch cpu from pytorch.org (Windows only) - run: | - python -m pip install torch==2.5.1 torchvision==0.20.1+cpu --index-url https://download.pytorch.org/whl/cpu - - if: runner.os == 'Linux' - name: Install itk pre-release (Linux only) - run: | - python -m pip install --pre -U itk - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - - name: Install the dependencies - run: | - python -m pip install --user --upgrade pip wheel - python -m pip install torch==2.5.1 torchvision==0.20.1 - cat "requirements-dev.txt" - python -m pip install -r requirements-dev.txt - python -m pip list - python setup.py develop # test no compile installation - shell: bash - - name: Run compiled (${{ runner.os }}) - run: | - python setup.py develop --uninstall - BUILD_MONAI=1 python setup.py develop # compile the cpp extensions - shell: bash - - name: Run quick tests (CPU ${{ runner.os }}) - run: | - python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' - python -c "import monai; monai.config.print_config()" - python -m unittest -v - env: - QUICKTEST: True - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - - packaging: - runs-on: ubuntu-latest - env: - QUICKTEST: True - shell: bash - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Set up Python 3.9 - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: | - ~/.cache/pip - ~/.cache/torch - key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install dependencies - run: | - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - python -m pip install --user --upgrade pip setuptools wheel twine packaging - # install the latest pytorch for testing - # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated - # fresh torch installation according to pyproject.toml - python -m pip install torch>=2.5.1 torchvision - - name: Check packages - run: | - pip uninstall monai - pip list | grep -iv monai - git fetch --depth=1 origin +refs/tags/*:refs/tags/* - set -e - - # build tar.gz and wheel - python setup.py check -m -s - python setup.py sdist bdist_wheel - python -m twine check dist/* - - run: echo "pwd=$PWD" >> $GITHUB_OUTPUT - id: root - - run: echo "tmp_dir=$(mktemp -d)" >> $GITHUB_OUTPUT - id: mktemp - - name: Move packages - run: | - printf ${{ steps.root.outputs.pwd }} - printf ${{ steps.mktemp.outputs.tmp_dir }} - # move packages to a temp dir - cp dist/monai* "${{ steps.mktemp.outputs.tmp_dir }}" - rm -r build dist monai.egg-info - cd "${{ steps.mktemp.outputs.tmp_dir }}" - ls -al - - name: Install wheel file - working-directory: ${{ steps.mktemp.outputs.tmp_dir }} - run: | - # install from wheel - python -m pip install monai*.whl - python -c 'import monai; monai.config.print_config()' 2>&1 | grep -iv "unknown" - python -c 'import monai; print(monai.__file__)' - python -m pip uninstall -y monai - rm monai*.whl - - name: Install source archive - working-directory: ${{ steps.mktemp.outputs.tmp_dir }} - run: | - # install from tar.gz - name=$(ls *.tar.gz | head -n1) - echo $name - python -m pip install $name[all] - python -c 'import monai; monai.config.print_config()' 2>&1 | grep -iv "unknown" - python -c 'import monai; print(monai.__file__)' - - name: Quick test - working-directory: ${{ steps.mktemp.outputs.tmp_dir }} - run: | - # run min tests - cp ${{ steps.root.outputs.pwd }}/requirements*.txt . - cp -r ${{ steps.root.outputs.pwd }}/tests . - ls -al - python -m pip install -r requirements-dev.txt - python -m unittest -v - env: - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - - build-docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.9 - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: | - ~/.cache/pip - ~/.cache/torch - key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip wheel - python -m pip install -r docs/requirements.txt - - name: Make html - run: | - cd docs/ - make clean - make html 2>&1 | tee tmp_log - if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "found errors"; grep "ERROR:" tmp_log; exit 1; fi - sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 - if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "found warnings"; grep "WARNING:" tmp_log; exit 1; fi - shell: bash From 4d8807555e420f0aa4f1adfa52c599fb2913fb0f Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:38:11 +0100 Subject: [PATCH 08/41] Script update Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index a8ccc110ec..25870c4e9a 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -13,11 +13,15 @@ on: concurrency: # automatically cancel the previously triggered workflows when there's a newer version - group: build-min-${{ github.event.pull_request.number || github.ref }} + group: cicd-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +# These jobs run the CICD tests, type checking, and testing packaging and documentation generation. These use the +# minimum supported versions of Python and PyTorch in many places hard-coded as literals, so when support is dropped +# for a version it is important to go through all jobs and check the versions they use are correct. + jobs: - static-checks: + static-checks: # Perform static type and other checks using runtests.sh runs-on: ubuntu-latest strategy: matrix: @@ -43,14 +47,14 @@ jobs: find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; python -m pip install --upgrade pip wheel python -m pip install -r requirements-dev.txt - - name: Lint and type check + - name: Lint and type check with "./runtests.sh --build --${{ matrix.opt }}" run: | # clean up temporary files $(pwd)/runtests.sh --build --clean - # Github actions have 2 cores, so parallelize pytype - $(pwd)/runtests.sh --build --${{ matrix.opt }} -j 2 + # Github actions have multiple cores, so parallelize pytype + $(pwd)/runtests.sh --build --${{ matrix.opt }} -j $(nproc --all) - min-dep: # min dependencies installed tests for different OS + min-dep: # Test with minumum dependencies installed for different OS, Python, and PyTorch combinations runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -124,7 +128,7 @@ jobs: NGC_ORG: ${{ secrets.NGC_ORG }} NGC_TEAM: ${{ secrets.NGC_TEAM }} - full-dep: # full dependencies installed tests for different OS + full-dep: # Test with full dependencies installed for different OS runners runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -192,7 +196,7 @@ jobs: QUICKTEST: True PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - packaging: + packaging: # Test package generation runs-on: ubuntu-latest env: QUICKTEST: True @@ -279,7 +283,7 @@ jobs: env: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - build-docs: + build-docs: # Test building documentation runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -308,7 +312,7 @@ jobs: cd docs/ make clean make html 2>&1 | tee tmp_log - if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "found errors"; grep "ERROR:" tmp_log; exit 1; fi + if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "Found errors:"; grep "ERROR:" tmp_log; exit 1; fi sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 - if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "found warnings"; grep "WARNING:" tmp_log; exit 1; fi - shell: bash + if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "Found warnings:"; grep "WARNING:" tmp_log; exit 1; fi + shell: bash \ No newline at end of file From d7e1451086822cf4f39a0d6357621451d4926ca4 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:55:12 +0100 Subject: [PATCH 09/41] Fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 25870c4e9a..2c47923beb 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -16,7 +16,7 @@ concurrency: group: cicd-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -# These jobs run the CICD tests, type checking, and testing packaging and documentation generation. These use the +# These jobs run the CICD tests, type checking, and testing packaging and documentation generation. These use the # minimum supported versions of Python and PyTorch in many places hard-coded as literals, so when support is dropped # for a version it is important to go through all jobs and check the versions they use are correct. @@ -53,7 +53,7 @@ jobs: $(pwd)/runtests.sh --build --clean # Github actions have multiple cores, so parallelize pytype $(pwd)/runtests.sh --build --${{ matrix.opt }} -j $(nproc --all) - + min-dep: # Test with minumum dependencies installed for different OS, Python, and PyTorch combinations runs-on: ${{ matrix.os }} strategy: @@ -315,4 +315,4 @@ jobs: if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "Found errors:"; grep "ERROR:" tmp_log; exit 1; fi sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "Found warnings:"; grep "WARNING:" tmp_log; exit 1; fi - shell: bash \ No newline at end of file + shell: bash From 7fc61070bef6540afbd8de7a3034b87de3a1057d Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:21:57 +0100 Subject: [PATCH 10/41] Update with GPU runner Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 2c47923beb..1af6a783bd 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -59,7 +59,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest, macOS-latest, ubuntu-latest] + os: [windows-latest, macOS-latest, ubuntu-latest, linux-gpu-runner] python-version: ['3.9'] pytorch-version: ['2.5.1'] include: @@ -110,6 +110,7 @@ jobs: key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - name: Install the dependencies with PyTorch ${{ matrix.pytorch-version }} run: | + /usr/bin/env nvidia-smi &> /dev/null || echo "No nvidia-smi found" # min. requirements python -m pip install torch==${{ matrix.pytorch-version }} python -m pip install -r requirements-min.txt From 3a2381c646bc526cddab79c52219fb69d525dc1a Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:32:46 +0100 Subject: [PATCH 11/41] Whoops Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 1af6a783bd..1fbc2e6376 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -110,7 +110,7 @@ jobs: key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - name: Install the dependencies with PyTorch ${{ matrix.pytorch-version }} run: | - /usr/bin/env nvidia-smi &> /dev/null || echo "No nvidia-smi found" + /usr/bin/env nvidia-smi 2> /dev/null || echo "No nvidia-smi found" # min. requirements python -m pip install torch==${{ matrix.pytorch-version }} python -m pip install -r requirements-min.txt From 95b731071258c9e57d99fa3aaa279eb8dbcc6dbd Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:42:02 +0100 Subject: [PATCH 12/41] Adding GPU check Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 1fbc2e6376..139a755261 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -66,13 +66,7 @@ jobs: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest pytorch-version: '2.5.1' - python-version: '3.10' - - os: ubuntu-latest - pytorch-version: '2.5.1' - python-version: '3.11' - - os: ubuntu-latest - pytorch-version: '2.5.1' - python-version: '3.12' + python-version: ['3.10', '3.11', '3.12'] # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest @@ -108,16 +102,21 @@ jobs: with: path: ${{ steps.pip-cache.outputs.dir }} key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install the dependencies with PyTorch ${{ matrix.pytorch-version }} + - name: Install the minimum dependencies run: | - /usr/bin/env nvidia-smi 2> /dev/null || echo "No nvidia-smi found" # min. requirements python -m pip install torch==${{ matrix.pytorch-version }} python -m pip install -r requirements-min.txt python -m pip list BUILD_MONAI=0 python setup.py develop # no compile of extensions shell: bash - - name: Run quick tests (CPU ${{ runner.os }}) + - if: matrix.os == 'linux-gpu-runner' + name: Print GPU Info + run: | + nvidia-smi + python -c 'import torch; print(torch.rand(2,2).to("cuda:0"))' + shell: bash + - name: Run quick tests run: | python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' python -c "import monai; monai.config.print_config()" @@ -174,7 +173,7 @@ jobs: run: | python -m pip install --pre -U itk find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - - name: Install the dependencies + - name: Install the complete dependencies run: | python -m pip install --user --upgrade pip wheel python -m pip install torch==2.5.1 torchvision==0.20.1 @@ -188,7 +187,7 @@ jobs: python setup.py develop --uninstall BUILD_MONAI=1 python setup.py develop # compile the cpp extensions shell: bash - - name: Run quick tests (CPU ${{ runner.os }}) + - name: Run quick tests run: | python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' python -c "import monai; monai.config.print_config()" From d8128f4b4208615bd981441acf8a06bfde8a8f58 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:43:20 +0100 Subject: [PATCH 13/41] Fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 139a755261..b48b8468f4 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -66,7 +66,13 @@ jobs: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest pytorch-version: '2.5.1' - python-version: ['3.10', '3.11', '3.12'] + python-version: '3.10' + - os: ubuntu-latest + pytorch-version: '2.5.1' + python-version: '3.11' + - os: ubuntu-latest + pytorch-version: '2.5.1' + python-version: '3.12' # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest From 55c351cc5021d131b43b022fdd7c6bc65692c95b Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Wed, 12 Nov 2025 14:35:27 +0000 Subject: [PATCH 14/41] Update with merge Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index a8e1829520..3de13a2da2 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -87,15 +87,16 @@ jobs: timeout-minutes: 40 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Prepare pip wheel run: | which python python -m pip install --upgrade pip wheel + python -m pip install --user more-itertools>=8.0 - name: cache weekly timestamp id: pip-cache run: | @@ -158,6 +159,7 @@ jobs: run: | which python python -m pip install --upgrade pip wheel + python -m pip install --user more-itertools>=8.0 - name: cache weekly timestamp id: pip-cache run: | From 4d58d5b759e993f4b67d71555e06197556dba931 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Wed, 12 Nov 2025 14:45:35 +0000 Subject: [PATCH 15/41] Removing Python 3.9 tests, adding Python 3.13 and Pytorch 2.9 tests Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 3de13a2da2..8eb70e2533 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -28,10 +28,10 @@ jobs: opt: ["codeformat", "pytype", "mypy"] steps: - uses: actions/checkout@v5 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: cache weekly timestamp id: pip-cache run: | @@ -59,31 +59,31 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest, macOS-latest, ubuntu-latest, linux-gpu-runner] - python-version: ['3.9'] - pytorch-version: ['2.5.1'] + os: [windows-latest, macOS-latest, ubuntu-latest] + python-version: ['3.10'] + pytorch-version: ['2.6.0'] include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest - pytorch-version: '2.5.1' - python-version: '3.10' - - os: ubuntu-latest - pytorch-version: '2.5.1' + pytorch-version: '2.6.0' python-version: '3.11' - os: ubuntu-latest - pytorch-version: '2.5.1' + pytorch-version: '2.6.0' python-version: '3.12' - - # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest - python-version: '3.9' pytorch-version: '2.6.0' + python-version: '3.13' + + # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest - python-version: '3.9' + python-version: '3.10' pytorch-version: '2.7.1' - os: ubuntu-latest - python-version: '3.9' + python-version: '3.10' pytorch-version: '2.8.0' + - os: ubuntu-latest + python-version: '3.10' + pytorch-version: '2.9.0' timeout-minutes: 40 steps: @@ -151,10 +151,10 @@ jobs: maximum-size: 16GB disk-root: "D:" - uses: actions/checkout@v5 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: Prepare pip wheel run: | which python @@ -213,10 +213,10 @@ jobs: - uses: actions/checkout@v5 with: fetch-depth: 0 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: cache weekly timestamp id: pip-cache run: | @@ -295,10 +295,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: cache weekly timestamp id: pip-cache run: | From 29a2ff67010b0108b8386320a7928b77a757a0e2 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Wed, 12 Nov 2025 15:03:31 +0000 Subject: [PATCH 16/41] Further changes for 3.9 to 3.10 Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/conda.yml | 2 +- .github/workflows/cron-ngc-bundle.yml | 4 +- .github/workflows/docker.yml | 4 +- .github/workflows/pythonapp-gpu.yml | 2 +- .github/workflows/release.yml | 12 +++--- .github/workflows/setupapp.yml | 6 +-- .github/workflows/weekly-preview.yml | 8 ++-- docs/.readthedocs.yaml | 2 +- docs/requirements.txt | 2 +- docs/source/installation.md | 4 +- json_test.py | 55 +++++++++++++++++++++++++++ monai/apps/auto3dseg/auto_runner.py | 2 +- monai/auto3dseg/utils.py | 3 +- requirements-dev.txt | 4 +- setup.cfg | 15 ++++---- 15 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 json_test.py diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index fd680e14c8..bedbcec548 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.9", "3.10"] + python-version: ["3.10", "3.11"] runs-on: ${{ matrix.os }} timeout-minutes: 46 # equal to max + 3*std over the last 600 successful runs env: diff --git a/.github/workflows/cron-ngc-bundle.yml b/.github/workflows/cron-ngc-bundle.yml index c9bebc7bff..141a0b9acc 100644 --- a/.github/workflows/cron-ngc-bundle.yml +++ b/.github/workflows/cron-ngc-bundle.yml @@ -18,10 +18,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: cache weekly timestamp id: pip-cache run: echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4741dca858..5dd6fbe9f6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -26,10 +26,10 @@ jobs: with: ref: dev fetch-depth: 0 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - shell: bash run: | git describe diff --git a/.github/workflows/pythonapp-gpu.yml b/.github/workflows/pythonapp-gpu.yml index 347b49bba3..8639127b4d 100644 --- a/.github/workflows/pythonapp-gpu.yml +++ b/.github/workflows/pythonapp-gpu.yml @@ -53,7 +53,7 @@ jobs: if [ ${{ matrix.environment }} = "PT230+CUDA124" ] then - PYVER=3.9 PYSFX=3 DISTUTILS=python3-distutils && \ + PYVER=3.10 PYSFX=3 DISTUTILS=python3-distutils && \ apt-get update && apt-get install -y --no-install-recommends \ curl \ pkg-config \ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3a8e8ffdf6..cfc2d4b7a4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v5 with: @@ -64,14 +64,14 @@ jobs: env: QUICKTEST: True - - if: matrix.python-version == '3.9' && startsWith(github.ref, 'refs/tags/') + - if: matrix.python-version == '3.10' && startsWith(github.ref, 'refs/tags/') name: Upload artifacts uses: actions/upload-artifact@v5 with: name: dist path: dist/ - - if: matrix.python-version == '3.9' && startsWith(github.ref, 'refs/tags/') + - if: matrix.python-version == '3.10' && startsWith(github.ref, 'refs/tags/') name: Check artifacts run: | ls -al dist/ @@ -79,7 +79,7 @@ jobs: ls -al dist/ # remove publishing to Test PyPI as it is moved to blossom - # - if: matrix.python-version == '3.9' && startsWith(github.ref, 'refs/tags/') + # - if: matrix.python-version == '3.10' && startsWith(github.ref, 'refs/tags/') # name: Publish to Test PyPI # uses: pypa/gh-action-pypi-publish@release/v1 # with: @@ -97,10 +97,10 @@ jobs: # full history so that we can git describe with: fetch-depth: 0 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - shell: bash run: | find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; diff --git a/.github/workflows/setupapp.yml b/.github/workflows/setupapp.yml index acd72eaf6f..912d254334 100644 --- a/.github/workflows/setupapp.yml +++ b/.github/workflows/setupapp.yml @@ -81,7 +81,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v5 with: @@ -127,10 +127,10 @@ jobs: install: # pip install from github url, the default branch is dev runs-on: ubuntu-latest steps: - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: cache weekly timestamp id: pip-cache run: | diff --git a/.github/workflows/weekly-preview.yml b/.github/workflows/weekly-preview.yml index 93d6f67f09..67a712fe2d 100644 --- a/.github/workflows/weekly-preview.yml +++ b/.github/workflows/weekly-preview.yml @@ -12,10 +12,10 @@ jobs: opt: ["codeformat", "pytype", "mypy"] steps: - uses: actions/checkout@v5 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: cache weekly timestamp id: pip-cache run: | @@ -46,10 +46,10 @@ jobs: with: ref: dev fetch-depth: 0 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: - python-version: '3.9' + python-version: '3.10' - name: Install setuptools run: | python -m pip install --user --upgrade setuptools wheel packaging diff --git a/docs/.readthedocs.yaml b/docs/.readthedocs.yaml index d2e2ee74a5..0212e806e8 100644 --- a/docs/.readthedocs.yaml +++ b/docs/.readthedocs.yaml @@ -6,7 +6,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.9" + python: "3.10" sphinx: configuration: docs/source/conf.py python: diff --git a/docs/requirements.txt b/docs/requirements.txt index f44f41a6b2..7f4db0f704 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -6,7 +6,7 @@ itk>=5.2 nibabel parameterized scikit-image>=0.19.0 -scipy>=1.12.0; python_version >= '3.9' +scipy>=1.12.0 tensorboard commonmark==0.9.1 recommonmark==0.6.0 diff --git a/docs/source/installation.md b/docs/source/installation.md index b8befc10b4..bf7fa56138 100644 --- a/docs/source/installation.md +++ b/docs/source/installation.md @@ -19,7 +19,7 @@ --- -MONAI's core functionality is written in Python 3 (>= 3.9) and only requires [Numpy](https://numpy.org/) and [Pytorch](https://pytorch.org/). +MONAI's core functionality is written in Python 3 (>= 3.10) and only requires [Numpy](https://numpy.org/) and [Pytorch](https://pytorch.org/). The package is currently distributed via Github as the primary source code repository, and the Python package index (PyPI). The pre-built Docker images are made available on DockerHub. @@ -245,7 +245,7 @@ this will install PyTorch as well as `pytorch-cuda`, please follow https://pytor ```bash git clone https://github.com/Project-MONAI/MONAI.git cd MONAI/ -conda create -n python= # eg 3.9 +conda create -n python= # eg 3.10 conda env update -n -f environment-dev.yml ``` diff --git a/json_test.py b/json_test.py new file mode 100644 index 0000000000..7111a67223 --- /dev/null +++ b/json_test.py @@ -0,0 +1,55 @@ +from functools import partial +import numpy as np +import torch +import json + + +JSON_NUMPY_TYPE = "numpy" +JSON_TORCH_TYPE = "torch" + + +class SafeEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, np.ndarray): + return {"__type__": JSON_NUMPY_TYPE, "dtype": str(obj.dtype), "data": obj.tolist()} + + if isinstance(obj, torch.Tensor): + return { + "__type__": JSON_TORCH_TYPE, + "dtype": str(obj.dtype).replace("torch.", ""), + "data": obj.detach().cpu().numpy().tolist(), + } + + return super().default(obj) + + +def json_decode_hook(item): + datatype = item.get("__type__", "") + if datatype == JSON_NUMPY_TYPE: + return np.array(item["data"], dtype=np.dtype(item["dtype"])) + elif datatype == JSON_TORCH_TYPE: + return torch.tensor(item["data"], dtype=getattr(torch, item["dtype"])) + else: + return item + + +json_dumps = partial(json.dumps, cls=SafeEncoder) +json_loads = partial(json.loads, object_hook=json_decode_hook) + +item = { + "np": np.random.rand(5, 5), + "pt": torch.rand(4, 4), + "int": 123, + "list": [1, 2, 3], + "tuple": (1, 2, 3), + "dict": {"one": 1, "two": 2}, +} + +print(item) +print() + +dump_item = json_dumps(item) + +loaded_item = json_loads(dump_item) + +print(loaded_item) diff --git a/monai/apps/auto3dseg/auto_runner.py b/monai/apps/auto3dseg/auto_runner.py index 28ba2a88f9..9acab5d441 100644 --- a/monai/apps/auto3dseg/auto_runner.py +++ b/monai/apps/auto3dseg/auto_runner.py @@ -560,7 +560,7 @@ def set_device_info( cmd_prefix: command line prefix for subprocess running in BundleAlgo and EnsembleRunner. Default using env "CMD_PREFIX" or None, examples are: - - single GPU/CPU or multinode bcprun: "python " or "/opt/conda/bin/python3.9 ", + - single GPU/CPU or multinode bcprun: "python " or "/opt/conda/bin/python3.10", - single node multi-GPU running "torchrun --nnodes=1 --nproc_per_node=2 " If user define this prefix, please make sure --nproc_per_node matches cuda_visible_device or diff --git a/monai/auto3dseg/utils.py b/monai/auto3dseg/utils.py index 211f23c415..8b5dab75b5 100644 --- a/monai/auto3dseg/utils.py +++ b/monai/auto3dseg/utils.py @@ -407,7 +407,8 @@ def _prepare_cmd_default(cmd: str, cmd_prefix: str | None = None, **kwargs: Any) Args: cmd: the command or script to run in the distributed job. - cmd_prefix: the command prefix to run the script, e.g., "python", "python -m", "python3", "/opt/conda/bin/python3.9 ". + cmd_prefix: the command prefix to run the script, + e.g., "python", "python -m", "python3", "/opt/conda/bin/python3.10". kwargs: the keyword arguments to be passed to the script. Returns: diff --git a/requirements-dev.txt b/requirements-dev.txt index ff234c856e..e1422ea8ce 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ -r requirements-min.txt pytorch-ignite==0.4.11 gdown>=4.7.3 -scipy>=1.12.0; python_version >= '3.9' +scipy>=1.12.0 itk>=5.2 nibabel pillow!=8.3.0 # https://github.com/python-pillow/Pillow/issues/5571 @@ -27,7 +27,7 @@ ninja torchio torchvision psutil -cucim-cu12; platform_system == "Linux" and python_version >= "3.9" and python_version <= "3.10" +cucim-cu12; platform_system == "Linux" and python_version <= "3.10" openslide-python openslide-bin imagecodecs; platform_system == "Linux" or platform_system == "Darwin" diff --git a/setup.cfg b/setup.cfg index b3949213c2..5011b6382e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,9 +21,10 @@ classifiers = Intended Audience :: Healthcare Industry Programming Language :: C++ Programming Language :: Python :: 3 - Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 Topic :: Scientific/Engineering Topic :: Scientific/Engineering :: Artificial Intelligence Topic :: Scientific/Engineering :: Medical Science Apps. @@ -33,7 +34,7 @@ classifiers = Typing :: Typed [options] -python_requires = >= 3.9 +python_requires = >= 3.10 # for compiling and develop setup only # no need to specify the versions so that we could # compile for multiple targeted versions. @@ -42,7 +43,7 @@ setup_requires = ninja packaging install_requires = - torch>=2.4.1 + torch>=2.6.0 numpy>=1.24,<3.0 [options.extras_require] @@ -50,7 +51,7 @@ all = nibabel ninja scikit-image>=0.14.2 - scipy>=1.12.0; python_version >= '3.9' + scipy>=1.12.0 pillow tensorboard gdown>=4.7.3 @@ -61,7 +62,7 @@ all = tqdm>=4.47.0 lmdb psutil - cucim-cu12; platform_system == "Linux" and python_version >= '3.9' and python_version <= '3.10' + cucim-cu12; platform_system == "Linux" and python_version <= '3.10' openslide-python openslide-bin tifffile; platform_system == "Linux" or platform_system == "Darwin" @@ -95,7 +96,7 @@ ninja = skimage = scikit-image>=0.14.2 scipy = - scipy>=1.12.0; python_version >= '3.9' + scipy>=1.12.0 pillow = pillow!=8.3.0 tensorboard = @@ -117,7 +118,7 @@ lmdb = psutil = psutil cucim = - cucim-cu12; platform_system == "Linux" and python_version >= '3.9' and python_version <= '3.10' + cucim-cu12; platform_system == "Linux" and python_version <= '3.10' openslide = openslide-python openslide-bin From d309fe9ce2ddbb58e8c04975632cffb4980049ac Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 15:04:23 +0000 Subject: [PATCH 17/41] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- monai/auto3dseg/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/auto3dseg/utils.py b/monai/auto3dseg/utils.py index 8b5dab75b5..ff1be57629 100644 --- a/monai/auto3dseg/utils.py +++ b/monai/auto3dseg/utils.py @@ -407,7 +407,7 @@ def _prepare_cmd_default(cmd: str, cmd_prefix: str | None = None, **kwargs: Any) Args: cmd: the command or script to run in the distributed job. - cmd_prefix: the command prefix to run the script, + cmd_prefix: the command prefix to run the script, e.g., "python", "python -m", "python3", "/opt/conda/bin/python3.10". kwargs: the keyword arguments to be passed to the script. From aa3080be6df90ba2dd9972d997999702fd5f7063 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Wed, 12 Nov 2025 15:18:35 +0000 Subject: [PATCH 18/41] Whoops Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- json_test.py | 55 ---------------------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 json_test.py diff --git a/json_test.py b/json_test.py deleted file mode 100644 index 7111a67223..0000000000 --- a/json_test.py +++ /dev/null @@ -1,55 +0,0 @@ -from functools import partial -import numpy as np -import torch -import json - - -JSON_NUMPY_TYPE = "numpy" -JSON_TORCH_TYPE = "torch" - - -class SafeEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, np.ndarray): - return {"__type__": JSON_NUMPY_TYPE, "dtype": str(obj.dtype), "data": obj.tolist()} - - if isinstance(obj, torch.Tensor): - return { - "__type__": JSON_TORCH_TYPE, - "dtype": str(obj.dtype).replace("torch.", ""), - "data": obj.detach().cpu().numpy().tolist(), - } - - return super().default(obj) - - -def json_decode_hook(item): - datatype = item.get("__type__", "") - if datatype == JSON_NUMPY_TYPE: - return np.array(item["data"], dtype=np.dtype(item["dtype"])) - elif datatype == JSON_TORCH_TYPE: - return torch.tensor(item["data"], dtype=getattr(torch, item["dtype"])) - else: - return item - - -json_dumps = partial(json.dumps, cls=SafeEncoder) -json_loads = partial(json.loads, object_hook=json_decode_hook) - -item = { - "np": np.random.rand(5, 5), - "pt": torch.rand(4, 4), - "int": 123, - "list": [1, 2, 3], - "tuple": (1, 2, 3), - "dict": {"one": 1, "two": 2}, -} - -print(item) -print() - -dump_item = json_dumps(item) - -loaded_item = json_loads(dump_item) - -print(loaded_item) From fabc53869b4f34c0dd7baa4c503d0098db53b52f Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:21:06 +0000 Subject: [PATCH 19/41] Adding ignore paths to stop tests triggering when documentation changed Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/build_docs.yml | 55 ++++++++++++++++++++++++++++++++ .github/workflows/cicd_tests.yml | 42 +++++------------------- 2 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/build_docs.yml diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml new file mode 100644 index 0000000000..178ddb728d --- /dev/null +++ b/.github/workflows/build_docs.yml @@ -0,0 +1,55 @@ +name: build_docs + +on: + # build docs test for pull requests and the releasing branches + push: + branches: + - dev + - main + - releasing/* + pull_request: + head_ref-ignore: + - dev + +concurrency: + # automatically cancel the previously triggered workflows when there's a newer version + group: cicd-tests-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +# This test is for building documentation on any relevant push or PR. This ensures that any changes to docs or source +# files is tested for correct doc building, whereas functional tests can be deferred if only docs were modified. + +jobs: + build-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Set up Python 3.10 + uses: actions/setup-python@v6 + with: + python-version: '3.10' + - name: cache weekly timestamp + id: pip-cache + run: | + echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + - name: cache for pip + uses: actions/cache@v4 + id: cache + with: + path: | + ~/.cache/pip + ~/.cache/torch + key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip wheel + python -m pip install -r docs/requirements.txt + - name: Make html + run: | + cd docs/ + make clean + make html 2>&1 | tee tmp_log + if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "Found errors:"; grep "ERROR:" tmp_log; exit 1; fi + sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 + if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "Found warnings:"; grep "WARNING:" tmp_log; exit 1; fi + shell: bash diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 8eb70e2533..3a732cfedc 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -7,9 +7,17 @@ on: - dev - main - releasing/* + paths-ignore: # skip if only docs are modified + - '**.md' + - '**.rst' + - 'docs/**' pull_request: head_ref-ignore: - dev + paths-ignore: # skip if only docs are modified + - '**.md' + - '**.rst' + - 'docs/**' concurrency: # automatically cancel the previously triggered workflows when there's a newer version @@ -290,37 +298,3 @@ jobs: python -m unittest -v env: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - - build-docs: # Test building documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - name: Set up Python 3.10 - uses: actions/setup-python@v6 - with: - python-version: '3.10' - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: | - ~/.cache/pip - ~/.cache/torch - key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip wheel - python -m pip install -r docs/requirements.txt - - name: Make html - run: | - cd docs/ - make clean - make html 2>&1 | tee tmp_log - if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "Found errors:"; grep "ERROR:" tmp_log; exit 1; fi - sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 - if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "Found warnings:"; grep "WARNING:" tmp_log; exit 1; fi - shell: bash From 89087256803e0d10ac4aa845d2c01235a92f70b9 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:48:47 +0000 Subject: [PATCH 20/41] Experimental image cleaning Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/build_docs.yml | 13 +++++++++++++ .github/workflows/cicd_tests.yml | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml index 178ddb728d..24346d7feb 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_docs.yml @@ -23,15 +23,26 @@ jobs: build-docs: runs-on: ubuntu-latest steps: + - name: Clean unused tools + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + rm -rf /usr/share/dotnet + rm -rf /usr/local/lib/android + rm -rf /opt/ghc /usr/local/.ghcup + docker system prune -f + - uses: actions/checkout@v5 + - name: Set up Python 3.10 uses: actions/setup-python@v6 with: python-version: '3.10' + - name: cache weekly timestamp id: pip-cache run: | echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT + - name: cache for pip uses: actions/cache@v4 id: cache @@ -40,10 +51,12 @@ jobs: ~/.cache/pip ~/.cache/torch key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} + - name: Install dependencies run: | python -m pip install --upgrade pip wheel python -m pip install -r docs/requirements.txt + - name: Make html run: | cd docs/ diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index ccf9335772..52c3339704 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -297,4 +297,5 @@ jobs: python -m pip install -r requirements-dev.txt python -m unittest -v env: - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 \ No newline at end of file + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 + \ No newline at end of file From 18f640d3096a859e1a5d0dd65af12ea088fde543 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:55:53 +0000 Subject: [PATCH 21/41] Fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/build_docs.yml | 10 +++++----- .github/workflows/cicd_tests.yml | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml index 24346d7feb..c0b597201d 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_docs.yml @@ -26,10 +26,10 @@ jobs: - name: Clean unused tools run: | find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - rm -rf /usr/share/dotnet - rm -rf /usr/local/lib/android - rm -rf /opt/ghc /usr/local/.ghcup - docker system prune -f + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc /usr/local/.ghcup + sudo docker system prune -f - uses: actions/checkout@v5 @@ -56,7 +56,7 @@ jobs: run: | python -m pip install --upgrade pip wheel python -m pip install -r docs/requirements.txt - + - name: Make html run: | cd docs/ diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 52c3339704..b9f7d6019c 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -298,4 +298,3 @@ jobs: python -m unittest -v env: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 - \ No newline at end of file From 4ec28007765611e4b78f16e4021b717889ebc406 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 7 Dec 2025 20:09:04 +0000 Subject: [PATCH 22/41] Always import npt Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- monai/metrics/average_precision.py | 6 ++---- monai/metrics/rocauc.py | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/monai/metrics/average_precision.py b/monai/metrics/average_precision.py index 53c41aeca5..ba0213953c 100644 --- a/monai/metrics/average_precision.py +++ b/monai/metrics/average_precision.py @@ -12,12 +12,10 @@ from __future__ import annotations import warnings -from typing import TYPE_CHECKING, cast +from typing import cast import numpy as np - -if TYPE_CHECKING: - import numpy.typing as npt +import numpy.typing as npt import torch diff --git a/monai/metrics/rocauc.py b/monai/metrics/rocauc.py index 57a8a072b4..16e4d6bb15 100644 --- a/monai/metrics/rocauc.py +++ b/monai/metrics/rocauc.py @@ -12,12 +12,10 @@ from __future__ import annotations import warnings -from typing import TYPE_CHECKING, cast +from typing import cast import numpy as np - -if TYPE_CHECKING: - import numpy.typing as npt +import numpy.typing as npt import torch From 27cb347520690298fbb87ee6a0c5dd37cc7feacb Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 7 Dec 2025 22:27:31 +0000 Subject: [PATCH 23/41] Disk size optimisation Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 41 +++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index b9f7d6019c..4dd0e071fa 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -24,9 +24,9 @@ concurrency: group: cicd-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -# These jobs run the CICD tests, type checking, and testing packaging and documentation generation. These use the -# minimum supported versions of Python and PyTorch in many places hard-coded as literals, so when support is dropped -# for a version it is important to go through all jobs and check the versions they use are correct. +# These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of +# Python and PyTorch in many places hard-coded as literals, so when support is dropped for a version it is important to +# go through all jobs and check the versions they use are correct. jobs: static-checks: # Perform static type and other checks using runtests.sh @@ -35,6 +35,14 @@ jobs: matrix: opt: ["codeformat", "pytype", "mypy"] steps: + - name: Clean unused tools + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc /usr/local/.ghcup + sudo docker system prune -f + - uses: actions/checkout@v6 - name: Set up Python 3.10 uses: actions/setup-python@v6 @@ -52,7 +60,6 @@ jobs: key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - name: Install dependencies run: | - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; python -m pip install --upgrade pip wheel python -m pip install -r requirements-dev.txt - name: Lint and type check with "./runtests.sh --build --${{ matrix.opt }}" @@ -95,6 +102,14 @@ jobs: timeout-minutes: 40 steps: + - if: runner.os == 'Linux' + name: Clean unused tools + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc /usr/local/.ghcup + sudo docker system prune -f - uses: actions/checkout@v5 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 @@ -151,6 +166,14 @@ jobs: os: [windows-latest, macOS-latest, ubuntu-latest] timeout-minutes: 120 steps: + - if: runner.os == 'Linux' + name: Clean unused tools + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc /usr/local/.ghcup + sudo docker system prune -f - if: runner.os == 'windows' name: Config pagefile (Windows only) uses: al-cheb/configure-pagefile-action@v1.5 @@ -188,7 +211,6 @@ jobs: name: Install itk pre-release (Linux only) run: | python -m pip install --pre -U itk - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - name: Install the complete dependencies run: | python -m pip install --user --upgrade pip wheel @@ -218,6 +240,14 @@ jobs: QUICKTEST: True shell: bash steps: + - name: Clean unused tools + run: | + find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc /usr/local/.ghcup + sudo docker system prune -f + - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -239,7 +269,6 @@ jobs: key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - name: Install dependencies run: | - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; python -m pip install --user --upgrade pip setuptools wheel twine packaging # install the latest pytorch for testing # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated From 3c5a3da8e0f29b6732f93c5dabba4f2b725a5f45 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 7 Dec 2025 23:51:50 +0000 Subject: [PATCH 24/41] Fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 6 +++--- monai/metrics/average_precision.py | 1 - monai/metrics/rocauc.py | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 4dd0e071fa..2d634c0c43 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -24,8 +24,8 @@ concurrency: group: cicd-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -# These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of -# Python and PyTorch in many places hard-coded as literals, so when support is dropped for a version it is important to +# These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of +# Python and PyTorch in many places hard-coded as literals, so when support is dropped for a version it is important to # go through all jobs and check the versions they use are correct. jobs: @@ -273,7 +273,7 @@ jobs: # install the latest pytorch for testing # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated # fresh torch installation according to pyproject.toml - python -m pip install torch>=2.5.1 torchvision + python -m pip install torch\>=2.5.1 torchvision - name: Check packages run: | pip uninstall monai diff --git a/monai/metrics/average_precision.py b/monai/metrics/average_precision.py index ba0213953c..7dd277bde6 100644 --- a/monai/metrics/average_precision.py +++ b/monai/metrics/average_precision.py @@ -16,7 +16,6 @@ import numpy as np import numpy.typing as npt - import torch from monai.utils import Average, look_up_option diff --git a/monai/metrics/rocauc.py b/monai/metrics/rocauc.py index 16e4d6bb15..72f0b3730c 100644 --- a/monai/metrics/rocauc.py +++ b/monai/metrics/rocauc.py @@ -16,7 +16,6 @@ import numpy as np import numpy.typing as npt - import torch from monai.utils import Average, look_up_option From ea2816a9f226369cf22ddd9219b75b3056f063f7 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:53:27 +0100 Subject: [PATCH 25/41] Updates with version bumps Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/build_docs.yml | 2 +- .github/workflows/cicd_tests.yml | 96 +++++++++++++++-------------- .github/workflows/cron.yml | 6 +- .github/workflows/docker.yml | 2 +- .github/workflows/pythonapp-gpu.yml | 2 +- .github/workflows/release.yml | 4 +- .github/workflows/setupapp.yml | 4 +- pyproject.toml | 4 +- requirements-dev.txt | 3 +- requirements.txt | 3 +- setup.cfg | 10 +-- 11 files changed, 71 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml index c0b597201d..130c5aa60e 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_docs.yml @@ -31,7 +31,7 @@ jobs: sudo rm -rf /opt/ghc /usr/local/.ghcup sudo docker system prune -f - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Python 3.10 uses: actions/setup-python@v6 diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index f6fc240657..68857b6187 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -24,9 +24,24 @@ concurrency: group: cicd-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +env: + # supported versions of Python + PYTHON_VER1: '3.10' + PYTHON_VER2: '3.11' + PYTHON_VER3: '3.12' + PYTHON_VER4: '3.13' + PYTHON_VER5: '3.14' + # supported versions of PyTorch + PYTORCH_VER1: '2.8.0' + PYTORCH_VER2: '2.9.1' + PYTORCH_VER3: '2.10.0' + PYTORCH_VER4: '2.11.0' + TORCHVISION_VER: "0.23.0" # used for testing with lowest PyTorch version + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 + # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of -# Python and PyTorch in many places hard-coded as literals, so when support is dropped for a version it is important to -# go through all jobs and check the versions they use are correct. +# Python and PyTorch in many places using the above environment variables, when support is dropped for a version it is +# important to update these as appropriate. jobs: static-checks: # Perform static type and other checks using runtests.sh @@ -44,10 +59,10 @@ jobs: sudo docker system prune -f - uses: actions/checkout@v6 - - name: Set up Python 3.10 + - name: Set up Python {{ $PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: {{ $PYTHON_VER1 }} cache: 'pip' - name: Install dependencies run: | @@ -65,31 +80,36 @@ jobs: strategy: fail-fast: false matrix: + # Base test cases are to test on all three OSes with the lowest versions of Python and PyTorch, other cases are + # added below as special cases to cover other Python and PyTorch versions under Ubuntu os: [windows-latest, macOS-latest, ubuntu-latest] - python-version: ['3.10'] - pytorch-version: ['2.6.0'] + python-version: [{{ $PYTHON_VER1 }}] + pytorch-version: [{{ $PYTORCH_VER1 }}] include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest - pytorch-version: '2.6.0' - python-version: '3.11' + pytorch-version: {{ $PYTORCH_VER1 }} + python-version: {{ $PYTHON_VER2 }} + - os: ubuntu-latest + pytorch-version: {{ $PYTORCH_VER1 }} + python-version: {{ $PYTHON_VER3 }} - os: ubuntu-latest - pytorch-version: '2.6.0' - python-version: '3.12' + pytorch-version: {{ $PYTORCH_VER1 }} + python-version: {{ $PYTHON_VER4 }} - os: ubuntu-latest - pytorch-version: '2.6.0' - python-version: '3.13' + pytorch-version: {{ $PYTORCH_VER1 }} + python-version: {{ $PYTHON_VER5 }} # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest - python-version: '3.10' - pytorch-version: '2.7.1' + python-version: {{ $PYTHON_VER1 }} + pytorch-version: {{ $PYTORCH_VER2 }} - os: ubuntu-latest - python-version: '3.10' - pytorch-version: '2.8.0' + python-version: {{ $PYTHON_VER1 }} + pytorch-version: {{ $PYTORCH_VER3 }} - os: ubuntu-latest - python-version: '3.10' - pytorch-version: '2.9.0' + python-version: {{ $PYTHON_VER1 }} + pytorch-version: {{ $PYTORCH_VER4 }} timeout-minutes: 40 steps: @@ -101,28 +121,17 @@ jobs: sudo rm -rf /usr/local/lib/android sudo rm -rf /opt/ghc /usr/local/.ghcup sudo docker system prune -f - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} + cache: 'pip' - name: Prepare pip wheel run: | which python python -m pip install --upgrade pip wheel python -m pip install --user more-itertools>=8.0 - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - shell: bash - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: ${{ matrix.os }}-latest-pip-${{ steps.pip-cache.outputs.datew }} - name: Install the minimum dependencies run: | # min. requirements @@ -156,6 +165,8 @@ jobs: matrix: os: [windows-latest, macOS-latest, ubuntu-latest] timeout-minutes: 120 + env: + QUICKTEST: True steps: - if: runner.os == 'Linux' name: Clean unused tools @@ -173,10 +184,10 @@ jobs: maximum-size: 16GB disk-root: "D:" - uses: actions/checkout@v6 - - name: Set up Python 3.10 + - name: Set up Python {{ $PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: {{ $PYTHON_VER1 }} cache: 'pip' - name: Prepare pip wheel run: | @@ -185,7 +196,7 @@ jobs: - if: runner.os == 'windows' name: Install torch cpu from pytorch.org (Windows only) run: | - python -m pip install torch==2.5.1 torchvision==0.20.1+cpu --index-url https://download.pytorch.org/whl/cpu + python -m pip install torch==$PYTORCH_VER1 torchvision==$TORCHVISION_VER+cpu --index-url https://download.pytorch.org/whl/cpu - if: runner.os == 'Linux' name: Install itk pre-release (Linux only) run: | @@ -193,7 +204,7 @@ jobs: - name: Install the complete dependencies run: | python -m pip install --user --upgrade pip wheel - python -m pip install torch==2.5.1 torchvision==0.20.1 + python -m pip install torch==$PYTORCH_VER1 torchvision==$TORCHVISION_VER cat "requirements-dev.txt" python -m pip install --no-build-isolation -r requirements-dev.txt python -m pip list @@ -209,9 +220,6 @@ jobs: python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' python -c "import monai; monai.config.print_config()" # python -m unittest -v - env: - QUICKTEST: True - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 packaging: # Test package generation runs-on: ubuntu-latest @@ -230,10 +238,10 @@ jobs: - uses: actions/checkout@v6 with: fetch-depth: 0 - - name: Set up Python 3.10 + - name: Set up Python {{ $PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: {{ $PYTHON_VER1 }} cache: 'pip' - name: Install dependencies run: | @@ -241,7 +249,7 @@ jobs: # install the latest pytorch for testing # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated # fresh torch installation according to pyproject.toml - python -m pip install torch>=2.5.1 torchvision --extra-index-url https://download.pytorch.org/whl/cpu + python -m pip install torch==$PYTORCH_VER1 torchvision --extra-index-url https://download.pytorch.org/whl/cpu - name: Check packages run: | pip uninstall monai @@ -293,17 +301,15 @@ jobs: ls -al python -m pip install --no-build-isolation -r requirements-dev.txt --extra-index-url https://download.pytorch.org/whl/cpu python -m unittest -v - env: - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 build-docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - name: Set up Python 3.10 + - name: Set up Python {{ $PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: {{ $PYTHON_VER1 }} cache: 'pip' - name: Install dependencies run: | diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index dca48dd9c8..f1ff708a43 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -67,7 +67,7 @@ jobs: if pgrep python; then pkill python; fi shell: bash - name: Upload coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: fail_ci_if_error: false files: ./coverage.xml @@ -115,7 +115,7 @@ jobs: if pgrep python; then pkill python; fi shell: bash - name: Upload coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: fail_ci_if_error: false files: ./coverage.xml @@ -220,7 +220,7 @@ jobs: if pgrep python; then pkill python; fi shell: bash - name: Upload coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: fail_ci_if_error: false files: ./coverage.xml diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 8fb53bc64c..78b05c954c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -37,7 +37,7 @@ jobs: python setup.py build cat build/lib/monai/_version.py - name: Upload version - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: _version.py path: build/lib/monai/_version.py diff --git a/.github/workflows/pythonapp-gpu.yml b/.github/workflows/pythonapp-gpu.yml index 0381bbe35c..7de9936e9b 100644 --- a/.github/workflows/pythonapp-gpu.yml +++ b/.github/workflows/pythonapp-gpu.yml @@ -125,6 +125,6 @@ jobs: shell: bash - name: Upload coverage if: ${{ github.head_ref != 'dev' && github.event.pull_request.merged != true }} - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: files: ./coverage.xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c04f186ee9..d7df47ae19 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,7 +66,7 @@ jobs: - if: matrix.python-version == '3.10' && startsWith(github.ref, 'refs/tags/') name: Upload artifacts - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: dist path: dist/ @@ -109,7 +109,7 @@ jobs: python setup.py build cat build/lib/monai/_version.py - name: Upload version - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: _version.py path: build/lib/monai/_version.py diff --git a/.github/workflows/setupapp.yml b/.github/workflows/setupapp.yml index d0124a50a3..63162b2dac 100644 --- a/.github/workflows/setupapp.yml +++ b/.github/workflows/setupapp.yml @@ -72,7 +72,7 @@ jobs: if pgrep python; then pkill python; fi shell: bash - name: Upload coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: fail_ci_if_error: false files: ./coverage.xml @@ -108,7 +108,7 @@ jobs: BUILD_MONAI=1 ./runtests.sh --build --coverage --quick --min coverage xml --ignore-errors - name: Upload coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: fail_ci_if_error: false files: ./coverage.xml diff --git a/pyproject.toml b/pyproject.toml index 3e63c38d3f..4a222c7d16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,14 +3,14 @@ requires = [ "wheel", "setuptools", "more-itertools>=8.0", - "torch>=2.4.1", + "torch>=2.8.0", "ninja", "packaging" ] [tool.black] line-length = 120 -target-version = ['py39', 'py310', 'py311', 'py312'] +target-version = ['py310', 'py311', 'py312', 'py313'] include = '\.pyi?$' exclude = ''' ( diff --git a/requirements-dev.txt b/requirements-dev.txt index a1e79c9197..915d30ed24 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -14,7 +14,7 @@ mccabe pep8-naming pycodestyle pyflakes -black>=25.1.0 +black>=26.3.1 isort>=5.1, !=6.0.0 ruff pytype>=2020.6.1, <=2024.4.11; platform_system != "Windows" @@ -25,6 +25,7 @@ torchio torchvision psutil cucim-cu12; platform_system == "Linux" and python_version <= "3.10" +cucim-cu13; platform_system == "Linux" and python_version >= '3.11' openslide-python openslide-bin imagecodecs; platform_system == "Linux" or platform_system == "Darwin" diff --git a/requirements.txt b/requirements.txt index c43fb21f92..7d283182a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ -torch>=2.4.1; platform_system != "Windows" -torch>=2.4.1, !=2.7.0; platform_system == "Windows" +torch>=2.8.0 numpy>=1.24,<3.0 diff --git a/setup.cfg b/setup.cfg index 95ea7f9c76..724d1eceb3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,7 +43,7 @@ setup_requires = ninja packaging install_requires = - torch>=2.6.0 + torch>=2.8.0 numpy>=1.24,<3.0 [options.extras_require] @@ -62,7 +62,7 @@ all = tqdm>=4.47.0 lmdb psutil - cucim-cu12; platform_system == "Linux" and python_version >= '3.9' and python_version <= '3.10' + cucim-cu12; platform_system == "Linux" and python_version <= '3.10' cucim-cu13; platform_system == "Linux" and python_version >= '3.11' openslide-python openslide-bin @@ -70,7 +70,7 @@ all = imagecodecs; platform_system == "Linux" or platform_system == "Darwin" pandas einops - transformers>=4.36.0, <4.41.0; python_version <= '3.10' + transformers>=4.53.0 mlflow>=2.12.2 clearml>=1.10.0rc0 matplotlib>=3.6.3 @@ -84,7 +84,7 @@ all = nni; platform_system == "Linux" and "arm" not in platform_machine and "aarch" not in platform_machine optuna onnx>=1.13.0 - onnxruntime; python_version <= '3.10' + onnxruntime zarr lpips==0.1.4 nvidia-ml-py @@ -119,7 +119,7 @@ lmdb = psutil = psutil cucim = - cucim-cu12; platform_system == "Linux" and python_version >= '3.9' and python_version <= '3.10' + cucim-cu12; platform_system == "Linux" and python_version <= '3.10' cucim-cu13; platform_system == "Linux" and python_version >= '3.11' openslide = openslide-python From 63a92bf7015629ff5d7574a0f1e8ca85ab007b09 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:06:34 +0100 Subject: [PATCH 26/41] Syntax fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 68857b6187..c1487f4c82 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -36,7 +36,7 @@ env: PYTORCH_VER2: '2.9.1' PYTORCH_VER3: '2.10.0' PYTORCH_VER4: '2.11.0' - TORCHVISION_VER: "0.23.0" # used for testing with lowest PyTorch version + TORCHVISION_VER: '0.23.0' # used for testing with lowest PyTorch version PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of @@ -59,10 +59,10 @@ jobs: sudo docker system prune -f - uses: actions/checkout@v6 - - name: Set up Python {{ $PYTHON_VER1 }} + - name: Set up Python ${{ env.PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: {{ $PYTHON_VER1 }} + python-version: ${{ env.PYTHON_VER1 }} cache: 'pip' - name: Install dependencies run: | @@ -83,33 +83,33 @@ jobs: # Base test cases are to test on all three OSes with the lowest versions of Python and PyTorch, other cases are # added below as special cases to cover other Python and PyTorch versions under Ubuntu os: [windows-latest, macOS-latest, ubuntu-latest] - python-version: [{{ $PYTHON_VER1 }}] - pytorch-version: [{{ $PYTORCH_VER1 }}] + python-version: [ ${{ env.PYTHON_VER1 }} ] + pytorch-version: [ ${{ env.PYTORCH_VER1 }} ] include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest - pytorch-version: {{ $PYTORCH_VER1 }} - python-version: {{ $PYTHON_VER2 }} + pytorch-version: ${{ env.PYTORCH_VER1 }} + python-version: ${{ env.PYTHON_VER2 }} - os: ubuntu-latest - pytorch-version: {{ $PYTORCH_VER1 }} - python-version: {{ $PYTHON_VER3 }} + pytorch-version: ${{ env.PYTORCH_VER1 }} + python-version: ${{ env.PYTHON_VER3 }} - os: ubuntu-latest - pytorch-version: {{ $PYTORCH_VER1 }} - python-version: {{ $PYTHON_VER4 }} + pytorch-version: ${{ env.PYTORCH_VER1 }} + python-version: ${{ env.PYTHON_VER4 }} - os: ubuntu-latest - pytorch-version: {{ $PYTORCH_VER1 }} - python-version: {{ $PYTHON_VER5 }} + pytorch-version: ${{ env.PYTORCH_VER1 }} + python-version: ${{ env.PYTHON_VER5 }} # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest - python-version: {{ $PYTHON_VER1 }} - pytorch-version: {{ $PYTORCH_VER2 }} + python-version: ${{ env.PYTHON_VER1 }} + pytorch-version: ${{ env.PYTORCH_VER2 }} - os: ubuntu-latest - python-version: {{ $PYTHON_VER1 }} - pytorch-version: {{ $PYTORCH_VER3 }} + python-version: ${{ env.PYTHON_VER1 }} + pytorch-version: ${{ env.PYTORCH_VER3 }} - os: ubuntu-latest - python-version: {{ $PYTHON_VER1 }} - pytorch-version: {{ $PYTORCH_VER4 }} + python-version: ${{ env.PYTHON_VER1 }} + pytorch-version: ${{ env.PYTORCH_VER4 }} timeout-minutes: 40 steps: @@ -184,10 +184,10 @@ jobs: maximum-size: 16GB disk-root: "D:" - uses: actions/checkout@v6 - - name: Set up Python {{ $PYTHON_VER1 }} + - name: Set up Python ${{ env.PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: {{ $PYTHON_VER1 }} + python-version: ${{ env.PYTHON_VER1 }} cache: 'pip' - name: Prepare pip wheel run: | @@ -238,10 +238,10 @@ jobs: - uses: actions/checkout@v6 with: fetch-depth: 0 - - name: Set up Python {{ $PYTHON_VER1 }} + - name: Set up Python ${{ env.PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: {{ $PYTHON_VER1 }} + python-version: ${{ env.PYTHON_VER1 }} cache: 'pip' - name: Install dependencies run: | @@ -306,10 +306,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - name: Set up Python {{ $PYTHON_VER1 }} + - name: Set up Python ${{ env.PYTHON_VER1 }} uses: actions/setup-python@v6 with: - python-version: {{ $PYTHON_VER1 }} + python-version: ${{ env.PYTHON_VER1 }} cache: 'pip' - name: Install dependencies run: | From b6695267eb1b7a5e9ec27dede29be7a124f2fa49 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:07:57 +0100 Subject: [PATCH 27/41] Syntax fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index c1487f4c82..1f791f7e08 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -83,8 +83,8 @@ jobs: # Base test cases are to test on all three OSes with the lowest versions of Python and PyTorch, other cases are # added below as special cases to cover other Python and PyTorch versions under Ubuntu os: [windows-latest, macOS-latest, ubuntu-latest] - python-version: [ ${{ env.PYTHON_VER1 }} ] - pytorch-version: [ ${{ env.PYTORCH_VER1 }} ] + python-version: ${{ env.PYTHON_VER1 }} + pytorch-version: ${{ env.PYTORCH_VER1 }} include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest From 22fe6ca63c376f553aa9480c768e389dc1cd7286 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:16:03 +0100 Subject: [PATCH 28/41] Pre-commit fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 1f791f7e08..fbbb9af07c 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -40,7 +40,7 @@ env: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of -# Python and PyTorch in many places using the above environment variables, when support is dropped for a version it is +# Python and PyTorch in many places using the above environment variables, when support is dropped for a version it is # important to update these as appropriate. jobs: From edcbffe781982a5fb93b6e2dd096ddb9c21ae4d3 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:18:50 +0100 Subject: [PATCH 29/41] Redundant file Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/build_docs.yml | 68 -------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 .github/workflows/build_docs.yml diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml deleted file mode 100644 index 130c5aa60e..0000000000 --- a/.github/workflows/build_docs.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: build_docs - -on: - # build docs test for pull requests and the releasing branches - push: - branches: - - dev - - main - - releasing/* - pull_request: - head_ref-ignore: - - dev - -concurrency: - # automatically cancel the previously triggered workflows when there's a newer version - group: cicd-tests-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -# This test is for building documentation on any relevant push or PR. This ensures that any changes to docs or source -# files is tested for correct doc building, whereas functional tests can be deferred if only docs were modified. - -jobs: - build-docs: - runs-on: ubuntu-latest - steps: - - name: Clean unused tools - run: | - find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \; - sudo rm -rf /usr/share/dotnet - sudo rm -rf /usr/local/lib/android - sudo rm -rf /opt/ghc /usr/local/.ghcup - sudo docker system prune -f - - - uses: actions/checkout@v6 - - - name: Set up Python 3.10 - uses: actions/setup-python@v6 - with: - python-version: '3.10' - - - name: cache weekly timestamp - id: pip-cache - run: | - echo "datew=$(date '+%Y-%V')" >> $GITHUB_OUTPUT - - - name: cache for pip - uses: actions/cache@v4 - id: cache - with: - path: | - ~/.cache/pip - ~/.cache/torch - key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip wheel - python -m pip install -r docs/requirements.txt - - - name: Make html - run: | - cd docs/ - make clean - make html 2>&1 | tee tmp_log - if [[ $(grep -c "ERROR:" tmp_log) != 0 ]]; then echo "Found errors:"; grep "ERROR:" tmp_log; exit 1; fi - sed '/WARNING.*pip/d' tmp_log > tmp_log1; mv tmp_log1 tmp_log # monai#7133 - if [[ $(grep -c "WARNING:" tmp_log) != 0 ]]; then echo "Found warnings:"; grep "WARNING:" tmp_log; exit 1; fi - shell: bash From 30616b109692342aba754b53aa97ffda1aafb675 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:27:16 +0100 Subject: [PATCH 30/41] Syntax fix Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index fbbb9af07c..3ddec1d308 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -26,17 +26,17 @@ concurrency: env: # supported versions of Python - PYTHON_VER1: '3.10' - PYTHON_VER2: '3.11' - PYTHON_VER3: '3.12' - PYTHON_VER4: '3.13' - PYTHON_VER5: '3.14' + PYTHON_VER1: "3.10" + PYTHON_VER2: "3.11" + PYTHON_VER3: "3.12" + PYTHON_VER4: "3.13" + PYTHON_VER5: "3.14" # supported versions of PyTorch - PYTORCH_VER1: '2.8.0' - PYTORCH_VER2: '2.9.1' - PYTORCH_VER3: '2.10.0' - PYTORCH_VER4: '2.11.0' - TORCHVISION_VER: '0.23.0' # used for testing with lowest PyTorch version + PYTORCH_VER1: "2.8.0" + PYTORCH_VER2: "2.9.1" + PYTORCH_VER3: "2.10.0" + PYTORCH_VER4: "2.11.0" + TORCHVISION_VER: "0.23.0" # used for testing with lowest PyTorch version PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of From 0b6ec1cce84cbd5e4eddfa42b62d5795f39ba4d5 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:40:38 +0100 Subject: [PATCH 31/41] Matrix restrictions Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 52 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 3ddec1d308..90f8a9e8b2 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -26,17 +26,17 @@ concurrency: env: # supported versions of Python - PYTHON_VER1: "3.10" - PYTHON_VER2: "3.11" - PYTHON_VER3: "3.12" - PYTHON_VER4: "3.13" - PYTHON_VER5: "3.14" + PYTHON_VER1: '3.10' + PYTHON_VER2: '3.11' + PYTHON_VER3: '3.12' + PYTHON_VER4: '3.13' + PYTHON_VER5: '3.14' # supported versions of PyTorch - PYTORCH_VER1: "2.8.0" - PYTORCH_VER2: "2.9.1" - PYTORCH_VER3: "2.10.0" - PYTORCH_VER4: "2.11.0" - TORCHVISION_VER: "0.23.0" # used for testing with lowest PyTorch version + PYTORCH_VER1: '2.8.0' + PYTORCH_VER2: '2.9.1' + PYTORCH_VER3: '2.10.0' + PYTORCH_VER4: '2.11.0' + TORCHVISION_VER: '0.23.0' # used for testing with lowest PyTorch version PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of @@ -83,33 +83,33 @@ jobs: # Base test cases are to test on all three OSes with the lowest versions of Python and PyTorch, other cases are # added below as special cases to cover other Python and PyTorch versions under Ubuntu os: [windows-latest, macOS-latest, ubuntu-latest] - python-version: ${{ env.PYTHON_VER1 }} - pytorch-version: ${{ env.PYTORCH_VER1 }} + python-version: ['3.10'] + pytorch-version: ['2.8.0'] include: # Test Python versions under Ubuntu with lowest PyTorch version supported - os: ubuntu-latest - pytorch-version: ${{ env.PYTORCH_VER1 }} - python-version: ${{ env.PYTHON_VER2 }} + pytorch-version: '2.8.0' + python-version: '3.11' - os: ubuntu-latest - pytorch-version: ${{ env.PYTORCH_VER1 }} - python-version: ${{ env.PYTHON_VER3 }} + pytorch-version: '2.8.0' + python-version: '3.12' - os: ubuntu-latest - pytorch-version: ${{ env.PYTORCH_VER1 }} - python-version: ${{ env.PYTHON_VER4 }} + pytorch-version: '2.8.0' + python-version: '3.13' - os: ubuntu-latest - pytorch-version: ${{ env.PYTORCH_VER1 }} - python-version: ${{ env.PYTHON_VER5 }} + pytorch-version: '2.8.0' + python-version: '3.14' # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest - python-version: ${{ env.PYTHON_VER1 }} - pytorch-version: ${{ env.PYTORCH_VER2 }} + python-version: '3.10' + pytorch-version: '2.9.1' - os: ubuntu-latest - python-version: ${{ env.PYTHON_VER1 }} - pytorch-version: ${{ env.PYTORCH_VER3 }} + python-version: '3.10' + pytorch-version: '2.10.0' - os: ubuntu-latest - python-version: ${{ env.PYTHON_VER1 }} - pytorch-version: ${{ env.PYTORCH_VER4 }} + python-version: '3.10' + pytorch-version: '2.11.0' timeout-minutes: 40 steps: From 6782838f430c6ee0da4ad0bd510601d91ef639ad Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sat, 4 Apr 2026 23:49:33 +0100 Subject: [PATCH 32/41] Updates for new black formatting Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 13 ++++----- monai/apps/detection/transforms/dictionary.py | 27 ++++++++----------- monai/apps/detection/utils/anchor_utils.py | 13 ++++----- monai/apps/reconstruction/transforms/array.py | 4 +-- monai/bundle/utils.py | 6 ++--- monai/losses/dice.py | 5 ++-- monai/losses/focal_loss.py | 5 ++-- pyproject.toml | 6 +++-- runtests.sh | 4 +-- 9 files changed, 37 insertions(+), 46 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 90f8a9e8b2..9efa9e92dd 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -24,6 +24,7 @@ concurrency: group: cicd-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +# Supported versions of Python and PyTorch are listed here for use below and as documentation env: # supported versions of Python PYTHON_VER1: '3.10' @@ -40,8 +41,8 @@ env: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of -# Python and PyTorch in many places using the above environment variables, when support is dropped for a version it is -# important to update these as appropriate. +# Python and PyTorch in many places using the above environment variables but also hard coded where necessary. +# When support is dropped for a version it is important to update these as appropriate. jobs: static-checks: # Perform static type and other checks using runtests.sh @@ -97,7 +98,7 @@ jobs: pytorch-version: '2.8.0' python-version: '3.13' - os: ubuntu-latest - pytorch-version: '2.8.0' + pytorch-version: '2.9.0' python-version: '3.14' # Test PyTorch versions under Ubuntu with lowest Python version supported @@ -196,7 +197,7 @@ jobs: - if: runner.os == 'windows' name: Install torch cpu from pytorch.org (Windows only) run: | - python -m pip install torch==$PYTORCH_VER1 torchvision==$TORCHVISION_VER+cpu --index-url https://download.pytorch.org/whl/cpu + python -m pip install torch==${PYTORCH_VER1} torchvision==${TORCHVISION_VER}+cpu --index-url https://download.pytorch.org/whl/cpu - if: runner.os == 'Linux' name: Install itk pre-release (Linux only) run: | @@ -204,7 +205,7 @@ jobs: - name: Install the complete dependencies run: | python -m pip install --user --upgrade pip wheel - python -m pip install torch==$PYTORCH_VER1 torchvision==$TORCHVISION_VER + python -m pip install torch==${PYTORCH_VER1} torchvision==${TORCHVISION_VER} cat "requirements-dev.txt" python -m pip install --no-build-isolation -r requirements-dev.txt python -m pip list @@ -249,7 +250,7 @@ jobs: # install the latest pytorch for testing # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated # fresh torch installation according to pyproject.toml - python -m pip install torch==$PYTORCH_VER1 torchvision --extra-index-url https://download.pytorch.org/whl/cpu + python -m pip install torch==${PYTORCH_VER1} torchvision --extra-index-url https://download.pytorch.org/whl/cpu - name: Check packages run: | pip uninstall monai diff --git a/monai/apps/detection/transforms/dictionary.py b/monai/apps/detection/transforms/dictionary.py index f52ab53531..737ec70b36 100644 --- a/monai/apps/detection/transforms/dictionary.py +++ b/monai/apps/detection/transforms/dictionary.py @@ -125,10 +125,8 @@ def __init__(self, box_keys: KeysCollection, box_ref_image_keys: str, allow_miss super().__init__(box_keys, allow_missing_keys) box_ref_image_keys_tuple = ensure_tuple(box_ref_image_keys) if len(box_ref_image_keys_tuple) > 1: - raise ValueError( - "Please provide a single key for box_ref_image_keys.\ - All boxes of box_keys are attached to box_ref_image_keys." - ) + raise ValueError("Please provide a single key for box_ref_image_keys.\ + All boxes of box_keys are attached to box_ref_image_keys.") self.box_ref_image_keys = box_ref_image_keys def __call__(self, data: Mapping[Hashable, NdarrayOrTensor]) -> dict[Hashable, NdarrayOrTensor]: @@ -290,8 +288,8 @@ def __init__( box_ref_image_keys_tuple = ensure_tuple(box_ref_image_keys) if len(box_ref_image_keys_tuple) > 1: raise ValueError( - "Please provide a single key for box_ref_image_keys.\ - All boxes of box_keys are attached to box_ref_image_keys." + "Please provide a single key for `box_ref_image_keys`. " + "All boxes of box_keys are attached to `box_ref_image_keys`." ) self.box_ref_image_keys = box_ref_image_keys self.image_meta_key = image_meta_key or f"{box_ref_image_keys}_{image_meta_key_postfix}" @@ -311,8 +309,7 @@ def extract_affine(self, data: Mapping[Hashable, torch.Tensor]) -> tuple[Ndarray raise ValueError(f"{meta_key} is not found. Please check whether it is the correct the image meta key.") if "affine" not in meta_dict: raise ValueError( - f"'affine' is not found in {meta_key}. \ - Please check whether it is the correct the image meta key." + f"Key 'affine' not found in {meta_key}. Please check it is the correct the image meta key." ) affine: NdarrayOrTensor = meta_dict["affine"] @@ -816,15 +813,15 @@ def __init__( box_keys_tuple = ensure_tuple(box_keys) if len(box_keys_tuple) != 1: raise ValueError( - "Please provide a single key for box_keys.\ - All label_keys are attached to this box_keys." + "Please provide at least one key for `box_keys`. All `label_keys` are attached to this `box_keys`." ) box_ref_image_keys_tuple = ensure_tuple(box_ref_image_keys) if len(box_ref_image_keys_tuple) != 1: raise ValueError( - "Please provide a single key for box_ref_image_keys.\ - All box_keys and label_keys are attached to this box_ref_image_keys." + "Please provide at least one key for `box_ref_image_keys`. " + "All box_keys and label_keys are attached to this `box_ref_image_keys`." ) + self.label_keys = ensure_tuple(label_keys) super().__init__(box_keys_tuple, allow_missing_keys) @@ -1091,10 +1088,8 @@ def __init__( box_keys_tuple = ensure_tuple(box_keys) if len(box_keys_tuple) != 1: - raise ValueError( - "Please provide a single key for box_keys.\ - All label_keys are attached to this box_keys." - ) + raise ValueError("Please provide a single key for box_keys.\ + All label_keys are attached to this box_keys.") self.box_keys = box_keys_tuple[0] self.label_keys = ensure_tuple(label_keys) diff --git a/monai/apps/detection/utils/anchor_utils.py b/monai/apps/detection/utils/anchor_utils.py index 20f6fc6025..9ee1964215 100644 --- a/monai/apps/detection/utils/anchor_utils.py +++ b/monai/apps/detection/utils/anchor_utils.py @@ -124,10 +124,7 @@ def __init__( aspect_ratios = (aspect_ratios,) * len(self.sizes) if len(self.sizes) != len(aspect_ratios): - raise ValueError( - "len(sizes) and len(aspect_ratios) should be equal. \ - It represents the number of feature maps." - ) + raise ValueError("The number of feature maps, `len(sizes)` and `len(aspect_ratios)`, should be equal.") spatial_dims = len(ensure_tuple(aspect_ratios[0][0])) + 1 spatial_dims = look_up_option(spatial_dims, [2, 3]) @@ -173,14 +170,14 @@ def generate_anchors( aspect_ratios_t = torch.as_tensor(aspect_ratios, dtype=dtype, device=device) # sized (M,) or (M,2) if (self.spatial_dims >= 3) and (len(aspect_ratios_t.shape) != 2): raise ValueError( - f"In {self.spatial_dims}-D image, aspect_ratios for each level should be \ - {len(aspect_ratios_t.shape) - 1}-D. But got aspect_ratios with shape {aspect_ratios_t.shape}." + f"In {self.spatial_dims}-D image, aspect_ratios for each level should be " + f"{len(aspect_ratios_t.shape) - 1}-D. Got aspect_ratios with shape {aspect_ratios_t.shape}." ) if (self.spatial_dims >= 3) and (aspect_ratios_t.shape[1] != self.spatial_dims - 1): raise ValueError( - f"In {self.spatial_dims}-D image, aspect_ratios for each level should has \ - shape (_,{self.spatial_dims - 1}). But got aspect_ratios with shape {aspect_ratios_t.shape}." + f"In {self.spatial_dims}-D image, aspect_ratios for each level should have " + f"shape (_,{self.spatial_dims - 1}). Got aspect_ratios with shape {aspect_ratios_t.shape}." ) # if 2d, w:h = 1:aspect_ratios diff --git a/monai/apps/reconstruction/transforms/array.py b/monai/apps/reconstruction/transforms/array.py index 911d7a06bb..64fc8cdd2d 100644 --- a/monai/apps/reconstruction/transforms/array.py +++ b/monai/apps/reconstruction/transforms/array.py @@ -62,8 +62,8 @@ def __init__( """ if len(center_fractions) != len(accelerations): raise ValueError( - "Number of center fractions \ - should match number of accelerations" + "Number of center fractions `len(center_fractions)` " + "should match number of accelerations `len(accelerations)`." ) self.center_fractions = center_fractions diff --git a/monai/bundle/utils.py b/monai/bundle/utils.py index 53d619f234..d37d7f1c05 100644 --- a/monai/bundle/utils.py +++ b/monai/bundle/utils.py @@ -124,10 +124,8 @@ "run_name": None, # may fill it at runtime "save_execute_config": True, - "is_not_rank0": ( - "$torch.distributed.is_available() \ - and torch.distributed.is_initialized() and torch.distributed.get_rank() > 0" - ), + "is_not_rank0": ("$torch.distributed.is_available() \ + and torch.distributed.is_initialized() and torch.distributed.get_rank() > 0"), # MLFlowHandler config for the trainer "trainer": { "_target_": "MLFlowHandler", diff --git a/monai/losses/dice.py b/monai/losses/dice.py index cd76ec1323..b4558f930c 100644 --- a/monai/losses/dice.py +++ b/monai/losses/dice.py @@ -204,9 +204,8 @@ def forward(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor: else: if self.class_weight.shape[0] != num_of_classes: raise ValueError( - """the length of the `weight` sequence should be the same as the number of classes. - If `include_background=False`, the weight should not include - the background category class 0.""" + "The length of the `weight` sequence should be the same as the number of classes. " + "If `include_background=False`, the weight should not include the background category class 0." ) if self.class_weight.min() < 0: raise ValueError("the value/values of the `weight` should be no less than 0.") diff --git a/monai/losses/focal_loss.py b/monai/losses/focal_loss.py index caa237fca8..7773cbdc9a 100644 --- a/monai/losses/focal_loss.py +++ b/monai/losses/focal_loss.py @@ -184,9 +184,8 @@ def forward(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor: else: if self.class_weight.shape[0] != num_of_classes: raise ValueError( - """the length of the `weight` sequence should be the same as the number of classes. - If `include_background=False`, the weight should not include - the background category class 0.""" + "The length of the `weight` sequence should be the same as the number of classes. " + "If `include_background=False`, the weight should not include the background category class 0." ) if self.class_weight.min() < 0: raise ValueError("the value/values of the `weight` should be no less than 0.") diff --git a/pyproject.toml b/pyproject.toml index 4a222c7d16..325622b66a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,8 @@ requires = [ [tool.black] line-length = 120 -target-version = ['py310', 'py311', 'py312', 'py313'] +target-version = ['py310'] +skip-magic-trailing-comma = true include = '\.pyi?$' exclude = ''' ( @@ -30,6 +31,7 @@ exclude = ''' | dist )/ # also separately exclude a file named versioneer.py + | versioneer.py | monai/_version.py ) ''' @@ -40,7 +42,7 @@ exclude = "monai/bundle/__main__.py" [tool.ruff] line-length = 120 -target-version = "py39" +target-version = "py310" [tool.ruff.lint] select = [ diff --git a/runtests.sh b/runtests.sh index a1551fe8dd..01401af4d7 100755 --- a/runtests.sh +++ b/runtests.sh @@ -516,9 +516,9 @@ then if [ $doBlackFix = true ] then - ${cmdPrefix}"${PY_EXE}" -m black --skip-magic-trailing-comma "$homedir" + ${cmdPrefix}"${PY_EXE}" -m black "$homedir" else - ${cmdPrefix}"${PY_EXE}" -m black --skip-magic-trailing-comma --check "$homedir" + ${cmdPrefix}"${PY_EXE}" -m black --check "$homedir" fi black_status=$? From 87c6fee5be41ea84461c78c01ddbb820872b8a98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 22:50:25 +0000 Subject: [PATCH 33/41] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- monai/apps/pathology/inferers/inferer.py | 3 ++- monai/apps/pathology/transforms/post/array.py | 2 +- monai/bundle/scripts.py | 3 ++- monai/engines/evaluator.py | 3 ++- monai/engines/trainer.py | 3 ++- monai/losses/hausdorff_loss.py | 2 +- monai/losses/sure_loss.py | 2 +- monai/networks/layers/conjugate_gradient.py | 2 +- monai/networks/nets/dynunet.py | 23 +++++++++---------- monai/networks/nets/vista3d.py | 3 ++- monai/optimizers/lr_finder.py | 3 ++- monai/transforms/adaptors.py | 2 +- monai/transforms/intensity/dictionary.py | 2 +- monai/transforms/io/array.py | 2 +- monai/transforms/io/dictionary.py | 2 +- monai/transforms/spatial/array.py | 4 ++-- monai/transforms/utility/array.py | 3 ++- monai/utils/component_store.py | 3 ++- monai/utils/decorators.py | 2 +- monai/visualize/gradient_based.py | 3 ++- tests/bundle/test_config_item.py | 2 +- tests/test_utils.py | 3 ++- 22 files changed, 43 insertions(+), 34 deletions(-) diff --git a/monai/apps/pathology/inferers/inferer.py b/monai/apps/pathology/inferers/inferer.py index 392cba221f..f4ba74adac 100644 --- a/monai/apps/pathology/inferers/inferer.py +++ b/monai/apps/pathology/inferers/inferer.py @@ -12,7 +12,8 @@ from __future__ import annotations from collections.abc import Sequence -from typing import Any, Callable +from typing import Any +from collections.abc import Callable import numpy as np import torch diff --git a/monai/apps/pathology/transforms/post/array.py b/monai/apps/pathology/transforms/post/array.py index 561ed3ae20..a3892049e1 100644 --- a/monai/apps/pathology/transforms/post/array.py +++ b/monai/apps/pathology/transforms/post/array.py @@ -13,7 +13,7 @@ import warnings from collections.abc import Sequence -from typing import Callable +from collections.abc import Callable import numpy as np import torch diff --git a/monai/bundle/scripts.py b/monai/bundle/scripts.py index fa9ba27096..9be611313a 100644 --- a/monai/bundle/scripts.py +++ b/monai/bundle/scripts.py @@ -23,7 +23,8 @@ from pydoc import locate from shutil import copyfile from textwrap import dedent -from typing import Any, Callable +from typing import Any +from collections.abc import Callable import torch from torch.cuda import is_available diff --git a/monai/engines/evaluator.py b/monai/engines/evaluator.py index 836b407ac5..4178dad9b9 100644 --- a/monai/engines/evaluator.py +++ b/monai/engines/evaluator.py @@ -13,7 +13,8 @@ import warnings from collections.abc import Iterable, Sequence -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any +from collections.abc import Callable import torch from torch.utils.data import DataLoader diff --git a/monai/engines/trainer.py b/monai/engines/trainer.py index 15033cabac..b958ca4ec2 100644 --- a/monai/engines/trainer.py +++ b/monai/engines/trainer.py @@ -13,7 +13,8 @@ import warnings from collections.abc import Iterable, Sequence -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any +from collections.abc import Callable import torch from torch.optim.optimizer import Optimizer diff --git a/monai/losses/hausdorff_loss.py b/monai/losses/hausdorff_loss.py index b75433e1da..017606ac08 100644 --- a/monai/losses/hausdorff_loss.py +++ b/monai/losses/hausdorff_loss.py @@ -17,7 +17,7 @@ from __future__ import annotations import warnings -from typing import Callable +from collections.abc import Callable import torch from torch.nn.modules.loss import _Loss diff --git a/monai/losses/sure_loss.py b/monai/losses/sure_loss.py index cc02317f72..53583b9051 100644 --- a/monai/losses/sure_loss.py +++ b/monai/losses/sure_loss.py @@ -11,7 +11,7 @@ from __future__ import annotations -from typing import Callable +from collections.abc import Callable import torch import torch.nn as nn diff --git a/monai/networks/layers/conjugate_gradient.py b/monai/networks/layers/conjugate_gradient.py index 93a45930d7..9432f15b6c 100644 --- a/monai/networks/layers/conjugate_gradient.py +++ b/monai/networks/layers/conjugate_gradient.py @@ -11,7 +11,7 @@ from __future__ import annotations -from typing import Callable +from collections.abc import Callable import torch from torch import nn diff --git a/monai/networks/nets/dynunet.py b/monai/networks/nets/dynunet.py index ec418469bb..d130b886a7 100644 --- a/monai/networks/nets/dynunet.py +++ b/monai/networks/nets/dynunet.py @@ -12,7 +12,6 @@ # isort: dont-add-import: from __future__ import annotations from collections.abc import Sequence -from typing import Optional, Union import torch import torch.nn as nn @@ -33,7 +32,7 @@ class DynUNetSkipLayer(nn.Module): forward passes of the network. """ - heads: Optional[list[torch.Tensor]] + heads: list[torch.Tensor] | None def __init__(self, index, downsample, upsample, next_layer, heads=None, super_head=None): super().__init__() @@ -133,13 +132,13 @@ def __init__( spatial_dims: int, in_channels: int, out_channels: int, - kernel_size: Sequence[Union[Sequence[int], int]], - strides: Sequence[Union[Sequence[int], int]], - upsample_kernel_size: Sequence[Union[Sequence[int], int]], - filters: Optional[Sequence[int]] = None, - dropout: Optional[Union[tuple, str, float]] = None, - norm_name: Union[tuple, str] = ("INSTANCE", {"affine": True}), - act_name: Union[tuple, str] = ("leakyrelu", {"inplace": True, "negative_slope": 0.01}), + kernel_size: Sequence[Sequence[int] | int], + strides: Sequence[Sequence[int] | int], + upsample_kernel_size: Sequence[Sequence[int] | int], + filters: Sequence[int] | None = None, + dropout: tuple | str | float | None = None, + norm_name: tuple | str = ("INSTANCE", {"affine": True}), + act_name: tuple | str = ("leakyrelu", {"inplace": True, "negative_slope": 0.01}), deep_supervision: bool = False, deep_supr_num: int = 1, res_block: bool = False, @@ -326,10 +325,10 @@ def get_module_list( self, in_channels: list[int], out_channels: list[int], - kernel_size: Sequence[Union[Sequence[int], int]], - strides: Sequence[Union[Sequence[int], int]], + kernel_size: Sequence[Sequence[int] | int], + strides: Sequence[Sequence[int] | int], conv_block: nn.Module, - upsample_kernel_size: Optional[Sequence[Union[Sequence[int], int]]] = None, + upsample_kernel_size: Sequence[Sequence[int] | int] | None = None, trans_bias: bool = False, ): layers = [] diff --git a/monai/networks/nets/vista3d.py b/monai/networks/nets/vista3d.py index 5490931d8d..df5250dac0 100644 --- a/monai/networks/nets/vista3d.py +++ b/monai/networks/nets/vista3d.py @@ -13,7 +13,8 @@ import math from collections.abc import Sequence -from typing import Any, Callable +from typing import Any +from collections.abc import Callable import numpy as np import torch diff --git a/monai/optimizers/lr_finder.py b/monai/optimizers/lr_finder.py index aa2e4567b3..bae04efff8 100644 --- a/monai/optimizers/lr_finder.py +++ b/monai/optimizers/lr_finder.py @@ -15,7 +15,8 @@ import types import warnings from functools import partial -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any +from collections.abc import Callable import numpy as np import torch diff --git a/monai/transforms/adaptors.py b/monai/transforms/adaptors.py index 5a0c24c7f6..b3c8b34f5c 100644 --- a/monai/transforms/adaptors.py +++ b/monai/transforms/adaptors.py @@ -123,7 +123,7 @@ def __call__(self, img, seg): from __future__ import annotations -from typing import Callable +from collections.abc import Callable __all__ = ["adaptor", "apply_alias", "to_kwargs", "FunctionSignature"] diff --git a/monai/transforms/intensity/dictionary.py b/monai/transforms/intensity/dictionary.py index fac46f2487..f0878c0c99 100644 --- a/monai/transforms/intensity/dictionary.py +++ b/monai/transforms/intensity/dictionary.py @@ -18,7 +18,7 @@ from __future__ import annotations from collections.abc import Hashable, Mapping, Sequence -from typing import Callable +from collections.abc import Callable import numpy as np diff --git a/monai/transforms/io/array.py b/monai/transforms/io/array.py index f0c1d1949d..95beb5ae96 100644 --- a/monai/transforms/io/array.py +++ b/monai/transforms/io/array.py @@ -23,7 +23,7 @@ from collections.abc import Sequence from pathlib import Path from pydoc import locate -from typing import Callable +from collections.abc import Callable import numpy as np import torch diff --git a/monai/transforms/io/dictionary.py b/monai/transforms/io/dictionary.py index be1e78db8a..fc634baa30 100644 --- a/monai/transforms/io/dictionary.py +++ b/monai/transforms/io/dictionary.py @@ -19,7 +19,7 @@ from collections.abc import Hashable, Mapping from pathlib import Path -from typing import Callable +from collections.abc import Callable import numpy as np diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index 55dab79c3d..6aba71a0f6 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -18,7 +18,7 @@ from collections.abc import Callable, Sequence from copy import deepcopy from itertools import zip_longest -from typing import Any, Optional, Union, cast +from typing import Any, Optional, cast import numpy as np import torch @@ -118,7 +118,7 @@ "RandSimulateLowResolution", ] -RandRange = Optional[Union[Sequence[Union[tuple[float, float], float]], float]] +RandRange = Optional[Sequence[tuple[float, float] | float] | float] class SpatialResample(InvertibleTransform, LazyTransform): diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index 7df6e2c5ef..1483441dc1 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -21,7 +21,8 @@ from collections.abc import Hashable, Mapping, Sequence from copy import deepcopy from functools import partial -from typing import Any, Callable +from typing import Any +from collections.abc import Callable import numpy as np import torch diff --git a/monai/utils/component_store.py b/monai/utils/component_store.py index bf0d632ddd..6713b61769 100644 --- a/monai/utils/component_store.py +++ b/monai/utils/component_store.py @@ -15,7 +15,8 @@ from collections.abc import Iterable from keyword import iskeyword from textwrap import dedent, indent -from typing import Any, Callable, TypeVar +from typing import Any, TypeVar +from collections.abc import Callable T = TypeVar("T") diff --git a/monai/utils/decorators.py b/monai/utils/decorators.py index a784510c64..b6cfbf2bf7 100644 --- a/monai/utils/decorators.py +++ b/monai/utils/decorators.py @@ -16,7 +16,7 @@ __all__ = ["RestartGenerator", "MethodReplacer"] from collections.abc import Generator -from typing import Callable +from collections.abc import Callable class RestartGenerator: diff --git a/monai/visualize/gradient_based.py b/monai/visualize/gradient_based.py index c54c9cd4ca..d858a3dfce 100644 --- a/monai/visualize/gradient_based.py +++ b/monai/visualize/gradient_based.py @@ -12,7 +12,8 @@ from __future__ import annotations from functools import partial -from typing import Any, Callable +from typing import Any +from collections.abc import Callable import torch diff --git a/tests/bundle/test_config_item.py b/tests/bundle/test_config_item.py index 4909ecf6be..e9f9d5ef8d 100644 --- a/tests/bundle/test_config_item.py +++ b/tests/bundle/test_config_item.py @@ -13,7 +13,7 @@ import unittest from functools import partial -from typing import Callable +from collections.abc import Callable import torch from parameterized import parameterized diff --git a/tests/test_utils.py b/tests/test_utils.py index e365237401..3e7d831b07 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -34,7 +34,8 @@ from itertools import product from pathlib import Path from subprocess import PIPE, Popen -from typing import Any, Callable +from typing import Any +from collections.abc import Callable from urllib.error import ContentTooShortError, HTTPError import numpy as np From 9b385866e59dac7abecd6b90c9949a15912e7693 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 5 Apr 2026 00:18:40 +0100 Subject: [PATCH 34/41] Format fixes and script fixes Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 1 + monai/_version.py | 9 +++++---- monai/apps/pathology/inferers/inferer.py | 3 +-- monai/apps/pathology/transforms/post/array.py | 3 +-- monai/bundle/scripts.py | 3 +-- monai/config/type_definitions.py | 14 +++++++------- monai/data/image_reader.py | 2 +- monai/engines/evaluator.py | 3 +-- monai/engines/trainer.py | 3 +-- monai/networks/nets/vista3d.py | 3 +-- monai/optimizers/lr_finder.py | 2 +- monai/transforms/intensity/dictionary.py | 3 +-- monai/transforms/io/array.py | 3 +-- monai/transforms/io/dictionary.py | 3 +-- monai/transforms/spatial/array.py | 2 +- monai/transforms/utility/array.py | 3 +-- monai/utils/component_store.py | 3 +-- monai/utils/decorators.py | 3 +-- monai/visualize/gradient_based.py | 2 +- requirements-dev.txt | 1 + tests/bundle/test_config_item.py | 2 +- tests/test_utils.py | 3 +-- 22 files changed, 32 insertions(+), 42 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 9efa9e92dd..1dbb36d8f4 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -198,6 +198,7 @@ jobs: name: Install torch cpu from pytorch.org (Windows only) run: | python -m pip install torch==${PYTORCH_VER1} torchvision==${TORCHVISION_VER}+cpu --index-url https://download.pytorch.org/whl/cpu + shell: bash - if: runner.os == 'Linux' name: Install itk pre-release (Linux only) run: | diff --git a/monai/_version.py b/monai/_version.py index 256d3654d9..759cdb5b80 100644 --- a/monai/_version.py +++ b/monai/_version.py @@ -15,7 +15,8 @@ import re import subprocess import sys -from typing import Callable, Dict +from typing import Dict +from collections.abc import Callable import functools @@ -54,8 +55,8 @@ class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" -LONG_VERSION_PY: Dict[str, str] = {} -HANDLERS: Dict[str, Dict[str, Callable]] = {} +LONG_VERSION_PY: dict[str, str] = {} +HANDLERS: dict[str, dict[str, Callable]] = {} def register_vcs_handler(vcs, method): # decorator @@ -145,7 +146,7 @@ def git_get_keywords(versionfile_abs): # _version.py. keywords = {} try: - with open(versionfile_abs, "r") as fobj: + with open(versionfile_abs) as fobj: for line in fobj: if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) diff --git a/monai/apps/pathology/inferers/inferer.py b/monai/apps/pathology/inferers/inferer.py index f4ba74adac..37be148d45 100644 --- a/monai/apps/pathology/inferers/inferer.py +++ b/monai/apps/pathology/inferers/inferer.py @@ -11,9 +11,8 @@ from __future__ import annotations -from collections.abc import Sequence +from collections.abc import Callable, Sequence from typing import Any -from collections.abc import Callable import numpy as np import torch diff --git a/monai/apps/pathology/transforms/post/array.py b/monai/apps/pathology/transforms/post/array.py index a3892049e1..5ab272f018 100644 --- a/monai/apps/pathology/transforms/post/array.py +++ b/monai/apps/pathology/transforms/post/array.py @@ -12,8 +12,7 @@ from __future__ import annotations import warnings -from collections.abc import Sequence -from collections.abc import Callable +from collections.abc import Callable, Sequence import numpy as np import torch diff --git a/monai/bundle/scripts.py b/monai/bundle/scripts.py index 9be611313a..ab02cd552e 100644 --- a/monai/bundle/scripts.py +++ b/monai/bundle/scripts.py @@ -17,14 +17,13 @@ import re import urllib import warnings -from collections.abc import Mapping, Sequence +from collections.abc import Callable, Mapping, Sequence from functools import partial from pathlib import Path from pydoc import locate from shutil import copyfile from textwrap import dedent from typing import Any -from collections.abc import Callable import torch from torch.cuda import is_available diff --git a/monai/config/type_definitions.py b/monai/config/type_definitions.py index 48c0547e31..fe2ec31e0e 100644 --- a/monai/config/type_definitions.py +++ b/monai/config/type_definitions.py @@ -53,7 +53,7 @@ # convenience to end-users. All supplied values will be # internally converted to a tuple of `Hashable`'s before # use -KeysCollection = Union[Collection[Hashable], Hashable] +KeysCollection = Collection[Hashable] | Hashable #: IndexSelection # @@ -61,13 +61,13 @@ # that store a subset of indices to select items from a List or Array like objects. # The indices must be integers, and if a container of indices is specified, the # container must be iterable. -IndexSelection = Union[Iterable[int], int] +IndexSelection = Iterable[int] | int #: Type of datatypes: Adapted from https://github.com/numpy/numpy/blob/v1.21.4/numpy/typing/_dtype_like.py#L121 -DtypeLike = Union[np.dtype, type, str, None] +DtypeLike = np.dtype | type | str | None #: NdarrayOrTensor: Union of numpy.ndarray and torch.Tensor to be used for typing -NdarrayOrTensor = Union[np.ndarray, torch.Tensor] +NdarrayOrTensor = np.ndarray | torch.Tensor #: NdarrayTensor # @@ -76,11 +76,11 @@ NdarrayTensor = TypeVar("NdarrayTensor", bound=NdarrayOrTensor) #: TensorOrList: The TensorOrList type is used for defining `batch-first Tensor` or `list of channel-first Tensor`. -TensorOrList = Union[torch.Tensor, Sequence[torch.Tensor]] +TensorOrList = torch.Tensor | Sequence[torch.Tensor] #: PathLike: The PathLike type is used for defining a file path. -PathLike = Union[str, os.PathLike] +PathLike = str | os.PathLike #: SequenceStr # string or a sequence of strings for `mode` types. -SequenceStr = Union[Sequence[str], str] +SequenceStr = Sequence[str] | str diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index c300476a6b..8d99ed79a0 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -60,7 +60,7 @@ if TYPE_CHECKING: import cupy - NdarrayOrCupy = Union[np.ndarray, cupy.ndarray] + NdarrayOrCupy = np.ndarray | cupy.ndarray else: NdarrayOrCupy = Any diff --git a/monai/engines/evaluator.py b/monai/engines/evaluator.py index 4178dad9b9..62d5f83847 100644 --- a/monai/engines/evaluator.py +++ b/monai/engines/evaluator.py @@ -12,9 +12,8 @@ from __future__ import annotations import warnings -from collections.abc import Iterable, Sequence +from collections.abc import Callable, Iterable, Sequence from typing import TYPE_CHECKING, Any -from collections.abc import Callable import torch from torch.utils.data import DataLoader diff --git a/monai/engines/trainer.py b/monai/engines/trainer.py index b958ca4ec2..921d54a59c 100644 --- a/monai/engines/trainer.py +++ b/monai/engines/trainer.py @@ -12,9 +12,8 @@ from __future__ import annotations import warnings -from collections.abc import Iterable, Sequence +from collections.abc import Callable, Iterable, Sequence from typing import TYPE_CHECKING, Any -from collections.abc import Callable import torch from torch.optim.optimizer import Optimizer diff --git a/monai/networks/nets/vista3d.py b/monai/networks/nets/vista3d.py index df5250dac0..232b8c1c11 100644 --- a/monai/networks/nets/vista3d.py +++ b/monai/networks/nets/vista3d.py @@ -12,9 +12,8 @@ from __future__ import annotations import math -from collections.abc import Sequence +from collections.abc import Callable, Sequence from typing import Any -from collections.abc import Callable import numpy as np import torch diff --git a/monai/optimizers/lr_finder.py b/monai/optimizers/lr_finder.py index bae04efff8..8692d2622f 100644 --- a/monai/optimizers/lr_finder.py +++ b/monai/optimizers/lr_finder.py @@ -14,9 +14,9 @@ import pickle import types import warnings +from collections.abc import Callable from functools import partial from typing import TYPE_CHECKING, Any -from collections.abc import Callable import numpy as np import torch diff --git a/monai/transforms/intensity/dictionary.py b/monai/transforms/intensity/dictionary.py index f0878c0c99..0c25d4ac99 100644 --- a/monai/transforms/intensity/dictionary.py +++ b/monai/transforms/intensity/dictionary.py @@ -17,8 +17,7 @@ from __future__ import annotations -from collections.abc import Hashable, Mapping, Sequence -from collections.abc import Callable +from collections.abc import Callable, Hashable, Mapping, Sequence import numpy as np diff --git a/monai/transforms/io/array.py b/monai/transforms/io/array.py index 95beb5ae96..049779f606 100644 --- a/monai/transforms/io/array.py +++ b/monai/transforms/io/array.py @@ -20,10 +20,9 @@ import sys import traceback import warnings -from collections.abc import Sequence +from collections.abc import Callable, Sequence from pathlib import Path from pydoc import locate -from collections.abc import Callable import numpy as np import torch diff --git a/monai/transforms/io/dictionary.py b/monai/transforms/io/dictionary.py index fc634baa30..4927450c7d 100644 --- a/monai/transforms/io/dictionary.py +++ b/monai/transforms/io/dictionary.py @@ -17,9 +17,8 @@ from __future__ import annotations -from collections.abc import Hashable, Mapping +from collections.abc import Callable, Hashable, Mapping from pathlib import Path -from collections.abc import Callable import numpy as np diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index 6aba71a0f6..db926bb938 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -118,7 +118,7 @@ "RandSimulateLowResolution", ] -RandRange = Optional[Sequence[tuple[float, float] | float] | float] +RandRange = Sequence[tuple[float, float] | float] | float | None class SpatialResample(InvertibleTransform, LazyTransform): diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index 1483441dc1..b39dd93931 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -18,11 +18,10 @@ import sys import time import warnings -from collections.abc import Hashable, Mapping, Sequence +from collections.abc import Callable, Hashable, Mapping, Sequence from copy import deepcopy from functools import partial from typing import Any -from collections.abc import Callable import numpy as np import torch diff --git a/monai/utils/component_store.py b/monai/utils/component_store.py index 6713b61769..360cea8fe3 100644 --- a/monai/utils/component_store.py +++ b/monai/utils/component_store.py @@ -12,11 +12,10 @@ from __future__ import annotations from collections import namedtuple -from collections.abc import Iterable +from collections.abc import Callable, Iterable from keyword import iskeyword from textwrap import dedent, indent from typing import Any, TypeVar -from collections.abc import Callable T = TypeVar("T") diff --git a/monai/utils/decorators.py b/monai/utils/decorators.py index b6cfbf2bf7..4a8b098ce1 100644 --- a/monai/utils/decorators.py +++ b/monai/utils/decorators.py @@ -15,8 +15,7 @@ __all__ = ["RestartGenerator", "MethodReplacer"] -from collections.abc import Generator -from collections.abc import Callable +from collections.abc import Callable, Generator class RestartGenerator: diff --git a/monai/visualize/gradient_based.py b/monai/visualize/gradient_based.py index d858a3dfce..a8d81eb579 100644 --- a/monai/visualize/gradient_based.py +++ b/monai/visualize/gradient_based.py @@ -11,9 +11,9 @@ from __future__ import annotations +from collections.abc import Callable from functools import partial from typing import Any -from collections.abc import Callable import torch diff --git a/requirements-dev.txt b/requirements-dev.txt index f7717c1510..a948de701c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -62,3 +62,4 @@ pyamg>=5.0.0, <5.3.0 git+https://github.com/facebookresearch/segment-anything.git@6fdee8f2727f4506cfbbe553e23b895e27956588 onnx_graphsurgeon polygraphy +pybind11 diff --git a/tests/bundle/test_config_item.py b/tests/bundle/test_config_item.py index e9f9d5ef8d..e7becb66bc 100644 --- a/tests/bundle/test_config_item.py +++ b/tests/bundle/test_config_item.py @@ -12,8 +12,8 @@ from __future__ import annotations import unittest -from functools import partial from collections.abc import Callable +from functools import partial import torch from parameterized import parameterized diff --git a/tests/test_utils.py b/tests/test_utils.py index 3e7d831b07..d040a10a51 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -28,14 +28,13 @@ import traceback import unittest import warnings -from collections.abc import Iterable +from collections.abc import Callable, Iterable from contextlib import contextmanager from functools import partial, reduce from itertools import product from pathlib import Path from subprocess import PIPE, Popen from typing import Any -from collections.abc import Callable from urllib.error import ContentTooShortError, HTTPError import numpy as np From 6309f30b143197862adc2c3665eb03716d22f709 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 23:18:58 +0000 Subject: [PATCH 35/41] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- monai/_version.py | 1 - monai/config/type_definitions.py | 2 +- monai/data/image_reader.py | 2 +- monai/transforms/spatial/array.py | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/monai/_version.py b/monai/_version.py index 759cdb5b80..f234227104 100644 --- a/monai/_version.py +++ b/monai/_version.py @@ -15,7 +15,6 @@ import re import subprocess import sys -from typing import Dict from collections.abc import Callable import functools diff --git a/monai/config/type_definitions.py b/monai/config/type_definitions.py index fe2ec31e0e..afe13abf37 100644 --- a/monai/config/type_definitions.py +++ b/monai/config/type_definitions.py @@ -13,7 +13,7 @@ import os from collections.abc import Collection, Hashable, Iterable, Sequence -from typing import TypeVar, Union +from typing import TypeVar import numpy as np import torch diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index 8d99ed79a0..08697c3fee 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -22,7 +22,7 @@ from collections.abc import Callable, Iterable, Iterator, Sequence from dataclasses import dataclass from pathlib import Path -from typing import TYPE_CHECKING, Any, Union +from typing import TYPE_CHECKING, Any import numpy as np from torch.utils.data._utils.collate import np_str_obj_array_pattern diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index db926bb938..d6b5ed8641 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -18,7 +18,7 @@ from collections.abc import Callable, Sequence from copy import deepcopy from itertools import zip_longest -from typing import Any, Optional, cast +from typing import Any, cast import numpy as np import torch From 8e54c6418e7652acbe620bd1d86ecfad4ba71c5c Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 5 Apr 2026 20:15:23 +0100 Subject: [PATCH 36/41] Adding pybind11 to test MacOS failure Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 1dbb36d8f4..cfb5dce328 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -205,7 +205,7 @@ jobs: python -m pip install --pre -U itk - name: Install the complete dependencies run: | - python -m pip install --user --upgrade pip wheel + python -m pip install --user --upgrade pip wheel pybind11 python -m pip install torch==${PYTORCH_VER1} torchvision==${TORCHVISION_VER} cat "requirements-dev.txt" python -m pip install --no-build-isolation -r requirements-dev.txt From 20570f3289658c67d5020112afb32afe012060bb Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 5 Apr 2026 23:25:31 +0100 Subject: [PATCH 37/41] mypy fixes Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 2 +- monai/apps/vista3d/inferer.py | 4 +++- monai/data/image_reader.py | 6 +++--- monai/networks/layers/convutils.py | 13 +++++-------- monai/networks/nets/daf3d.py | 1 + monai/networks/nets/dints.py | 8 ++++---- monai/optimizers/lr_scheduler.py | 2 +- monai/transforms/intensity/array.py | 4 ++-- monai/transforms/utils_pytorch_numpy_unification.py | 4 ++-- monai/visualize/visualizer.py | 3 ++- 10 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index cfb5dce328..47376f760b 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -205,7 +205,7 @@ jobs: python -m pip install --pre -U itk - name: Install the complete dependencies run: | - python -m pip install --user --upgrade pip wheel pybind11 + python -m pip install --user --upgrade pip wheel pybind11 # pybind11 added for macOS, may not be needed python -m pip install torch==${PYTORCH_VER1} torchvision==${TORCHVISION_VER} cat "requirements-dev.txt" python -m pip install --no-build-isolation -r requirements-dev.txt diff --git a/monai/apps/vista3d/inferer.py b/monai/apps/vista3d/inferer.py index bdd833af9d..aedeb5f347 100644 --- a/monai/apps/vista3d/inferer.py +++ b/monai/apps/vista3d/inferer.py @@ -77,7 +77,7 @@ def point_based_window_inferer( image, pad = _pad_previous_mask(copy.deepcopy(inputs), roi_size) point_coords = point_coords + torch.tensor([pad[-2], pad[-4], pad[-6]]).to(point_coords.device) prev_mask = _pad_previous_mask(copy.deepcopy(prev_mask), roi_size)[0] if prev_mask is not None else None - stitched_output = None + stitched_output: torch.Tensor | None = None for p in point_coords[0][point_start:]: lx_, rx_ = _get_window_idx(p[0], roi_size[0], image.shape[-3], center_only=center_only, margin=margin) ly_, ry_ = _get_window_idx(p[1], roi_size[1], image.shape[-2], center_only=center_only, margin=margin) @@ -113,6 +113,8 @@ def point_based_window_inferer( ) stitched_output[unravel_slice] += output.to("cpu") stitched_mask[unravel_slice] = 1 + + assert stitched_output is not None # needed for correct typing below # if stitched_mask is 0, then NaN value stitched_output = stitched_output / stitched_mask # revert padding diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py index 08697c3fee..c281e4fc67 100644 --- a/monai/data/image_reader.py +++ b/monai/data/image_reader.py @@ -22,7 +22,7 @@ from collections.abc import Callable, Iterable, Iterator, Sequence from dataclasses import dataclass from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, TypeAlias import numpy as np from torch.utils.data._utils.collate import np_str_obj_array_pattern @@ -60,9 +60,9 @@ if TYPE_CHECKING: import cupy - NdarrayOrCupy = np.ndarray | cupy.ndarray + NdarrayOrCupy: TypeAlias = np.ndarray | cupy.ndarray else: - NdarrayOrCupy = Any + NdarrayOrCupy: TypeAlias = Any __all__ = ["ImageReader", "ITKReader", "NibabelReader", "NumpyReader", "PILReader", "PydicomReader", "NrrdReader"] diff --git a/monai/networks/layers/convutils.py b/monai/networks/layers/convutils.py index fc8ea03809..6602bcbcd6 100644 --- a/monai/networks/layers/convutils.py +++ b/monai/networks/layers/convutils.py @@ -12,6 +12,7 @@ from __future__ import annotations from collections.abc import Sequence +from typing import cast import numpy as np import torch @@ -118,14 +119,10 @@ def gaussian_1d( out = out / (2.5066282 * sigma) elif approx.lower() == "scalespace": sigma2 = sigma * sigma - out_pos: list[torch.Tensor | None] = [None] * (tail + 1) - out_pos[0] = _modified_bessel_0(sigma2) - out_pos[1] = _modified_bessel_1(sigma2) - for k in range(2, len(out_pos)): - out_pos[k] = _modified_bessel_i(k, sigma2) - out = out_pos[:0:-1] - out.extend(out_pos) - out = torch.stack(out) * torch.exp(-sigma2) + out_pos: list[torch.Tensor] = [_modified_bessel_0(sigma2), _modified_bessel_1(sigma2)] + out_pos += [_modified_bessel_i(k, sigma2) for k in range(2, tail + 1)] + out_pos_mirror = out_pos[:0:-1] + out_pos + out = torch.stack(out_pos_mirror) * torch.exp(-sigma2) else: raise NotImplementedError(f"Unsupported option: approx='{approx}'.") return out / out.sum() if normalize else out # type: ignore diff --git a/monai/networks/nets/daf3d.py b/monai/networks/nets/daf3d.py index 02e5bb022a..4e47d79a2d 100644 --- a/monai/networks/nets/daf3d.py +++ b/monai/networks/nets/daf3d.py @@ -570,6 +570,7 @@ def forward(self, x): supervised_final = self.predict2(aspp) + output: list | torch.Tensor if self.training: output = supervised1 + supervised2 + [supervised_final] output = [F.interpolate(o, size=x.size()[2:], mode="trilinear") for o in output] diff --git a/monai/networks/nets/dints.py b/monai/networks/nets/dints.py index f87fcebea8..98f8de5772 100644 --- a/monai/networks/nets/dints.py +++ b/monai/networks/nets/dints.py @@ -923,8 +923,8 @@ def get_topology_entropy(self, probs): for res_idx in range(len(self.arch_code2out)): _node_out[self.arch_code2out[res_idx]] += self.child_list[child_idx][res_idx] _node_in[self.arch_code2in[res_idx]] += self.child_list[child_idx][res_idx] - _node_in = (_node_in >= 1).astype(int) - _node_out = (_node_out >= 1).astype(int) + _node_in = (_node_in >= 1).astype(int) # type: ignore + _node_out = (_node_out >= 1).astype(int) # type: ignore node2in[self.node_act_dict[str(_node_out)]].append(child_idx) node2out[self.node_act_dict[str(_node_in)]].append(child_idx) self.node2in = node2in @@ -976,7 +976,7 @@ def decode(self): _node_act = np.zeros(self.num_depths).astype(int) for path_idx in range(len(self.child_list[child_idx])): _node_act[self.arch_code2out[path_idx]] += self.child_list[child_idx][path_idx] - _node_act = (_node_act >= 1).astype(int) + _node_act = (_node_act >= 1).astype(int) # type: ignore for mtx in self.transfer_mtx[str(_node_act)]: connect_child_idx = path2child[str(mtx.flatten()[self.tidx].astype(int))] sub_amtx[child_idx, connect_child_idx] = 1 @@ -1014,7 +1014,7 @@ def decode(self): a_idx -= 1 for res_idx in range(len(self.arch_code2out)): node_a[a_idx, self.arch_code2in[res_idx]] += arch_code_a[0, res_idx] - node_a = (node_a >= 1).astype(int) + node_a = (node_a >= 1).astype(int) # type: ignore return node_a, arch_code_a, arch_code_c, arch_code_a_max def forward(self, x): diff --git a/monai/optimizers/lr_scheduler.py b/monai/optimizers/lr_scheduler.py index 8f89352158..96c1412fea 100644 --- a/monai/optimizers/lr_scheduler.py +++ b/monai/optimizers/lr_scheduler.py @@ -107,4 +107,4 @@ def get_lr(self): if self.last_epoch < self.warmup_steps: return current_lr else: - return [max(self.end_lr, _current_lr) for _current_lr in current_lr] + return [max(self.end_lr, _current_lr) for _current_lr in current_lr] # type: ignore diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py index 986a715c22..23a57ae9fb 100644 --- a/monai/transforms/intensity/array.py +++ b/monai/transforms/intensity/array.py @@ -17,7 +17,7 @@ from abc import abstractmethod from collections.abc import Callable, Iterable, Sequence from functools import partial -from typing import Any +from typing import Any, cast from warnings import warn import numpy as np @@ -1872,7 +1872,7 @@ def interp(self, x: NdarrayOrTensor, xp: NdarrayOrTensor, fp: NdarrayOrTensor) - ns = torch if isinstance(x, torch.Tensor) else np if isinstance(x, np.ndarray): # approx 2x faster than code below for ndarray - return np.interp(x, xp, fp) + return cast(np.ndarray, np.interp(x, xp, fp)) m = (fp[1:] - fp[:-1]) / (xp[1:] - xp[:-1]) b = fp[:-1] - (m * xp[:-1]) diff --git a/monai/transforms/utils_pytorch_numpy_unification.py b/monai/transforms/utils_pytorch_numpy_unification.py index 66756f4476..1bc9c206d8 100644 --- a/monai/transforms/utils_pytorch_numpy_unification.py +++ b/monai/transforms/utils_pytorch_numpy_unification.py @@ -12,7 +12,7 @@ from __future__ import annotations from collections.abc import Sequence -from typing import TypeVar +from typing import TypeVar, cast import numpy as np import torch @@ -65,7 +65,7 @@ def softplus(x: NdarrayOrTensor) -> NdarrayOrTensor: Softplus of the input. """ if isinstance(x, np.ndarray): - return np.logaddexp(np.zeros_like(x), x) + return cast(np.ndarray, np.logaddexp(np.zeros_like(x), x)) return torch.logaddexp(torch.zeros_like(x), x) diff --git a/monai/visualize/visualizer.py b/monai/visualize/visualizer.py index e7f5d9bbbe..023e444406 100644 --- a/monai/visualize/visualizer.py +++ b/monai/visualize/visualizer.py @@ -31,6 +31,7 @@ def default_upsampler(spatial_size: Sized, align_corners: bool = False) -> Calla def up(x): linear_mode = [InterpolateMode.LINEAR, InterpolateMode.BILINEAR, InterpolateMode.TRILINEAR] interp_mode = linear_mode[len(spatial_size) - 1] - return F.interpolate(x, size=spatial_size, mode=str(interp_mode.value), align_corners=align_corners) + smode = str(interp_mode.value) + return F.interpolate(x, size=spatial_size, mode=smode, align_corners=align_corners) # type: ignore return up From 5f5482b7b8b44a772db95212f853169273bae98e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 5 Apr 2026 22:25:49 +0000 Subject: [PATCH 38/41] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- monai/networks/layers/convutils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monai/networks/layers/convutils.py b/monai/networks/layers/convutils.py index 6602bcbcd6..f4d321ea1c 100644 --- a/monai/networks/layers/convutils.py +++ b/monai/networks/layers/convutils.py @@ -12,7 +12,6 @@ from __future__ import annotations from collections.abc import Sequence -from typing import cast import numpy as np import torch From 8ffacc83d6f76c4706ecb0d6754a346e591954d6 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Sun, 5 Apr 2026 23:49:54 +0100 Subject: [PATCH 39/41] Enable tests Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index 47376f760b..ce86f2ce73 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -151,7 +151,7 @@ jobs: run: | python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' python -c "import monai; monai.config.print_config()" - # ./runtests.sh --min + ./runtests.sh --min shell: bash env: QUICKTEST: True @@ -221,7 +221,7 @@ jobs: run: | python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))' python -c "import monai; monai.config.print_config()" - # python -m unittest -v + python -m unittest -v packaging: # Test package generation runs-on: ubuntu-latest From ed2847582e570d52a9a32ca67922f2576c7b10fe Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 6 Apr 2026 11:40:55 +0100 Subject: [PATCH 40/41] Test fixes Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 4 ++-- tests/test_utils.py | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index ce86f2ce73..ca1ecb6dc1 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -37,7 +37,7 @@ env: PYTORCH_VER2: '2.9.1' PYTORCH_VER3: '2.10.0' PYTORCH_VER4: '2.11.0' - TORCHVISION_VER: '0.23.0' # used for testing with lowest PyTorch version + TORCHVISION_VER: '0.23.0' # used for testing with lowest PyTorch version (PYTORCH_VER1), update as needed PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354 # These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of @@ -98,7 +98,7 @@ jobs: pytorch-version: '2.8.0' python-version: '3.13' - os: ubuntu-latest - pytorch-version: '2.9.0' + pytorch-version: '2.9.1' python-version: '3.14' # Test PyTorch versions under Ubuntu with lowest Python version supported diff --git a/tests/test_utils.py b/tests/test_utils.py index d040a10a51..b1babe983d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -533,7 +533,7 @@ def run_process(self, func, local_rank, args, kwargs, results): time.sleep(0.1) results.put(True) except Exception as e: - results.put(False) + results.put(str(e)) raise e finally: os.environ.clear() @@ -562,15 +562,17 @@ def _wrapper(*args, **kwargs): results = tmp.Queue() func = _call_original_func args = [obj.__name__, obj.__module__] + list(args) + for proc_rank in range(self.nproc_per_node): - p = tmp.Process( - target=self.run_process, args=(func, proc_rank, args, kwargs, results), daemon=self.daemon - ) + run_args = (func, proc_rank, args, kwargs, results) + p = tmp.Process(target=self.run_process, args=run_args, daemon=self.daemon) p.start() processes.append(p) + for p in processes: p.join() - assert results.get(), "Distributed call failed." + pr=results.get() + assert pr is True, f"Distributed call failed: {pr}" _del_original_func(obj) return _wrapper From 7e3b15cec9bcfaefe2f166a8a0c499af887c9635 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:00:27 +0100 Subject: [PATCH 41/41] Test fixes Signed-off-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com> --- .github/workflows/cicd_tests.yml | 8 ++++---- tests/test_utils.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cicd_tests.yml b/.github/workflows/cicd_tests.yml index ca1ecb6dc1..0993a87b62 100644 --- a/.github/workflows/cicd_tests.yml +++ b/.github/workflows/cicd_tests.yml @@ -31,7 +31,7 @@ env: PYTHON_VER2: '3.11' PYTHON_VER3: '3.12' PYTHON_VER4: '3.13' - PYTHON_VER5: '3.14' + # PYTHON_VER5: '3.14' # TODO: not compatible with Torchscript, re-enable once Torchscript removed from MONAI # supported versions of PyTorch PYTORCH_VER1: '2.8.0' PYTORCH_VER2: '2.9.1' @@ -97,9 +97,9 @@ jobs: - os: ubuntu-latest pytorch-version: '2.8.0' python-version: '3.13' - - os: ubuntu-latest - pytorch-version: '2.9.1' - python-version: '3.14' + # - os: ubuntu-latest + # pytorch-version: '2.9.1' + # python-version: '3.14' # Test PyTorch versions under Ubuntu with lowest Python version supported - os: ubuntu-latest diff --git a/tests/test_utils.py b/tests/test_utils.py index b1babe983d..8bdbf6423e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -571,7 +571,7 @@ def _wrapper(*args, **kwargs): for p in processes: p.join() - pr=results.get() + pr = results.get() assert pr is True, f"Distributed call failed: {pr}" _del_original_func(obj)