From e6ff286bd2fff612ebd034691423a0599c1a3a57 Mon Sep 17 00:00:00 2001 From: Phil Schaf Date: Sat, 13 Sep 2025 14:13:23 +0200 Subject: [PATCH 1/5] remove numpy 1 support --- .pre-commit-config.yaml | 2 +- docs/conf.py | 2 -- pyproject.toml | 3 +-- src/fast_array_utils/stats/__init__.py | 24 ++++++++++---------- src/fast_array_utils/stats/_is_constant.py | 20 ++++++++--------- src/fast_array_utils/stats/_mean.py | 7 +++--- src/fast_array_utils/stats/_mean_var.py | 2 +- src/fast_array_utils/stats/_sum.py | 14 ++++++------ tests/test_stats.py | 26 +++++++++++----------- tests/test_to_dense.py | 2 +- typings/cupy/_core/core.pyi | 2 +- typings/cupy/_creation/from_data.pyi | 2 +- typings/cupyx/scipy/sparse/_base.pyi | 2 +- typings/dask/array/core.pyi | 2 +- 14 files changed, 53 insertions(+), 57 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4f34a50..30a89d9 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.12.12 + rev: v0.13.0 hooks: - id: ruff-check args: [--fix, --exit-non-zero-on-fix] diff --git a/docs/conf.py b/docs/conf.py index 56f888b..32f21a4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -85,7 +85,6 @@ source_directory="docs/", ) -_np_aliases = {"bool_": "bool"} _np_nocls = {"float64": "attr"} _optional_types = { "CupyArray": "cupy.ndarray", @@ -111,7 +110,6 @@ def find_type_alias(name: str) -> tuple[str, str, str | None] | tuple[None, None return "class", path, None return "data", f"fast_array_utils.{name}", None if name.startswith("np."): - name = _np_aliases.get(name[3:], name[3:]) return _np_nocls.get(name, "class"), f"numpy.{name}", f"np.{name}" if name in npt.__all__: return "data", f"numpy.typing.{name}", None diff --git a/pyproject.toml b/pyproject.toml index 340c395..e4e4060 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ "Programming Language :: Python :: 3.13", ] dynamic = [ "description", "readme", "version" ] -dependencies = [ "numpy>=1.25.2" ] +dependencies = [ "numpy>=2" ] optional-dependencies.accel = [ "numba>=0.57" ] optional-dependencies.doc = [ "furo>=2024.8.6", @@ -144,7 +144,6 @@ lint.per-file-ignores."typings/**/*.pyi" = [ "A002", "F403", "F405", "N801" ] # lint.allowed-confusables = [ "×", "’" ] lint.flake8-bugbear.extend-immutable-calls = [ "testing.fast_array_utils.Flags" ] lint.flake8-copyright.notice-rgx = "SPDX-License-Identifier: MPL-2\\.0" -lint.flake8-tidy-imports.banned-api."numpy.bool".msg = "Use `np.bool_` instead for numpy>=1.24<2 compatibility" lint.flake8-type-checking.exempt-modules = [ ] lint.flake8-type-checking.strict = true lint.isort.known-first-party = [ "fast_array_utils" ] diff --git a/src/fast_array_utils/stats/__init__.py b/src/fast_array_utils/stats/__init__.py index 60dcae6..a4aaa29 100644 --- a/src/fast_array_utils/stats/__init__.py +++ b/src/fast_array_utils/stats/__init__.py @@ -29,19 +29,19 @@ @overload def is_constant(x: NDArray[Any] | types.CSBase | types.CupyArray, /, *, axis: None = None) -> bool: ... @overload -def is_constant(x: NDArray[Any] | types.CSBase, /, *, axis: Literal[0, 1]) -> NDArray[np.bool_]: ... +def is_constant(x: NDArray[Any] | types.CSBase, /, *, axis: Literal[0, 1]) -> NDArray[np.bool]: ... @overload def is_constant(x: types.CupyArray, /, *, axis: Literal[0, 1]) -> types.CupyArray: ... @overload -def is_constant(x: types.DaskArray, /, *, axis: Literal[0, 1, None] = None) -> types.DaskArray: ... +def is_constant(x: types.DaskArray, /, *, axis: Literal[0, 1] | None = None) -> types.DaskArray: ... def is_constant( x: NDArray[Any] | types.CSBase | types.CupyArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, -) -> bool | NDArray[np.bool_] | types.CupyArray | types.DaskArray: + axis: Literal[0, 1] | None = None, +) -> bool | NDArray[np.bool] | types.CupyArray | types.DaskArray: """Check whether values in array are constant. Parameters @@ -80,7 +80,7 @@ def is_constant( # TODO(flying-sheep): support CSDataset (TODO) # https://github.com/scverse/fast-array-utils/issues/52 @overload -def mean(x: CpuArray | GpuArray | DiskArray, /, *, axis: Literal[None] = None, dtype: DTypeLike | None = None) -> np.number[Any]: ... +def mean(x: CpuArray | GpuArray | DiskArray, /, *, axis: None = None, dtype: DTypeLike | None = None) -> np.number[Any]: ... @overload def mean(x: CpuArray | DiskArray, /, *, axis: Literal[0, 1], dtype: DTypeLike | None = None) -> NDArray[np.number[Any]]: ... @overload @@ -93,7 +93,7 @@ def mean( x: CpuArray | GpuArray | DiskArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, ) -> NDArray[np.number[Any]] | types.CupyArray | np.number[Any] | types.DaskArray: """Mean over both or one axis. @@ -131,24 +131,24 @@ def mean( from ._mean import mean_ validate_axis(x.ndim, axis) - return mean_(x, axis=axis, dtype=dtype) # type: ignore[no-any-return] # literally the same type, wtf mypy + return mean_(x, axis=axis, dtype=dtype) @overload -def mean_var(x: CpuArray | GpuArray, /, *, axis: Literal[None] = None, correction: int = 0) -> tuple[np.float64, np.float64]: ... +def mean_var(x: CpuArray | GpuArray, /, *, axis: None = None, correction: int = 0) -> tuple[np.float64, np.float64]: ... @overload def mean_var(x: CpuArray, /, *, axis: Literal[0, 1], correction: int = 0) -> tuple[NDArray[np.float64], NDArray[np.float64]]: ... @overload def mean_var(x: GpuArray, /, *, axis: Literal[0, 1], correction: int = 0) -> tuple[types.CupyArray, types.CupyArray]: ... @overload -def mean_var(x: types.DaskArray, /, *, axis: Literal[0, 1, None] = None, correction: int = 0) -> tuple[types.DaskArray, types.DaskArray]: ... +def mean_var(x: types.DaskArray, /, *, axis: Literal[0, 1] | None = None, correction: int = 0) -> tuple[types.DaskArray, types.DaskArray]: ... def mean_var( x: CpuArray | GpuArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, correction: int = 0, ) -> ( tuple[np.float64, np.float64] @@ -218,14 +218,14 @@ def sum(x: GpuArray, /, *, axis: Literal[0, 1], dtype: DTypeLike | None = None, @overload -def sum(x: types.DaskArray, /, *, axis: Literal[0, 1, None] = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False) -> types.DaskArray: ... +def sum(x: types.DaskArray, /, *, axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False) -> types.DaskArray: ... def sum( x: CpuArray | GpuArray | DiskArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False, ) -> NDArray[Any] | types.CupyArray | np.number[Any] | types.DaskArray: diff --git a/src/fast_array_utils/stats/_is_constant.py b/src/fast_array_utils/stats/_is_constant.py index 51f5c98..ed64151 100644 --- a/src/fast_array_utils/stats/_is_constant.py +++ b/src/fast_array_utils/stats/_is_constant.py @@ -24,13 +24,13 @@ def is_constant_( a: NDArray[Any] | types.CSBase | types.CupyArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, -) -> bool | NDArray[np.bool_] | types.CupyArray | types.DaskArray: # pragma: no cover + axis: Literal[0, 1] | None = None, +) -> bool | NDArray[np.bool] | types.CupyArray | types.DaskArray: # pragma: no cover raise NotImplementedError @is_constant_.register(np.ndarray | types.CupyArray) -def _is_constant_ndarray(a: NDArray[Any] | types.CupyArray, /, *, axis: Literal[0, 1, None] = None) -> bool | NDArray[np.bool_] | types.CupyArray: +def _is_constant_ndarray(a: NDArray[Any] | types.CupyArray, /, *, axis: Literal[0, 1] | None = None) -> bool | NDArray[np.bool] | types.CupyArray: # Should eventually support nd, not now. match axis: case None: @@ -41,13 +41,13 @@ def _is_constant_ndarray(a: NDArray[Any] | types.CupyArray, /, *, axis: Literal[ return _is_constant_rows(a) -def _is_constant_rows(a: NDArray[Any] | types.CupyArray) -> NDArray[np.bool_] | types.CupyArray: +def _is_constant_rows(a: NDArray[Any] | types.CupyArray) -> NDArray[np.bool] | types.CupyArray: b = np.broadcast_to(a[:, 0][:, np.newaxis], a.shape) - return cast("NDArray[np.bool_]", (a == b).all(axis=1)) + return cast("NDArray[np.bool]", (a == b).all(axis=1)) @is_constant_.register(types.CSBase) -def _is_constant_cs(a: types.CSBase, /, *, axis: Literal[0, 1, None] = None) -> bool | NDArray[np.bool_]: +def _is_constant_cs(a: types.CSBase, /, *, axis: Literal[0, 1] | None = None) -> bool | NDArray[np.bool]: from . import is_constant if len(a.shape) == 1: # pragma: no cover @@ -68,9 +68,9 @@ def _is_constant_cs(a: types.CSBase, /, *, axis: Literal[0, 1, None] = None) -> @numba.njit(cache=True) -def _is_constant_cs_major(a: types.CSBase, shape: tuple[int, int]) -> NDArray[np.bool_]: +def _is_constant_cs_major(a: types.CSBase, shape: tuple[int, int]) -> NDArray[np.bool]: n = len(a.indptr) - 1 - result = np.ones(n, dtype=np.bool_) + result = np.ones(n, dtype=np.bool) for i in numba.prange(n): start = a.indptr[i] stop = a.indptr[i + 1] @@ -83,13 +83,13 @@ def _is_constant_cs_major(a: types.CSBase, shape: tuple[int, int]) -> NDArray[np @is_constant_.register(types.DaskArray) -def _is_constant_dask(a: types.DaskArray, /, *, axis: Literal[0, 1, None] = None) -> types.DaskArray: +def _is_constant_dask(a: types.DaskArray, /, *, axis: Literal[0, 1] | None = None) -> types.DaskArray: import dask.array as da from . import is_constant if axis is not None: - return da.map_blocks(partial(is_constant, axis=axis), a, drop_axis=axis, meta=np.array([], dtype=np.bool_)) + return da.map_blocks(partial(is_constant, axis=axis), a, drop_axis=axis, meta=np.array([], dtype=np.bool)) rv = ( (a == a[0, 0].compute()).all() diff --git a/src/fast_array_utils/stats/_mean.py b/src/fast_array_utils/stats/_mean.py index f6dd63f..93c5a82 100644 --- a/src/fast_array_utils/stats/_mean.py +++ b/src/fast_array_utils/stats/_mean.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MPL-2.0 from __future__ import annotations -from typing import TYPE_CHECKING, no_type_check +from typing import TYPE_CHECKING import numpy as np @@ -17,14 +17,13 @@ from ..typing import CpuArray, DiskArray, GpuArray -@no_type_check # mypy is very confused def mean_( x: CpuArray | GpuArray | DiskArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, ) -> NDArray[np.number[Any]] | np.number[Any] | types.DaskArray: total = sum_(x, axis=axis, dtype=dtype) n = np.prod(x.shape) if axis is None else x.shape[axis] - return total / n + return total / n # type: ignore[call-overload,operator,return-value] diff --git a/src/fast_array_utils/stats/_mean_var.py b/src/fast_array_utils/stats/_mean_var.py index 28239c0..df2d127 100644 --- a/src/fast_array_utils/stats/_mean_var.py +++ b/src/fast_array_utils/stats/_mean_var.py @@ -23,7 +23,7 @@ def mean_var_( x: CpuArray | GpuArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, correction: int = 0, ) -> ( tuple[NDArray[np.float64], NDArray[np.float64]] diff --git a/src/fast_array_utils/stats/_sum.py b/src/fast_array_utils/stats/_sum.py index e5eb711..a0a14f4 100644 --- a/src/fast_array_utils/stats/_sum.py +++ b/src/fast_array_utils/stats/_sum.py @@ -17,7 +17,7 @@ from ..typing import CpuArray, DiskArray, GpuArray - ComplexAxis: TypeAlias = tuple[Literal[0], Literal[1]] | tuple[Literal[0, 1]] | Literal[0, 1, None] + ComplexAxis: TypeAlias = tuple[Literal[0], Literal[1]] | tuple[Literal[0, 1]] | Literal[0, 1] | None @singledispatch @@ -25,7 +25,7 @@ def sum_( x: CpuArray | GpuArray | DiskArray | types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False, ) -> NDArray[Any] | np.number[Any] | types.CupyArray | types.DaskArray: @@ -43,7 +43,7 @@ def _sum_cupy( x: GpuArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False, ) -> types.CupyArray | np.number[Any]: @@ -56,7 +56,7 @@ def _sum_cs( x: types.CSBase, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False, ) -> NDArray[Any] | np.number[Any]: @@ -76,7 +76,7 @@ def _sum_dask( x: types.DaskArray, /, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: DTypeLike | None = None, keep_cupy_as_array: bool = False, ) -> types.DaskArray: @@ -129,7 +129,7 @@ def sum_dask_inner( return cast("NDArray[Any] | types.CupyArray", rv.reshape(shape)) -def normalize_axis(axis: ComplexAxis, ndim: int) -> Literal[0, 1, None]: +def normalize_axis(axis: ComplexAxis, ndim: int) -> Literal[0, 1] | None: """Adapt `axis` parameter passed by Dask to what we support.""" match axis: case int() | None: @@ -145,7 +145,7 @@ def normalize_axis(axis: ComplexAxis, ndim: int) -> Literal[0, 1, None]: return axis -def get_shape(a: NDArray[Any] | np.number[Any] | types.CupyArray, *, axis: Literal[0, 1, None], keepdims: bool) -> tuple[int] | tuple[int, int]: +def get_shape(a: NDArray[Any] | np.number[Any] | types.CupyArray, *, axis: Literal[0, 1] | None, keepdims: bool) -> tuple[int] | tuple[int, int]: """Get the output shape of an axis-flattening operation.""" match keepdims, a.ndim: case False, 0: diff --git a/tests/test_stats.py b/tests/test_stats.py index 8edb826..2380c8d 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -24,17 +24,17 @@ Array: TypeAlias = CpuArray | GpuArray | DiskArray | types.CSDataset | types.DaskArray - DTypeIn = np.float32 | np.float64 | np.int32 | np.bool_ + DTypeIn = np.float32 | np.float64 | np.int32 | np.bool DTypeOut = np.float32 | np.float64 | np.int64 - NdAndAx: TypeAlias = tuple[Literal[1], Literal[None]] | tuple[Literal[2], Literal[0, 1, None]] + NdAndAx: TypeAlias = tuple[Literal[1], None] | tuple[Literal[2], Literal[0, 1] | None] class StatFun(Protocol): # noqa: D101 def __call__( # noqa: D102 self, arr: Array, *, - axis: Literal[0, 1, None] = None, + axis: Literal[0, 1] | None = None, dtype: type[DTypeOut] | None = None, ) -> NDArray[Any] | np.number[Any] | types.DaskArray: ... @@ -77,11 +77,11 @@ def check_ndim(array_type: ArrayType, ndim: Literal[1, 2]) -> Literal[1, 2]: @pytest.fixture(scope="session") -def axis(ndim_and_axis: NdAndAx) -> Literal[0, 1, None]: +def axis(ndim_and_axis: NdAndAx) -> Literal[0, 1] | None: return ndim_and_axis[1] -@pytest.fixture(params=[np.float32, np.float64, np.int32, np.bool_]) +@pytest.fixture(params=[np.float32, np.float64, np.int32, np.bool]) def dtype_in(request: pytest.FixtureRequest, array_type: ArrayType) -> type[DTypeIn]: dtype = cast("type[DTypeIn]", request.param) inner_cls = array_type.inner.cls if array_type.inner else array_type.cls @@ -107,7 +107,7 @@ def np_arr(dtype_in: type[DTypeIn], ndim: Literal[1, 2]) -> NDArray[DTypeIn]: @pytest.mark.array_type(skip={*ATS_SPARSE_DS, Flags.Matrix}) @pytest.mark.parametrize("func", STAT_FUNCS) @pytest.mark.parametrize(("ndim", "axis"), [(1, 0), (2, 3), (2, -1)], ids=["1d-ax0", "2d-ax3", "2d-axneg"]) -def test_ndim_error(array_type: ArrayType[Array], func: StatFun, ndim: Literal[1, 2], axis: Literal[0, 1, None]) -> None: +def test_ndim_error(array_type: ArrayType[Array], func: StatFun, ndim: Literal[1, 2], axis: Literal[0, 1] | None) -> None: check_ndim(array_type, ndim) # not using the fixture because we don’t need to test multiple dtypes np_arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32) @@ -124,7 +124,7 @@ def test_sum( array_type: ArrayType[CpuArray | GpuArray | DiskArray | types.DaskArray], dtype_in: type[DTypeIn], dtype_arg: type[DTypeOut] | None, - axis: Literal[0, 1, None], + axis: Literal[0, 1] | None, np_arr: NDArray[DTypeIn], ) -> None: arr = array_type(np_arr.copy()) @@ -152,7 +152,7 @@ def test_sum( if dtype_arg is not None: assert sum_.dtype == dtype_arg, (sum_.dtype, dtype_arg) - elif dtype_in in {np.bool_, np.int32}: + elif dtype_in in {np.bool, np.int32}: assert sum_.dtype == np.int64 else: assert sum_.dtype == dtype_in @@ -182,7 +182,7 @@ def test_sum_dask_shapes(array_type: ArrayType[types.DaskArray], axis: Literal[0 @pytest.mark.array_type(skip=ATS_SPARSE_DS) -def test_mean(array_type: ArrayType[Array], axis: Literal[0, 1, None], np_arr: NDArray[DTypeIn]) -> None: +def test_mean(array_type: ArrayType[Array], axis: Literal[0, 1] | None, np_arr: NDArray[DTypeIn]) -> None: arr = array_type(np_arr) result = stats.mean(arr, axis=axis) # type: ignore[arg-type] # https://github.com/python/mypy/issues/16777 @@ -198,7 +198,7 @@ def test_mean(array_type: ArrayType[Array], axis: Literal[0, 1, None], np_arr: N @pytest.mark.array_type(skip=Flags.Disk) def test_mean_var( array_type: ArrayType[CpuArray | GpuArray | types.DaskArray], - axis: Literal[0, 1, None], + axis: Literal[0, 1] | None, np_arr: NDArray[DTypeIn], ) -> None: arr = array_type(np_arr) @@ -263,7 +263,7 @@ def test_mean_var_sparse_32(array_type: ArrayType[types.CSArray]) -> None: def test_is_constant( *, array_type: ArrayType[CpuArray | types.DaskArray], - axis: Literal[0, 1, None], + axis: Literal[0, 1] | None, expected: bool | list[bool], ) -> None: x_data = [ @@ -277,7 +277,7 @@ def test_is_constant( x = array_type(x_data, dtype=np.float64) result = stats.is_constant(x, axis=axis) if isinstance(result, types.DaskArray): - result = cast("NDArray[np.bool_] | bool", result.compute()) + result = cast("NDArray[np.bool] | bool", result.compute()) if isinstance(result, types.CupyArray | types.CupyCSMatrix): result = result.get() if isinstance(expected, list): @@ -307,7 +307,7 @@ def test_stats_benchmark( benchmark: BenchmarkFixture, func: StatFun, array_type: ArrayType[CpuArray, None], - axis: Literal[0, 1, None], + axis: Literal[0, 1] | None, dtype: type[np.float32 | np.float64], ) -> None: shape = (10_000, 10_000) if "sparse" in array_type.mod else (1000, 1000) diff --git a/tests/test_to_dense.py b/tests/test_to_dense.py index bb61218..a7b5692 100644 --- a/tests/test_to_dense.py +++ b/tests/test_to_dense.py @@ -31,7 +31,7 @@ def test_to_dense(array_type: ArrayType[Array], *, order: Literal["K", "C", "F"], to_cpu_memory: bool) -> None: x = array_type([[1, 2, 3], [4, 5, 6]], dtype=np.float32) if not to_cpu_memory and array_type.cls in {types.CSCDataset, types.CSRDataset}: - with pytest.raises(ValueError, match="to_cpu_memory must be True if x is an CS{R,C}Dataset"): + with pytest.raises(ValueError, match=r"to_cpu_memory must be True if x is an CS\{R,C\}Dataset"): to_dense(x, order=order, to_cpu_memory=to_cpu_memory) return diff --git a/typings/cupy/_core/core.pyi b/typings/cupy/_core/core.pyi index 1ace0e6..f8d459e 100644 --- a/typings/cupy/_core/core.pyi +++ b/typings/cupy/_core/core.pyi @@ -32,7 +32,7 @@ class ndarray: @property def T(self) -> Self: ... # noqa: N802 @overload - def all(self, axis: None = None) -> np.bool_: ... + def all(self, axis: None = None) -> np.bool: ... @overload def all(self, axis: int) -> ndarray: ... def reshape(self, shape: tuple[int, ...] | int) -> ndarray: ... diff --git a/typings/cupy/_creation/from_data.pyi b/typings/cupy/_creation/from_data.pyi index 13b61fe..da6f030 100644 --- a/typings/cupy/_creation/from_data.pyi +++ b/typings/cupy/_creation/from_data.pyi @@ -10,7 +10,7 @@ from .._core import ndarray def asarray( a: ArrayLike | h5py.Dataset | zarr.Array, dtype: DTypeLike | None = None, - order: Literal["C", "F", "A", "K", None] = None, + order: Literal["C", "F", "A", "K"] | None = None, *, blocking: bool = False, ) -> ndarray: ... diff --git a/typings/cupyx/scipy/sparse/_base.pyi b/typings/cupyx/scipy/sparse/_base.pyi index 3cf37c5..45a05b7 100644 --- a/typings/cupyx/scipy/sparse/_base.pyi +++ b/typings/cupyx/scipy/sparse/_base.pyi @@ -10,7 +10,7 @@ class spmatrix: dtype: np.dtype[Any] shape: tuple[int, int] ndim: int - def toarray(self, order: Literal["C", "F", None] = None, out: None = None) -> cupy.ndarray: ... + def toarray(self, order: Literal["C", "F"] | None = None, out: None = None) -> cupy.ndarray: ... def __power__(self, other: int) -> Self: ... def __array__(self) -> NDArray[Any]: ... def get(self, stream: cupy.cuda.Stream | None = None) -> sps.spmatrix: ... diff --git a/typings/dask/array/core.pyi b/typings/dask/array/core.pyi index 4073171..dba0e6c 100644 --- a/typings/dask/array/core.pyi +++ b/typings/dask/array/core.pyi @@ -56,7 +56,7 @@ class Array: *, traverse: bool = True, maxval: float | None = None, - color: Literal["order", "ages", "freed", "memoryincreases", "memorydecreases", "memorypressure", None] = None, + color: Literal["order", "ages", "freed", "memoryincreases", "memorydecreases", "memorypressure"] | None = None, collapse_outputs: bool = False, verbose: bool = False, engine: str = "ipycytoscape", From ec4959643dcb286e09d376d9387c55b932a73962 Mon Sep 17 00:00:00 2001 From: Phil Schaf Date: Sat, 13 Sep 2025 14:17:26 +0200 Subject: [PATCH 2/5] simpler --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e4e4060..364febf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,8 +148,8 @@ lint.flake8-type-checking.exempt-modules = [ ] lint.flake8-type-checking.strict = true lint.isort.known-first-party = [ "fast_array_utils" ] lint.isort.lines-after-imports = 2 -lint.isort.required-imports = [ "from __future__ import annotations" ] lint.pydocstyle.convention = "numpy" +lint.future-annotations = true [tool.pytest.ini_options] addopts = [ From 75fa18c046f91b043bbb9f09c94bc9a2262d1e61 Mon Sep 17 00:00:00 2001 From: Phil Schaf Date: Sat, 13 Sep 2025 14:23:05 +0200 Subject: [PATCH 3/5] bump dask min --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 364febf..7474611 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,8 @@ optional-dependencies.doc = [ "sphinx-autodoc-typehints>=3.2", "sphinx-autofixture>=0.4.1", ] -optional-dependencies.full = [ "dask", "fast-array-utils[accel,sparse]", "h5py", "zarr" ] +optional-dependencies.full = [ "fast-array-utils[accel,dask,sparse]", "h5py", "zarr" ] +optional-dependencies.dask = [ "dask>=2023.6.1" ] optional-dependencies.sparse = [ "scipy>=1.11" ] optional-dependencies.test = [ "anndata", @@ -99,7 +100,7 @@ overrides.matrix.resolution.features = [ ] overrides.matrix.resolution.dependencies = [ # TODO: move to min dep once this is fixed: https://github.com/tlambert03/hatch-min-requirements/issues/5 - { if = [ "lowest" ], value = "dask==2023.5.1" }, + { if = [ "lowest" ], value = "dask==2023.6.1" }, ] [[tool.hatch.envs.hatch-test.matrix]] From 62b366213dfe160e7b6089edf7c00c64f33d77c5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 12:23:12 +0000 Subject: [PATCH 4/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7474611..7532703 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ classifiers = [ dynamic = [ "description", "readme", "version" ] dependencies = [ "numpy>=2" ] optional-dependencies.accel = [ "numba>=0.57" ] +optional-dependencies.dask = [ "dask>=2023.6.1" ] optional-dependencies.doc = [ "furo>=2024.8.6", "pytest>=8.4", @@ -35,7 +36,6 @@ optional-dependencies.doc = [ "sphinx-autofixture>=0.4.1", ] optional-dependencies.full = [ "fast-array-utils[accel,dask,sparse]", "h5py", "zarr" ] -optional-dependencies.dask = [ "dask>=2023.6.1" ] optional-dependencies.sparse = [ "scipy>=1.11" ] optional-dependencies.test = [ "anndata", From 87492816cd9fb1b4d0bfcecc1f68d6abe834e1af Mon Sep 17 00:00:00 2001 From: Phil Schaf Date: Sat, 13 Sep 2025 15:17:31 +0200 Subject: [PATCH 5/5] whoops --- docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/conf.py b/docs/conf.py index 32f21a4..1c04e72 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -110,6 +110,7 @@ def find_type_alias(name: str) -> tuple[str, str, str | None] | tuple[None, None return "class", path, None return "data", f"fast_array_utils.{name}", None if name.startswith("np."): + name = name.removeprefix("np.") return _np_nocls.get(name, "class"), f"numpy.{name}", f"np.{name}" if name in npt.__all__: return "data", f"numpy.typing.{name}", None