diff --git a/.github/codecov.yml b/.github/codecov.yml index e9b99c821..e9b2ef7cd 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -7,6 +7,8 @@ coverage: patch: default: target: 100 + ignore: + - "numcodecs/tests/**" comment: layout: "diff, files" behavior: default diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a2a62c448..61f8a6f7e 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"] - # macos-13 is an intel runner, macos-14 is a arm64 runner - platform: [ubuntu-latest, windows-latest, macos-13, macos-14] + # macos-15-large is an intel runner, macos-14 is a arm64 runner + platform: [ubuntu-latest, windows-latest, macos-15-large, macos-14] defaults: run: @@ -37,9 +37,11 @@ jobs: - name: Install compilers run: conda install -y c-compiler cxx-compiler - - name: Install clang - if: matrix.platform == 'macos-13' - run: conda install -y 'clang>=12.0.1,<17' + - name: Install GCC 14 + # GCC 15 defaults to C23, where `bool` is a keyword, and the c-blosc + # version bundled on this branch still defines `bool` with a typedef. + if: runner.os == 'Linux' + run: conda install -y 'gcc<15' 'gxx<15' - name: Show conda environment info run: | @@ -49,15 +51,36 @@ jobs: - name: Install numcodecs run: | - export DISABLE_NUMCODECS_AVX2="" + # On this branch setup.py adds -mno-avx2 whenever this variable is set, and + # recent clang rejects that flag on arm64, so only set it on x86_64. + if [[ "$(uname -m)" == "x86_64" ]]; then + export DISABLE_NUMCODECS_AVX2="" + fi python -m pip install -v -e .[test,test_extras,msgpack,crc32c,pcodec,zfpy] + - 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: Install zarr-python # Since zarr v3 requires numpy >= 1.25, on Python 3.11 leave it out # so we can have some tests of our minimum version of numpy (1.24) if: matrix.python-version != '3.11' - # TODO: remove --pre option when zarr v3 is out - run: python -m pip install --pre zarr>=3.0.0b2 + # numcodecs.zarr3 in this branch targets the zarr 3.0.x API; zarr 3.1+ + # moved these codecs into zarr itself and changed internal APIs. + run: python -m pip install "zarr>=3.0,<3.1" - name: List installed packages run: python -m pip list diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index 6746ffb8f..8227cfa90 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -13,8 +13,8 @@ jobs: strategy: fail-fast: false matrix: - # macos-13 is an intel runner, macos-14 is a arm64 runner - os: [ubuntu-latest, windows-latest, macos-13, macos-14] + # macos-15-large is an intel runner, macos-14 is an arm64 runner + os: [ubuntu-latest, windows-latest, macos-15-large, macos-14] env: CIBW_TEST_COMMAND: python -c "import numcodecs" CIBW_BUILD: "cp311-* cp312-* cp313-*" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5728b2fb3..88ba122b5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,4 +30,4 @@ repos: hooks: - id: mypy args: [--config-file, pyproject.toml] - additional_dependencies: [numpy, pytest, crc32c, zfpy, 'zarr>=3.0.0rc1'] + additional_dependencies: [numpy, pytest, crc32c, zfpy, 'zarr>=3.0.0rc1,<3.1'] diff --git a/.readthedocs.yaml b/.readthedocs.yaml index fa14bf340..5e124a8fc 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,12 +4,12 @@ submodules: include: all build: - os: ubuntu-20.04 + os: ubuntu-24.04 tools: python: "3.12" jobs: post_install: - - python -m pip install --pre 'zarr>=3.0.0b2' + - python -m pip install --pre 'zarr~=3.0.0' sphinx: configuration: docs/conf.py diff --git a/numcodecs/tests/test_checksum32.py b/numcodecs/tests/test_checksum32.py index 9bdc25cb1..8af409454 100644 --- a/numcodecs/tests/test_checksum32.py +++ b/numcodecs/tests/test_checksum32.py @@ -54,12 +54,12 @@ ) -@pytest.mark.parametrize(("codec", "arr"), itertools.product(codecs, arrays)) +@pytest.mark.parametrize(("codec", "arr"), tuple(itertools.product(codecs, arrays))) def test_encode_decode(codec, arr): check_encode_decode(arr, codec) -@pytest.mark.parametrize(("codec", "arr"), itertools.product(codecs, arrays)) +@pytest.mark.parametrize(("codec", "arr"), tuple(itertools.product(codecs, arrays))) def test_errors(codec, arr): enc = codec.encode(arr) with pytest.raises(RuntimeError): diff --git a/numcodecs/tests/test_zarr3.py b/numcodecs/tests/test_zarr3.py index 0d8ecc74f..eaf8634e9 100644 --- a/numcodecs/tests/test_zarr3.py +++ b/numcodecs/tests/test_zarr3.py @@ -92,12 +92,14 @@ def test_generic_compressor( (numcodecs.zarr3.FixedScaleOffset, {"offset": 0, "scale": 25.5}), (numcodecs.zarr3.FixedScaleOffset, {"offset": 0, "scale": 51, "astype": "uint16"}), (numcodecs.zarr3.AsType, {"encode_dtype": "float32", "decode_dtype": "float32"}), + (numcodecs.zarr3.AsType, {"encode_dtype": "float32"}), ], ids=[ "delta", "fixedscaleoffset", "fixedscaleoffset2", "astype", + "astype_no_decode_dtype", ], ) def test_generic_filter( diff --git a/numcodecs/zarr3.py b/numcodecs/zarr3.py index f1743ffbc..43684c3dd 100644 --- a/numcodecs/zarr3.py +++ b/numcodecs/zarr3.py @@ -286,7 +286,7 @@ def __init__(self, **codec_config: dict[str, JSON]) -> None: def resolve_metadata(self, chunk_spec: ArraySpec) -> ArraySpec: if astype := self.codec_config.get("astype"): - return replace(chunk_spec, dtype=np.dtype(astype)) # type: ignore[arg-type] + return replace(chunk_spec, dtype=np.dtype(astype)) # type: ignore[call-overload] return chunk_spec @@ -304,7 +304,7 @@ def __init__(self, **codec_config: JSON) -> None: def resolve_metadata(self, chunk_spec: ArraySpec) -> ArraySpec: if astype := self.codec_config.get("astype"): - return replace(chunk_spec, dtype=np.dtype(astype)) # type: ignore[arg-type] + return replace(chunk_spec, dtype=np.dtype(astype)) # type: ignore[call-overload] return chunk_spec def evolve_from_array_spec(self, array_spec: ArraySpec) -> FixedScaleOffset: diff --git a/pyproject.toml b/pyproject.toml index 29ef0bf0d..af7efb93f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -117,6 +117,9 @@ write_to = "numcodecs/version.py" skip = "./.git,fixture" ignore-words-list = "ba, compiletime, hist, nd, unparseable" +[tool.coverage.run] +omit = ["numcodecs/tests/*"] + [tool.coverage.report] exclude_lines = [ "pragma: no cover", @@ -156,6 +159,10 @@ filterwarnings = [ [tool.cibuildwheel] environment = { DISABLE_NUMCODECS_AVX2=1 } +[tool.cibuildwheel.linux] +# Only install NumPy from wheels when building. Recent NumPy releases have no manylinux2014 +# wheels, and building them from source fails with the GCC in the manylinux2014 image. +environment = { DISABLE_NUMCODECS_AVX2=1, PIP_ONLY_BINARY="numpy" } [tool.cibuildwheel.macos] environment = { MACOSX_DEPLOYMENT_TARGET=10.9, DISABLE_NUMCODECS_AVX2=1, CFLAGS="$CFLAGS -Wno-implicit-function-declaration" } [[tool.cibuildwheel.overrides]]