diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9cb4c86..79ba013 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v6 with: { fetch-depth: 0, filter: "blob:none" } - - uses: astral-sh/setup-uv@v7 + - uses: astral-sh/setup-uv@v8.2.0 - name: Get test environments id: get-envs run: | @@ -39,6 +39,8 @@ jobs: test: name: Tests needs: get-environments + permissions: + id-token: write # for codecov OIDC runs-on: ${{ matrix.os }} strategy: matrix: @@ -52,7 +54,7 @@ jobs: steps: - uses: actions/checkout@v6 with: { fetch-depth: 0, filter: "blob:none" } - - uses: astral-sh/setup-uv@v7 + - uses: astral-sh/setup-uv@v8.2.0 with: python-version: ${{ matrix.env.python }} - name: create environment @@ -63,14 +65,16 @@ jobs: # https://github.com/codecov/codecov-cli/issues/648 uvx hatch run ${{ matrix.env.name }}:coverage xml rm test-data/.coverage - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@v7 with: name: ${{ matrix.env.name }} fail_ci_if_error: true files: test-data/coverage.xml - token: ${{ secrets.CODECOV_TOKEN }} + use_oidc: true bench: name: CPU Benchmarks + permissions: + id-token: write # for codspeed OIDC runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 @@ -78,12 +82,12 @@ jobs: - uses: actions/setup-python@v6 with: python-version: '3.14' - - uses: astral-sh/setup-uv@v7 + - uses: astral-sh/setup-uv@v8.2.0 - run: uv pip install --system --group=test -e .[full] - - uses: CodSpeedHQ/action@v3 + - uses: CodSpeedHQ/action@v4 with: + mode: simulation run: pytest -m benchmark --codspeed -n auto - token: ${{ secrets.CODSPEED_TOKEN }} import: name: Import Tests runs-on: ubuntu-latest @@ -93,7 +97,7 @@ jobs: - uses: actions/setup-python@v6 with: python-version: '3.14' - - uses: astral-sh/setup-uv@v7 + - uses: astral-sh/setup-uv@v8.2.0 - run: uv pip install --system -e . - run: python -c 'import fast_array_utils as fau; print(fau.__all__)' - run: uv pip install --system -e .[testing] @@ -106,9 +110,7 @@ jobs: steps: - uses: actions/checkout@v6 with: { fetch-depth: 0, filter: "blob:none" } - - uses: j178/prek-action@v1 - with: - working-directory: ${{ github.workspace }} + - uses: j178/prek-action@v2 pass: name: All Checks if: always() diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32cf75d..fbb6241 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: trailing-whitespace - id: no-commit-to-branch - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.15 + rev: v0.15.16 hooks: - id: ruff-check args: [--fix, --exit-non-zero-on-fix] @@ -29,7 +29,7 @@ repos: pass_filenames: false additional_dependencies: - anndata>=0.12 - - array-api-compat>=1.13 + - array-api-compat>=1.13,!=1.15.0 # https://github.com/data-apis/array-api-compat/issues/436 - dask>=2026.1 - h5py>=3.15 - jax>=0.10 @@ -40,6 +40,7 @@ repos: - scikit-learn>=1.8 - scipy-stubs>=1.17 - sphinx>=9 + - types-array-api>=1.3 - types-docutils>=0.22 - zarr>=3.1 ci: diff --git a/.vscode/settings.json b/.vscode/settings.json index a4a891c..f1e4981 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,6 +17,6 @@ }, "python.testing.pytestArgs": ["-vv", "--color=yes", "-m", "not benchmark"], "python.testing.pytestEnabled": true, - "python-envs.defaultEnvManager": "flying-sheep.hatch:hatch", - "python-envs.defaultPackageManager": "flying-sheep.hatch:hatch", + "python-envs.defaultEnvManager": "pypa.hatch:hatch", + "python-envs.defaultPackageManager": "pypa.hatch:hatch", } diff --git a/pyproject.toml b/pyproject.toml index 0c4ebc7..ad5d18d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,12 +35,14 @@ urls.Documentation = "https://icb-fast-array-utils.readthedocs-hosted.com/" entry-points.pytest11.fast_array_utils = "testing.fast_array_utils.pytest" [dependency-groups] +dev = [ "types-array-api", "types-docutils" ] test = [ "anndata", "fast-array-utils[full]", "jax", "jaxlib", "scikit-learn", + { include-group = "dev" }, { include-group = "test-min" }, ] doc = [ diff --git a/src/fast_array_utils/stats/_generic_ops.py b/src/fast_array_utils/stats/_generic_ops.py index dd8a07b..5d260a9 100644 --- a/src/fast_array_utils/stats/_generic_ops.py +++ b/src/fast_array_utils/stats/_generic_ops.py @@ -14,6 +14,7 @@ if TYPE_CHECKING: from typing import Any, Literal + from array_api.latest import Array as AArray from numpy.typing import DTypeLike, NDArray from ..typing import CpuArray, DiskArray, GpuArray @@ -111,7 +112,7 @@ def _generic_op_dask( @generic_op.register(types.HasArrayNamespace) -def _generic_op_array_api[A: types.HasArrayNamespace]( +def _generic_op_array_api[A: AArray[object, object]]( x: A, /, op: Ops, diff --git a/src/fast_array_utils/stats/_power.py b/src/fast_array_utils/stats/_power.py index 82653a9..1d6634c 100644 --- a/src/fast_array_utils/stats/_power.py +++ b/src/fast_array_utils/stats/_power.py @@ -10,6 +10,7 @@ if TYPE_CHECKING: + from array_api.latest import Array as AArray from numpy.typing import DTypeLike from fast_array_utils.typing import CpuArray, GpuArray @@ -36,11 +37,11 @@ def _power_numpy_cupy(x: np.ndarray, n: int, /, dtype: DTypeLike | None = None) @_power.register(types.HasArrayNamespace) -def _power_array_api(x: types.HasArrayNamespace, n: int, /, dtype: DTypeLike | None = None) -> types.HasArrayNamespace: +def _power_array_api[A: AArray[object, object]](x: A, n: int, /, dtype: DTypeLike | None = None) -> A: import array_api_compat xp = array_api_compat.array_namespace(x) - return xp.pow(x, n) if dtype is None else xp.pow(xp.astype(x, dtype), n) # type: ignore[no-any-return] + return xp.pow(x, n) if dtype is None else xp.pow(xp.astype(x, dtype), n) @_power.register(types.CSBase | types.CupyCSMatrix)