From 466a9d8fb99135c31e0fbefdbf8cd2a4f31e2e34 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 20:30:44 +0200 Subject: [PATCH 1/9] test(checksum32): wrap parametrize itertools.product in tuple pytest 9 raises PytestRemovedIn10Warning for non-Collection iterables passed to parametrize, which becomes an error under filterwarnings=error and aborts test collection. Same change as 15803df on backport-0.15-zstd-fixes. Assisted-by: ClaudeCode:claude-fable-5.1 --- numcodecs/tests/test_checksum32.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numcodecs/tests/test_checksum32.py b/numcodecs/tests/test_checksum32.py index 06b0a1a8c..cbdd80293 100644 --- a/numcodecs/tests/test_checksum32.py +++ b/numcodecs/tests/test_checksum32.py @@ -63,12 +63,12 @@ def get_all_codecs(): return codecs -@pytest.mark.parametrize(("codec", "arr"), itertools.product(get_all_codecs(), arrays)) +@pytest.mark.parametrize(("codec", "arr"), tuple(itertools.product(get_all_codecs(), arrays))) def test_encode_decode(codec, arr): check_encode_decode(arr, codec) -@pytest.mark.parametrize(("codec", "arr"), itertools.product(get_all_codecs(), arrays)) +@pytest.mark.parametrize(("codec", "arr"), tuple(itertools.product(get_all_codecs(), arrays))) def test_errors(codec, arr): enc = codec.encode(arr) with pytest.raises(RuntimeError): From d2842acda1a014d88ff15c6790ae95ab3306eda4 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 20:30:58 +0200 Subject: [PATCH 2/9] ci: stop testing the 0.16.x line against zarr-python main zarr-python main now requires Python >=3.12, while this line supports Python >=3.11. uv resolves all dependency groups together, so the test-zarr-main group made every uv invocation fail with an unsatisfiable resolution (seen in the i386 workflow). A maintenance line does not need to track zarr-python main, so remove the group, its pixi tasks, and its CI matrix entry. Assisted-by: ClaudeCode:claude-fable-5.1 --- .github/workflows/ci.yaml | 2 +- pyproject.toml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2c6a53507..1aec3e3ad 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -75,7 +75,7 @@ jobs: strategy: fail-fast: false matrix: - zarr-version: ["312", "313", "main"] + zarr-version: ["312", "313"] defaults: run: diff --git a/pyproject.toml b/pyproject.toml index db2f3b618..f49e2d33d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,12 +92,6 @@ test-zarr-313 = [ "zarr==3.1.3", "crc32c", ] -test-zarr-main = [ - "pytest", - "pytest-cov", - "zarr @ git+https://github.com/zarr-developers/zarr-python.git@main", - "crc32c", -] [tool.setuptools] package-dir = {"" = "."} @@ -250,7 +244,6 @@ conflicts = [ [ { group = "test-zarr-312" }, { group = "test-zarr-313" }, - { group = "test-zarr-main" } ] ] @@ -283,10 +276,8 @@ test-google-crc32c = ["test", "test-google-crc32c"] [tool.pixi.tasks] ls-deps-312 = "uv run --group test-zarr-312 uv pip freeze" ls-deps-313 = "uv run --group test-zarr-313 uv pip freeze" -ls-deps-main = "uv run --group test-zarr-main uv pip freeze" test-zarr-312 = "uv run --group test-zarr-312 pytest numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" test-zarr-313 = "uv run --group test-zarr-313 pytest numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" -test-zarr-main = "uv run --group test-zarr-main pytest numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" [tool.pixi.feature.test.tasks] run-tests = "pytest -v" From 9176a4df5a8382cc2e00666acbdf1b45bbfb6369 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 20:30:59 +0200 Subject: [PATCH 3/9] ci: replace the macos-13 runner with macos-15-large macos-13 runners are no longer available. macos-15-large is still an Intel runner, so x86 coverage is preserved. macOS 15's dyld rejects the duplicate LC_RPATH entries that the conda-forge compilers produce, so add the same deduplication step used on backport-0.15-zstd-fixes (64eade5, 7ae0f4b). Assisted-by: ClaudeCode:claude-fable-5.1 --- .github/workflows/ci.yaml | 22 +++++++++++++++++++--- .github/workflows/wheel.yaml | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1aec3e3ad..08ef96fd9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,8 +13,8 @@ jobs: fail-fast: false matrix: python-version: ["3.11", "3.12", "3.13", "3.14"] - # macos-13 is an intel runner, macos-14 is an arm64 runner - platform: [ubuntu-latest, ubuntu-22.04-arm, windows-latest, macos-13, macos-14] + # macos-15-large is an intel runner, macos-14 is an arm64 runner + platform: [ubuntu-latest, ubuntu-22.04-arm, windows-latest, macos-15-large, macos-14] defaults: run: @@ -38,7 +38,7 @@ jobs: run: conda install -y c-compiler cxx-compiler - name: Install clang - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-large' run: conda install -y 'clang>=12.0.1,<17' - name: Show conda environment info @@ -57,6 +57,22 @@ jobs: python -m pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,pcodec,zfpy] fi + - name: Deduplicate LC_RPATH entries + # The conda-forge compilers inject -Wl,-rpath,$PREFIX/lib multiple + # times, producing duplicate LC_RPATH load commands. macOS 15's dyld + # rejects duplicate LC_RPATH at load time, so strip the extras. + if: runner.os == 'macOS' + run: | + rpaths() { otool -l "$1" | awk '/ LC_RPATH$/{getline; getline; print $2}'; } + for so in numcodecs/*.so; do + for rp in $(rpaths "$so" | sort | uniq -d); do + while [ "$(rpaths "$so" | grep -cx "$rp")" -gt 1 ]; do + echo "Removing duplicate LC_RPATH '$rp' from $so" + install_name_tool -delete_rpath "$rp" "$so" + done + done + done + - name: List installed packages run: python -m pip list diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index 466b90185..a006d513d 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -19,8 +19,8 @@ jobs: strategy: fail-fast: false matrix: - # macos-13 is an intel runner, macos-14 is an arm64 runner - os: [ubuntu-latest, ubuntu-22.04-arm, windows-latest, macos-13, macos-14] + # macos-15-large is an intel runner, macos-14 is an arm64 runner + os: [ubuntu-latest, ubuntu-22.04-arm, windows-latest, macos-15-large, macos-14] env: CIBW_TEST_COMMAND: python -c "import numcodecs" CIBW_BUILD: "cp311-* cp312-* cp313-* cp314-*" From 456930f53c7ae7cdf7ac77adb303cb2ad5a3d6b6 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 20:30:59 +0200 Subject: [PATCH 4/9] ci(docs): build on ubuntu-24.04 on Read the Docs Read the Docs removed the ubuntu-20.04 build image. Assisted-by: ClaudeCode:claude-fable-5.1 --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index fa14bf340..44e973358 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,7 +4,7 @@ submodules: include: all build: - os: ubuntu-20.04 + os: ubuntu-24.04 tools: python: "3.12" jobs: From 8b44a43fc7052b421e2db4bfcf0690c07ee9db61 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 20:37:30 +0200 Subject: [PATCH 5/9] ci: stop pinning clang below 17 on the Intel macOS runner The pin downgraded the conda-forge compiler to clang 14, which cannot parse the macOS 15 SDK headers on macos-15-large (math.h: '_Float16 is not supported on this target'), so every extension build failed. Use the clang that the conda-forge c-compiler package installs instead. Assisted-by: ClaudeCode:claude-fable-5.1 --- .github/workflows/ci.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 08ef96fd9..3747a29a1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,10 +37,6 @@ jobs: - name: Install compilers run: conda install -y c-compiler cxx-compiler - - name: Install clang - if: matrix.platform == 'macos-15-large' - run: conda install -y 'clang>=12.0.1,<17' - - name: Show conda environment info run: | conda info From 9939e5433a8cb1c5979b9e07b09496c1aa4becc1 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 20:49:31 +0200 Subject: [PATCH 6/9] ci(i386): install zfpy with uv pip instead of uv add zfp's pyproject.toml has no [project] table, so 'uv add "zfpy @ ./zfp"' fails with 'No project table found'. Install the locally built zfpy into the environment with 'uv pip install ./zfp', as main does. Because zfpy is no longer recorded in pyproject.toml, keep the same virtual environment for the numcodecs install and run pytest with --no-sync so uv does not re-resolve the environment. Assisted-by: ClaudeCode:claude-fable-5.1 --- .github/workflows/ci-i386.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-i386.yml b/.github/workflows/ci-i386.yml index 61f46b7c7..3544e41ea 100644 --- a/.github/workflows/ci-i386.yml +++ b/.github/workflows/ci-i386.yml @@ -56,13 +56,12 @@ jobs: uv run cmake zfp -B zfp/build -DBUILD_ZFPY=ON -DBUILD_TESTING=OFF -DPYTHON_LIBRARY=$PYTHON_LIB -DPYTHON_INCLUDE_DIR=$PYTHON_INCLUDE uv run make -j -C zfp/build uv run sudo make -C zfp/build install - uv add "zfpy @ ./zfp" + uv pip install ./zfp shell: alpine.sh {0} - name: Install numcodecs run: | export DISABLE_NUMCODECS_AVX2="" - uv venv # TODO: Remove this conditional when pcodec supports Python 3.14 if [[ "${{ matrix.python-version }}" == "3.14" ]]; then uv pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,zfpy] @@ -76,5 +75,5 @@ jobs: shell: alpine.sh {0} - name: Run tests - run: uv run pytest -v + run: uv run --no-sync pytest -v shell: alpine.sh {0} From 5d1d7c0e56b1a4f11efbba980f472a44e8c3939a Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 21:04:18 +0200 Subject: [PATCH 7/9] ci(i386): stop installing pcodec in the i386 job This workflow has no matrix, so the python-version conditional always took the branch that installs pcodec. pcodec has no i386 wheel and its source build produces a wheel tagged linux_x86_64, which uv refuses to install in the i386 Alpine environment. Install without pcodec, as main does; the pcodec tests are skipped when it is missing. Assisted-by: ClaudeCode:claude-fable-5.1 --- .github/workflows/ci-i386.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-i386.yml b/.github/workflows/ci-i386.yml index 3544e41ea..4f63cfa9f 100644 --- a/.github/workflows/ci-i386.yml +++ b/.github/workflows/ci-i386.yml @@ -62,12 +62,9 @@ jobs: - name: Install numcodecs run: | export DISABLE_NUMCODECS_AVX2="" - # TODO: Remove this conditional when pcodec supports Python 3.14 - if [[ "${{ matrix.python-version }}" == "3.14" ]]; then - uv pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,zfpy] - else - uv pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,pcodec,zfpy] - fi + # pcodec is left out: it has no i386 wheel, and its source build + # produces a wheel tagged x86_64 that cannot be installed here. + uv pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,zfpy] shell: alpine.sh {0} - name: List installed packages From 6a48c7a099d870cdf5368eb05aba33757a9e3641 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 21:14:27 +0200 Subject: [PATCH 8/9] test(pyzstd): skip test_pyzstd when pyzstd cannot be imported On Python 3.14, pyzstd imports the standard library's compression.zstd, which needs the _zstd extension module. Alpine's i386 Python does not ship it, so importing pyzstd raised ModuleNotFoundError and aborted test collection. Use pytest.importorskip, as main does (#845). Assisted-by: ClaudeCode:claude-fable-5.1 --- numcodecs/tests/test_pyzstd.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/numcodecs/tests/test_pyzstd.py b/numcodecs/tests/test_pyzstd.py index 7ee6084b4..4474f5805 100644 --- a/numcodecs/tests/test_pyzstd.py +++ b/numcodecs/tests/test_pyzstd.py @@ -2,9 +2,10 @@ import numpy as np import pytest -import pyzstd -from numcodecs.zstd import Zstd +pyzstd = pytest.importorskip("pyzstd") + +from numcodecs.zstd import Zstd # noqa: E402 test_data = [ b"Hello World!", From a38a16f7a7a6d74ae5c8dc2f6e329e7aed70d328 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Mon, 5 Oct 2026 21:34:43 +0200 Subject: [PATCH 9/9] ci(codecov): compare project coverage against the base commit codecov/project has failed on every recent commit of this line, including the 0.16.5 release, at 98.68% against a 100% target. The uncovered lines are in numcodecs/zarr3.py and the crc32c fallback paths, which the coverage-uploading jobs do not exercise. Set the project target to auto so the check fails only when a change lowers coverage. The patch target stays at 100%. Assisted-by: ClaudeCode:claude-fable-5.1 --- .github/codecov.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/codecov.yml b/.github/codecov.yml index e9b99c821..9b2c0d7ea 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -2,7 +2,10 @@ coverage: status: project: default: - target: 100 + # Compare against the base commit instead of requiring 100%: on this + # maintenance branch the zarr and crc32c fallback paths are not + # covered by the jobs that upload coverage. + target: auto threshold: 0.1 patch: default: