From 9a84121df8b6408d0e2e24268149b3b7e1344f61 Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:12:48 -0400 Subject: [PATCH 1/8] Use pixi to simplify ci jobs --- .github/workflows/ci.yaml | 44 +++++++-------------------------------- pyproject.toml | 35 +++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4030e194..8e2630a6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,14 +12,10 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.11", "3.12", "3.13", "3.14"] + python-version: ["py311", "py312", "py313", "py314"] # 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: - shell: bash -el {0} - steps: - name: Checkout source uses: actions/checkout@v5 @@ -27,42 +23,18 @@ jobs: submodules: recursive fetch-depth: 0 # required for version resolution - - name: Set up Conda - uses: conda-incubator/setup-miniconda@v3.2.0 + - name: Set up Pixi + uses: prefix-dev/setup-pixi@v0.9.0 with: - channels: conda-forge - miniforge-version: latest - python-version: ${{ matrix.python-version }} - - - 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 - conda config --show-sources - conda list --show-channel-urls - - - 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 - python -m pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,zfpy] - else - python -m pip install -v -e .[test,test_extras,msgpack,google_crc32c,crc32c,pcodec,zfpy] - fi + pixi-version: v0.49.0 + cache: false + environments: test-${{ matrix.python-version }} - name: List installed packages - run: python -m pip list + run: pixi run -e test-${{ matrix.python-version }} uv pip list - name: Run tests - shell: "bash -l {0}" - run: pytest -v + run: pixi run -e test-${{ matrix.python-version }} run-tests - uses: codecov/codecov-action@v5 with: diff --git a/pyproject.toml b/pyproject.toml index a47600dc..d0f7bc29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -259,17 +259,29 @@ conflicts = [ [tool.pixi.workspace] channels = ["conda-forge"] -platforms = ["linux-64", "osx-arm64", "osx-64", "win-64"] +platforms = ["linux-64", "linux-aarch64", "osx-arm64", "osx-64", "win-64"] [tool.pixi.dependencies] -python = "=3.14" -clang = ">=19.1.7,<20" c-compiler = ">=1.9.0,<2" cxx-compiler = ">=1.9.0,<2" uv = "*" +# Python version features +[tool.pixi.feature.py311.dependencies] +python = "3.11.*" + +[tool.pixi.feature.py312.dependencies] +python = "3.12.*" + +[tool.pixi.feature.py313.dependencies] +python = "3.13.*" + +[tool.pixi.feature.py314.dependencies] +python = "3.14.*" + +# Test dependencies [tool.pixi.feature.test.pypi-dependencies] -numcodecs = { path = ".", editable = true, extras = ["test","test_extras","msgpack","zfpy"] } +numcodecs = { path = ".", editable = true, extras = ["test", "test_extras", "msgpack", "zfpy", "pcodec"] } [tool.pixi.feature.test-google-crc32c.pypi-dependencies] numcodecs = { path = ".", editable = true, extras = ["google_crc32c"] } @@ -277,16 +289,21 @@ numcodecs = { path = ".", editable = true, extras = ["google_crc32c"] } [tool.pixi.feature.test-crc32c.pypi-dependencies] numcodecs = { path = ".", editable = true, extras = ["crc32c"] } +# Environments [tool.pixi.environments] -default = { solve-group = "default" } -test = ["test"] -test-crc32c = ["test", "test-crc32c"] -test-google-crc32c = ["test", "test-google-crc32c"] +default = { features = ["py314"], solve-group = "py314" } +test-py311 = { features = ["test", "test-google-crc32c", "py311"], solve-group = "py311" } +test-py312 = { features = ["test", "test-google-crc32c", "py312"], solve-group = "py312" } +test-py313 = { features = ["test", "test-google-crc32c", "py313"], solve-group = "py313" } +test-py314 = { features = ["test", "test-google-crc32c", "py314"], solve-group = "py314" } +test-crc32c = { features = ["test", "test-crc32c", "py314"], solve-group = "py314-crc32c" } +test-google-crc32c = { features = ["test", "test-google-crc32c", "py314"], solve-group = "py314-google-crc32c" } +# Tasks [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" +ls-deps-main = "uv run --group test-zarr-main 'uv pip freeze'" test-zarr-312 = "uv run --group test-zarr-312 pytest --cov=numcodecs --cov-report=xml --cov-report=term numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" test-zarr-313 = "uv run --group test-zarr-313 pytest --cov=numcodecs --cov-report=xml --cov-report=term numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" test-zarr-main = "uv run --group test-zarr-main pytest --cov=numcodecs --cov-report=xml --cov-report=term numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" From f3474161294f09c2f03f1516535f0cfdadbff4b9 Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:50:28 -0400 Subject: [PATCH 2/8] Use pixi-build-python --- pyproject.toml | 60 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d0f7bc29..b0a14603 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,7 +102,6 @@ test-zarr-main = [ [tool.setuptools] package-dir = {"" = "."} packages = ["numcodecs", "numcodecs.tests"] -zip-safe = false [tool.setuptools.package-data] numcodecs = [ @@ -113,7 +112,7 @@ numcodecs = [ [tool.setuptools_scm] version_scheme = "guess-next-dev" local_scheme = "dirty-tag" -write_to = "numcodecs/version.py" +version_file = "numcodecs/version.py" [tool.codespell] skip = "./.git,fixture" @@ -132,7 +131,7 @@ exclude_lines = [ ignore = ["PY005", "PY007", "PP302", "PP308", "PP309", "GH103", "GH212", "PC111", "PC140", "PC160", "PC170", "PC180", "MY100", "RF103"] [tool.pytest.ini_options] -addopts = "-ra --strict-config --strict-markers --cov=numcodecs --cov-report xml --doctest-modules --doctest-glob=*.pyx" +addopts = "-ra --strict-config --strict-markers --cov=numcodecs --cov-report xml --doctest-modules" doctest_optionflags = [ "NORMALIZE_WHITESPACE", "ELLIPSIS", @@ -151,7 +150,7 @@ norecursedirs = [ "docs", "fixture", "notebooks", - "numcodecs.egg-info", + "*.egg-info", ] log_cli_level = "INFO" xfail_strict = true @@ -162,10 +161,10 @@ filterwarnings = [ [tool.cibuildwheel] environment = { DISABLE_NUMCODECS_AVX2=1 } + [tool.cibuildwheel.macos] -# cibuildwheel uses 3.12 for the Python driver, which supports High Sierra and later -# https://github.com/pypa/cibuildwheel/blob/ee63bf16da6cddfb925f542f2c7b59ad50e93969/action.yml#L31 environment = { MACOSX_DEPLOYMENT_TARGET=10.13, DISABLE_NUMCODECS_AVX2=1, CFLAGS="$CFLAGS -Wno-implicit-function-declaration" } + [[tool.cibuildwheel.overrides]] select = "*-macosx_arm64" environment = { DISABLE_NUMCODECS_AVX2=1, DISABLE_NUMCODECS_SSE2=1 } @@ -257,16 +256,38 @@ conflicts = [ ] ] +# Pixi source package — pixi-build-python builds numcodecs as a conda +# package, ensuring compilers are available at build time (fixes Windows CI). +# numcodecs is not listed as a path dependency in the per-version features +# below; [tool.pixi.package] causes pixi to build and install it automatically +# per solve-group, so explicit path deps would cause a double-resolution +# conflict (the ABI-tagged build from one solve leaking into another). +[tool.pixi.package] +version = "0.16.6.dev0" + +[tool.pixi.package.build] +backend = { name = "pixi-build-python", version = "0.4.*" } + +[tool.pixi.package.build.config] +compilers = ["c", "cxx"] +noarch = false + +[tool.pixi.package.host-dependencies] +setuptools = ">=77" +setuptools-scm = ">=6.2" +cython = "*" +numpy = ">2" + [tool.pixi.workspace] channels = ["conda-forge"] platforms = ["linux-64", "linux-aarch64", "osx-arm64", "osx-64", "win-64"] +preview = ["pixi-build"] [tool.pixi.dependencies] -c-compiler = ">=1.9.0,<2" -cxx-compiler = ">=1.9.0,<2" uv = "*" -# Python version features +# Python version features. numcodecs is intentionally not listed here — +# [tool.pixi.package] handles building and installing it per solve-group. [tool.pixi.feature.py311.dependencies] python = "3.11.*" @@ -277,17 +298,26 @@ python = "3.12.*" python = "3.13.*" [tool.pixi.feature.py314.dependencies] -python = "3.14.*" +python = ">=3.14.0,<3.15" -# Test dependencies +# Test dependencies (extras from [project.optional-dependencies] declared as +# separate pypi-dependencies since the source package has no extras concept). [tool.pixi.feature.test.pypi-dependencies] -numcodecs = { path = ".", editable = true, extras = ["test", "test_extras", "msgpack", "zfpy", "pcodec"] } +coverage = "*" +pytest = "*" +pytest-cov = "*" +pyzstd = "*" +importlib-metadata = "*" +crc32c = "*" +msgpack = "*" +zfpy = ">=1.0.0" +pcodec = ">=0.3,<0.4" [tool.pixi.feature.test-google-crc32c.pypi-dependencies] -numcodecs = { path = ".", editable = true, extras = ["google_crc32c"] } +google-crc32c = ">=1.5" [tool.pixi.feature.test-crc32c.pypi-dependencies] -numcodecs = { path = ".", editable = true, extras = ["crc32c"] } +crc32c = ">=2.7" # Environments [tool.pixi.environments] @@ -309,4 +339,4 @@ test-zarr-313 = "uv run --group test-zarr-313 pytest --cov=numcodecs --cov-repor test-zarr-main = "uv run --group test-zarr-main pytest --cov=numcodecs --cov-report=xml --cov-report=term numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" [tool.pixi.feature.test.tasks] -run-tests = "pytest -v" +run-tests = "pytest -v" \ No newline at end of file From 79ec0e0141841952298fae833e42df6179a7d925 Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:59:40 -0400 Subject: [PATCH 3/8] Update versions --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8e2630a6..87d276cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,9 +24,9 @@ jobs: fetch-depth: 0 # required for version resolution - name: Set up Pixi - uses: prefix-dev/setup-pixi@v0.9.0 + uses: prefix-dev/setup-pixi@v0.9.4 with: - pixi-version: v0.49.0 + pixi-version: v0.62.2 cache: false environments: test-${{ matrix.python-version }} @@ -61,9 +61,9 @@ jobs: fetch-depth: 0 # required for version resolution - name: Set up Pixi - uses: prefix-dev/setup-pixi@v0.9.0 + uses: prefix-dev/setup-pixi@v0.9.4 with: - pixi-version: v0.49.0 + pixi-version: v0.62.2 cache: false - name: List installed packages From 44f414d4efa1c0d3444eeb6ed9d4b9b01f69a5ef Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:01:49 -0400 Subject: [PATCH 4/8] Narrow changes --- pyproject.toml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b0a14603..308981a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,7 @@ test-zarr-main = [ [tool.setuptools] package-dir = {"" = "."} packages = ["numcodecs", "numcodecs.tests"] +zip-safe = false [tool.setuptools.package-data] numcodecs = [ @@ -112,7 +113,7 @@ numcodecs = [ [tool.setuptools_scm] version_scheme = "guess-next-dev" local_scheme = "dirty-tag" -version_file = "numcodecs/version.py" +write_to = "numcodecs/version.py" [tool.codespell] skip = "./.git,fixture" @@ -131,7 +132,7 @@ exclude_lines = [ ignore = ["PY005", "PY007", "PP302", "PP308", "PP309", "GH103", "GH212", "PC111", "PC140", "PC160", "PC170", "PC180", "MY100", "RF103"] [tool.pytest.ini_options] -addopts = "-ra --strict-config --strict-markers --cov=numcodecs --cov-report xml --doctest-modules" +addopts = "-ra --strict-config --strict-markers --cov=numcodecs --cov-report xml --doctest-modules --doctest-glob=*.pyx" doctest_optionflags = [ "NORMALIZE_WHITESPACE", "ELLIPSIS", @@ -150,7 +151,7 @@ norecursedirs = [ "docs", "fixture", "notebooks", - "*.egg-info", + "numcodecs.egg-info", ] log_cli_level = "INFO" xfail_strict = true @@ -163,6 +164,8 @@ filterwarnings = [ environment = { DISABLE_NUMCODECS_AVX2=1 } [tool.cibuildwheel.macos] +# cibuildwheel uses 3.12 for the Python driver, which supports High Sierra and later +# https://github.com/pypa/cibuildwheel/blob/ee63bf16da6cddfb925f542f2c7b59ad50e93969/action.yml#L31 environment = { MACOSX_DEPLOYMENT_TARGET=10.13, DISABLE_NUMCODECS_AVX2=1, CFLAGS="$CFLAGS -Wno-implicit-function-declaration" } [[tool.cibuildwheel.overrides]] From 796716d751017966de51282776749ce2b224944b Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:08:55 -0400 Subject: [PATCH 5/8] Fallback version --- numcodecs/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/numcodecs/__init__.py b/numcodecs/__init__.py index e3626b1b..5c9e3467 100644 --- a/numcodecs/__init__.py +++ b/numcodecs/__init__.py @@ -23,7 +23,13 @@ from numcodecs.registry import get_codec as get_codec from numcodecs.registry import register_codec -from numcodecs.version import version as __version__ # noqa: F401 + +try: + from numcodecs.version import version as __version__ +except ImportError: + from importlib.metadata import version as _get_version + + __version__ = _get_version("numcodecs") from numcodecs.zlib import Zlib register_codec(Zlib) From a8e0e76bfd7ced5c7717ad4e17c4ac0b97a28fbf Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:20:13 -0400 Subject: [PATCH 6/8] Revert "Fallback version" This reverts commit 796716d751017966de51282776749ce2b224944b. --- numcodecs/__init__.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/numcodecs/__init__.py b/numcodecs/__init__.py index 5c9e3467..e3626b1b 100644 --- a/numcodecs/__init__.py +++ b/numcodecs/__init__.py @@ -23,13 +23,7 @@ from numcodecs.registry import get_codec as get_codec from numcodecs.registry import register_codec - -try: - from numcodecs.version import version as __version__ -except ImportError: - from importlib.metadata import version as _get_version - - __version__ = _get_version("numcodecs") +from numcodecs.version import version as __version__ # noqa: F401 from numcodecs.zlib import Zlib register_codec(Zlib) From a3eba225ad5ce7e21ba5fcde19d2532df9fd7436 Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:20:29 -0400 Subject: [PATCH 7/8] Add import mode --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 308981a2..a588f79b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -132,6 +132,7 @@ exclude_lines = [ ignore = ["PY005", "PY007", "PP302", "PP308", "PP309", "GH103", "GH212", "PC111", "PC140", "PC160", "PC170", "PC180", "MY100", "RF103"] [tool.pytest.ini_options] +import_mode = "importlib" addopts = "-ra --strict-config --strict-markers --cov=numcodecs --cov-report xml --doctest-modules --doctest-glob=*.pyx" doctest_optionflags = [ "NORMALIZE_WHITESPACE", From 857feb87a40b0d48e3fae92966781c729381db53 Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:40:37 -0400 Subject: [PATCH 8/8] Revert --- pyproject.toml | 52 +++++++++----------------------------------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a588f79b..d0f7bc29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -132,7 +132,6 @@ exclude_lines = [ ignore = ["PY005", "PY007", "PP302", "PP308", "PP309", "GH103", "GH212", "PC111", "PC140", "PC160", "PC170", "PC180", "MY100", "RF103"] [tool.pytest.ini_options] -import_mode = "importlib" addopts = "-ra --strict-config --strict-markers --cov=numcodecs --cov-report xml --doctest-modules --doctest-glob=*.pyx" doctest_optionflags = [ "NORMALIZE_WHITESPACE", @@ -163,12 +162,10 @@ filterwarnings = [ [tool.cibuildwheel] environment = { DISABLE_NUMCODECS_AVX2=1 } - [tool.cibuildwheel.macos] # cibuildwheel uses 3.12 for the Python driver, which supports High Sierra and later # https://github.com/pypa/cibuildwheel/blob/ee63bf16da6cddfb925f542f2c7b59ad50e93969/action.yml#L31 environment = { MACOSX_DEPLOYMENT_TARGET=10.13, DISABLE_NUMCODECS_AVX2=1, CFLAGS="$CFLAGS -Wno-implicit-function-declaration" } - [[tool.cibuildwheel.overrides]] select = "*-macosx_arm64" environment = { DISABLE_NUMCODECS_AVX2=1, DISABLE_NUMCODECS_SSE2=1 } @@ -260,38 +257,16 @@ conflicts = [ ] ] -# Pixi source package — pixi-build-python builds numcodecs as a conda -# package, ensuring compilers are available at build time (fixes Windows CI). -# numcodecs is not listed as a path dependency in the per-version features -# below; [tool.pixi.package] causes pixi to build and install it automatically -# per solve-group, so explicit path deps would cause a double-resolution -# conflict (the ABI-tagged build from one solve leaking into another). -[tool.pixi.package] -version = "0.16.6.dev0" - -[tool.pixi.package.build] -backend = { name = "pixi-build-python", version = "0.4.*" } - -[tool.pixi.package.build.config] -compilers = ["c", "cxx"] -noarch = false - -[tool.pixi.package.host-dependencies] -setuptools = ">=77" -setuptools-scm = ">=6.2" -cython = "*" -numpy = ">2" - [tool.pixi.workspace] channels = ["conda-forge"] platforms = ["linux-64", "linux-aarch64", "osx-arm64", "osx-64", "win-64"] -preview = ["pixi-build"] [tool.pixi.dependencies] +c-compiler = ">=1.9.0,<2" +cxx-compiler = ">=1.9.0,<2" uv = "*" -# Python version features. numcodecs is intentionally not listed here — -# [tool.pixi.package] handles building and installing it per solve-group. +# Python version features [tool.pixi.feature.py311.dependencies] python = "3.11.*" @@ -302,26 +277,17 @@ python = "3.12.*" python = "3.13.*" [tool.pixi.feature.py314.dependencies] -python = ">=3.14.0,<3.15" +python = "3.14.*" -# Test dependencies (extras from [project.optional-dependencies] declared as -# separate pypi-dependencies since the source package has no extras concept). +# Test dependencies [tool.pixi.feature.test.pypi-dependencies] -coverage = "*" -pytest = "*" -pytest-cov = "*" -pyzstd = "*" -importlib-metadata = "*" -crc32c = "*" -msgpack = "*" -zfpy = ">=1.0.0" -pcodec = ">=0.3,<0.4" +numcodecs = { path = ".", editable = true, extras = ["test", "test_extras", "msgpack", "zfpy", "pcodec"] } [tool.pixi.feature.test-google-crc32c.pypi-dependencies] -google-crc32c = ">=1.5" +numcodecs = { path = ".", editable = true, extras = ["google_crc32c"] } [tool.pixi.feature.test-crc32c.pypi-dependencies] -crc32c = ">=2.7" +numcodecs = { path = ".", editable = true, extras = ["crc32c"] } # Environments [tool.pixi.environments] @@ -343,4 +309,4 @@ test-zarr-313 = "uv run --group test-zarr-313 pytest --cov=numcodecs --cov-repor test-zarr-main = "uv run --group test-zarr-main pytest --cov=numcodecs --cov-report=xml --cov-report=term numcodecs/tests/test_zarr3.py numcodecs/tests/test_zarr3_import.py" [tool.pixi.feature.test.tasks] -run-tests = "pytest -v" \ No newline at end of file +run-tests = "pytest -v"