diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53ae996..3c40e61 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.20 + rev: v0.15.21 hooks: - id: ruff-check args: [--fix, --exit-non-zero-on-fix] @@ -14,15 +14,15 @@ repos: args: [--preview, --select=CPY] - id: ruff-format - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.25.1 + rev: v2.25.2 hooks: - id: pyproject-fmt - repo: https://github.com/biomejs/pre-commit - rev: v2.5.2 + rev: v2.5.3 hooks: - id: biome-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v2.1.0 + rev: v2.3.0 hooks: - id: mypy args: [--config-file=pyproject.toml, .] diff --git a/src/fast_array_utils/conv/_to_dense.py b/src/fast_array_utils/conv/_to_dense.py index 66d1580..07c8b08 100644 --- a/src/fast_array_utils/conv/_to_dense.py +++ b/src/fast_array_utils/conv/_to_dense.py @@ -21,7 +21,7 @@ # fallback’s arg0 type has to include types of registered functions @singledispatch def to_dense_( - x: CpuArray | GpuArray | DiskArray | types.DaskArray | types.sparray | types.spmatrix | types.CupySpMatrix | types.HasArrayNamespace, + x: CpuArray | GpuArray | DiskArray | types.CSDataset | types.DaskArray | types.sparray | types.spmatrix | types.CupySpMatrix | types.HasArrayNamespace, /, *, order: Literal["K", "A", "C", "F"] = "K", @@ -64,8 +64,7 @@ def _to_dense_ooc(x: types.CSDataset, /, *, order: Literal["K", "A", "C", "F"] = if not to_cpu_memory: msg = "to_cpu_memory must be True if x is an CS{R,C}Dataset" raise ValueError(msg) - # TODO(flying-sheep): why is to_memory of type Any? # noqa: TD003 - return to_dense(cast("types.CSBase", x.to_memory()), order=sparse_order(x, order=order)) + return to_dense(x.to_memory(), order=sparse_order(x, order=order)) @to_dense_.register(types.CupyArray | types.CupySpMatrix) diff --git a/src/fast_array_utils/stats/_power.py b/src/fast_array_utils/stats/_power.py index 1d6634c..429018e 100644 --- a/src/fast_array_utils/stats/_power.py +++ b/src/fast_array_utils/stats/_power.py @@ -2,7 +2,7 @@ from __future__ import annotations from functools import singledispatch -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast import numpy as np @@ -47,10 +47,10 @@ def _power_array_api[A: AArray[object, object]](x: A, n: int, /, dtype: DTypeLik @_power.register(types.CSBase | types.CupyCSMatrix) def _power_cs[Mat: types.CSBase | types.CupyCSMatrix](x: Mat, n: int, /, dtype: DTypeLike | None = None) -> Mat: new_data = power(x.data, n, dtype=dtype) - return type(x)((new_data, x.indices, x.indptr), shape=x.shape, dtype=new_data.dtype) # type: ignore[call-overload,return-value] + return type(x)((new_data, x.indices, x.indptr), shape=x.shape, dtype=new_data.dtype) # type: ignore[call-overload] @_power.register(types.DaskArray) def _power_dask(x: types.DaskArray, n: int, /, dtype: DTypeLike | None = None) -> types.DaskArray: - meta = x._meta.astype(dtype or x.dtype) # noqa: SLF001 - return x.map_blocks(lambda c: power(c, n, dtype=dtype), dtype=dtype, meta=meta) # type: ignore[type-var,arg-type] + meta = cast("CpuArray | GpuArray", x._meta.astype(dtype or x.dtype)) # noqa: SLF001 # https://github.com/python/mypy/issues/16826 + return x.map_blocks(lambda c: power(c, n, dtype=dtype), dtype=dtype, meta=meta) diff --git a/src/fast_array_utils/stats/_utils.py b/src/fast_array_utils/stats/_utils.py index fe062c2..f468508 100644 --- a/src/fast_array_utils/stats/_utils.py +++ b/src/fast_array_utils/stats/_utils.py @@ -54,7 +54,7 @@ def to_scalar(a: types.CupyArray | NDArray[Any]) -> np.number[Any]: a = a.get() return a.reshape(())[()] # type: ignore[return-value] - return rv.map_blocks(to_scalar, meta=x.dtype.type(0)) # type: ignore[arg-type] + return rv.map_blocks(to_scalar, meta=x.dtype.type(0)) def _dask_block( diff --git a/src/fast_array_utils/types.py b/src/fast_array_utils/types.py index 8da8972..6042540 100644 --- a/src/fast_array_utils/types.py +++ b/src/fast_array_utils/types.py @@ -111,7 +111,7 @@ if TYPE_CHECKING: - from anndata.abc import CSCDataset, CSRDataset # type: ignore[import-untyped] + from anndata.abc import CSCDataset, CSRDataset else: # pragma: no cover try: # only exists in anndata 0.11+ from anndata.abc import CSCDataset, CSRDataset diff --git a/src/testing/fast_array_utils/_array_type.py b/src/testing/fast_array_utils/_array_type.py index 44ef641..74bd09c 100644 --- a/src/testing/fast_array_utils/_array_type.py +++ b/src/testing/fast_array_utils/_array_type.py @@ -146,7 +146,7 @@ def cls(self) -> type[Arr]: # noqa: PLR0911 return cast("type[Arr]", zarr.Array) case "anndata.abc", ("CSCDataset" | "CSRDataset") as cls_name, _: - import anndata.abc # type: ignore[import-untyped] + import anndata.abc return cast("type[Arr]", getattr(anndata.abc, cls_name)) case _: @@ -188,13 +188,7 @@ def random( import dask.array as da arr = da.zeros(shape, dtype=dtype, chunks=_half_chunk_size(shape)) - return cast( - "Arr", - arr.map_blocks( - lambda x: self.random(x.shape, dtype=x.dtype, gen=gen, density=density), # type: ignore[attr-defined] - dtype=dtype, - ), - ) + return cast("Arr", arr.map_blocks(lambda x: self.random(x.shape, dtype=x.dtype, gen=gen, density=density), dtype=dtype)) case "h5py", "Dataset", _: raise NotImplementedError case "zarr", "Array", _: @@ -235,7 +229,7 @@ def __call__(self, x: ArrayLike | Array, /, *, dtype: DTypeLike | None = None) - @staticmethod def _to_numpy_array(x: ArrayLike | Array, /, *, dtype: DTypeLike | None = None) -> NDArray[np.number[Any]]: """Convert to a numpy array.""" - x = to_dense(x, to_cpu_memory=True) + x = to_dense(x, to_cpu_memory=True) # type: ignore[arg-type] # doesn’t officially handle ArrayLike return x if dtype is None else x.astype(dtype) def _to_dask_array(self, x: ArrayLike | Array, /, *, dtype: DTypeLike | None = None) -> types.DaskArray: @@ -277,7 +271,7 @@ def _to_zarr_array(cls, x: ArrayLike | Array, /, *, dtype: DTypeLike | None = No def _to_cs_dataset(self, x: ArrayLike | Array, /, *, dtype: DTypeLike | None = None) -> types.CSDataset: """Convert to a scipy sparse dataset.""" - import anndata.io # type: ignore[import-untyped] + import anndata.io from scipy.sparse import csc_array, csr_array assert self.inner is not None @@ -298,7 +292,7 @@ def _to_cs_dataset(self, x: ArrayLike | Array, /, *, dtype: DTypeLike | None = N cls = cast("type[types.csr_array[Any, tuple[int, int]] | types.csc_array]", csr_array if self.cls is types.CSRDataset else csc_array) x_sparse = self._to_scipy_sparse(x, dtype=dtype, cls=cls) anndata.io.write_elem(grp, "/mtx", x_sparse) - return anndata.io.sparse_dataset(grp["mtx"]) + return anndata.io.sparse_dataset(cast("types.H5Group | types.ZarrGroup", grp["mtx"])) def _to_scipy_sparse( self, @@ -314,7 +308,7 @@ def _to_scipy_sparse( if isinstance(x, types.CupySpMatrix): x = x.get() # can be a coo_matrix due to dask concatenation elif not isinstance(x, types.spmatrix | types.sparray | np.ndarray): - x = to_dense(x, to_cpu_memory=True) + x = to_dense(x, to_cpu_memory=True) # type: ignore[arg-type] # doesn’t officially handle ArrayLike cls = cast("type[types.CSBase]", cls or self.cls) return cls(x, dtype=dtype) # type: ignore[arg-type,misc] diff --git a/tests/test_jax.py b/tests/test_jax.py index 5cb4fc7..ea3ead1 100644 --- a/tests/test_jax.py +++ b/tests/test_jax.py @@ -98,7 +98,7 @@ def test_mean_var(subtests: pytest.Subtests, jax_arr: jax.Array, axis: Literal[0 def test_to_dense(*, jax_arr: jax.Array, to_cpu_memory: bool) -> None: import jax.numpy as jnp - result = to_dense(jax_arr, to_cpu_memory=to_cpu_memory) + result = to_dense(jax_arr, to_cpu_memory=to_cpu_memory) # type: ignore[call-overload] # https://github.com/python/mypy/issues/16777 if to_cpu_memory: assert isinstance(result, np.ndarray) diff --git a/tests/test_stats.py b/tests/test_stats.py index 8371250..dd42da6 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -155,7 +155,7 @@ def test_ndim_error( arr = array_type(np_arr) with pytest.raises(AxisError): - func(arr, axis=axis) + func(arr, axis=axis) # type: ignore[arg-type] # https://github.com/python/mypy/issues/16777 @pytest.mark.array_type(skip=ATS_SPARSE_DS) diff --git a/tests/test_to_dense.py b/tests/test_to_dense.py index 1d75969..3abd04d 100644 --- a/tests/test_to_dense.py +++ b/tests/test_to_dense.py @@ -41,7 +41,7 @@ def test_to_dense(array_type: ArrayType[Array], *, order: Literal["K", "C", "F"] else nullcontext(), WARNS_NUMBA if issubclass(array_type.cls, types.CSBase) and not find_spec("numba") else nullcontext(), ): - arr = to_dense(x, order=order, to_cpu_memory=to_cpu_memory) + arr = to_dense(x, order=order, to_cpu_memory=to_cpu_memory) # type: ignore[arg-type] # https://github.com/python/mypy/issues/16777 assert_expected_cls(x, arr, to_cpu_memory=to_cpu_memory) assert arr.shape == (2, 3) @@ -56,7 +56,7 @@ def test_to_dense_extra(coo_matrix_type: ArrayType[types.COOBase | types.CupyCOO src_mtx = coo_matrix_type([[1, 2, 3], [4, 5, 6]], dtype=np.float32) with WARNS_NUMBA if not find_spec("numba") else nullcontext(): - arr = to_dense(src_mtx, order=order, to_cpu_memory=to_cpu_memory) + arr = to_dense(src_mtx, order=order, to_cpu_memory=to_cpu_memory) # type: ignore[arg-type] # https://github.com/python/mypy/issues/16777 assert_expected_cls(src_mtx, arr, to_cpu_memory=to_cpu_memory) assert arr.shape == (2, 3) diff --git a/typings/dask/array/core.pyi b/typings/dask/array/core.pyi index 7f65dd2..0a19cc0 100644 --- a/typings/dask/array/core.pyi +++ b/typings/dask/array/core.pyi @@ -63,7 +63,7 @@ class Array: def map_blocks( self, # TODO(flying-sheep): make this generic, _Array the default # noqa: TD003 - func: Callable[[object], object], + func: Callable[..., object], *args: Never, name: str | None = None, token: str | None = None, @@ -89,7 +89,7 @@ def from_array( ) -> Array: ... def map_blocks( # TODO(flying-sheep): make this generic, _Array the default # noqa: TD003 - func: Callable[[object], object], + func: Callable[..., object], *args: Array, name: str | None = None, token: str | None = None,