Skip to content

Commit 4296053

Browse files
authored
Merge branch 'main' into fix/nested-shard-reads
2 parents 1e6608e + 7eba7f1 commit 4296053

16 files changed

Lines changed: 258 additions & 16 deletions

File tree

.github/workflows/check_changelogs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
1313

1414
- name: Install uv
15-
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
15+
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
1616

1717
- name: Check changelog entries
1818
run: uv run --no-sync python ci/check_changelog_entries.py

.github/workflows/codspeed.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: CodSpeed Benchmarks
2+
3+
on:
4+
push:
5+
branches:
6+
- "main"
7+
pull_request:
8+
# `workflow_dispatch` allows CodSpeed to trigger backtest
9+
# performance analysis in order to generate initial data.
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
benchmarks:
17+
name: Run benchmarks
18+
runs-on: codspeed-macro
19+
steps:
20+
- uses: actions/checkout@v5
21+
with:
22+
fetch-depth: 0 # grab all branches and tags
23+
- name: Set up Python
24+
uses: actions/setup-python@v6
25+
with:
26+
python-version: "3.11"
27+
- name: Install Hatch
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install hatch
31+
- name: Run the benchmarks
32+
uses: CodSpeedHQ/action@v4
33+
with:
34+
mode: walltime
35+
run: hatch run test.py3.11-2.0-minimal:pytest tests/benchmarks --codspeed

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ jobs:
2121
strategy:
2222
matrix:
2323
python-version: ['3.11', '3.12', '3.13']
24-
numpy-version: ['1.26', '2.2']
24+
numpy-version: ['2.0', '2.2']
2525
dependency-set: ["minimal", "optional"]
2626
os: ["ubuntu-latest"]
2727
include:
2828
- python-version: '3.11'
29-
numpy-version: '1.26'
29+
numpy-version: '2.0'
3030
dependency-set: 'optional'
3131
os: 'macos-latest'
3232
- python-version: '3.13'
3333
numpy-version: '2.2'
3434
dependency-set: 'optional'
3535
os: 'macos-latest'
3636
- python-version: '3.11'
37-
numpy-version: '1.26'
37+
numpy-version: '2.0'
3838
dependency-set: 'optional'
3939
os: 'windows-latest'
4040
- python-version: '3.13'

changes/3562.misc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add continuous performance benchmarking infrastructure.

changes/3636.misc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The minimum required version of NumPy is now 2.0.

changes/3648.misc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix deprecation of setting a shape on an array directly in ``numpy`` 2.5+.

docs/contributing.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,4 +264,13 @@ If an existing Zarr format version changes, or a new version of the Zarr format
264264
## Release procedure
265265

266266
Open an issue on GitHub announcing the release using the release checklist template:
267-
[https://github.com/zarr-developers/zarr-python/issues/new?template=release-checklist.md](https://github.com/zarr-developers/zarr-python/issues/new?template=release-checklist.md>). The release checklist includes all steps necessary for the release.
267+
[https://github.com/zarr-developers/zarr-python/issues/new?template=release-checklist.md](https://github.com/zarr-developers/zarr-python/issues/new?template=release-checklist.md>). The release checklist includes all steps necessary for the release.
268+
269+
## Benchmarks
270+
271+
Zarr uses [pytest-benchmark](https://pytest-benchmark.readthedocs.io/en/latest/) for running
272+
performance benchmarks as part of our test suite. The benchmarks can be are found in `tests/benchmarks`.
273+
By default pytest is configured to run these benchmarks as plain tests (i.e., no benchmarking). To run
274+
a benchmark with timing measurements, use the `--benchmark-enable` when invoking `pytest`.
275+
276+
The benchmarks are run as part of the continuous integration suite through [codspeed](https://codspeed.io/zarr-developers/zarr-python).

docs/user-guide/installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Required dependencies include:
66

77
- [Python](https://docs.python.org/3/) (3.11 or later)
88
- [packaging](https://packaging.pypa.io) (22.0 or later)
9-
- [numpy](https://numpy.org) (1.26 or later)
9+
- [numpy](https://numpy.org) (2.0 or later)
1010
- [numcodecs](https://numcodecs.readthedocs.io) (0.14 or later)
1111
- [google-crc32c](https://github.com/googleapis/python-crc32c) (1.5 or later)
1212
- [typing_extensions](https://typing-extensions.readthedocs.io) (4.9 or later)

pyproject.toml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ requires-python = ">=3.11"
3333
# If you add a new dependency here, please also add it to .pre-commit-config.yml
3434
dependencies = [
3535
'packaging>=22.0',
36-
'numpy>=1.26',
36+
'numpy>=2.0',
3737
'numcodecs>=0.14',
3838
'google-crc32c>=1.5',
3939
'typing_extensions>=4.12',
@@ -82,6 +82,8 @@ test = [
8282
'numpydoc',
8383
"hypothesis",
8484
"pytest-xdist",
85+
"pytest-benchmark",
86+
"pytest-codspeed",
8587
"packaging",
8688
"tomlkit",
8789
"uv",
@@ -163,7 +165,7 @@ COV_CORE_DATAFILE = ".coverage.eager"
163165

164166
[[tool.hatch.envs.test.matrix]]
165167
python = ["3.11", "3.12", "3.13"]
166-
numpy = ["1.26", "2.2"]
168+
numpy = ["2.0", "2.2"]
167169
deps = ["minimal", "optional"]
168170

169171
[tool.hatch.envs.test.overrides]
@@ -175,11 +177,12 @@ matrix.deps.dependencies = [
175177
run-coverage = "pytest --cov-config=pyproject.toml --cov=src --cov-append --cov-report xml --junitxml=junit.xml -o junit_family=legacy"
176178
run-coverage-html = "pytest --cov-config=pyproject.toml --cov=src --cov-append --cov-report html"
177179
run-coverage-gpu = "pip install cupy-cuda12x && pytest -m gpu --cov-config=pyproject.toml --cov=src --cov-append --cov-report xml --junitxml=junit.xml -o junit_family=legacy"
178-
run = "run-coverage --no-cov"
180+
run = "run-coverage --no-cov --ignore tests/benchmarks"
179181
run-pytest = "run"
180182
run-verbose = "run-coverage --verbose"
181183
run-mypy = "mypy src"
182184
run-hypothesis = "run-coverage -nauto --run-slow-hypothesis tests/test_properties.py tests/test_store/test_stateful*"
185+
run-benchmark = "pytest --benchmark-enable tests/benchmarks"
183186
list-env = "pip list"
184187

185188
[tool.hatch.envs.gputest]
@@ -192,11 +195,11 @@ features = ["test", "gpu"]
192195

193196
[[tool.hatch.envs.gputest.matrix]]
194197
python = ["3.11", "3.12", "3.13"]
195-
numpy = ["1.26", "2.2"]
198+
numpy = ["2.0", "2.2"]
196199
version = ["minimal"]
197200

198201
[tool.hatch.envs.gputest.scripts]
199-
run-coverage = "pytest -m gpu --cov-config=pyproject.toml --cov=pkg --cov-report xml --cov=src --junitxml=junit.xml -o junit_family=legacy"
202+
run-coverage = "pytest -m gpu --cov-config=pyproject.toml --cov=pkg --cov-report xml --cov=src --junitxml=junit.xml -o junit_family=legacy --ignore tests/benchmarks"
200203
run = "run-coverage --no-cov"
201204
run-verbose = "run-coverage --verbose"
202205
run-mypy = "mypy src"
@@ -234,7 +237,7 @@ python = "3.11"
234237
dependencies = [
235238
'zarr[remote]',
236239
'packaging==22.*',
237-
'numpy==1.26.*',
240+
'numpy==2.0.*',
238241
'numcodecs==0.14.*', # 0.14 needed for zarr3 codecs
239242
'fsspec==2023.10.0',
240243
's3fs==2023.10.0',
@@ -405,7 +408,10 @@ doctest_optionflags = [
405408
"IGNORE_EXCEPTION_DETAIL",
406409
]
407410
addopts = [
408-
"--durations=10", "-ra", "--strict-config", "--strict-markers",
411+
"--benchmark-columns", "min,mean,stddev,outliers,rounds,iterations",
412+
"--benchmark-disable", # benchmark routines run as tests without benchmarking instrumentation
413+
"--durations", "10",
414+
"-ra", "--strict-config", "--strict-markers",
409415
]
410416
filterwarnings = [
411417
"error",

src/zarr/_compat.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
from collections.abc import Callable
33
from functools import wraps
44
from inspect import Parameter, signature
5-
from typing import Any, TypeVar
5+
from typing import TYPE_CHECKING, Any, TypeVar
6+
7+
import numpy as np
8+
from packaging.version import Version
69

710
from zarr.errors import ZarrFutureWarning
811

12+
if TYPE_CHECKING:
13+
from numpy.typing import NDArray
14+
915
T = TypeVar("T")
1016

1117
# Based off https://github.com/scikit-learn/scikit-learn/blob/e87b32a81c70abed8f2e97483758eb64df8255e9/sklearn/utils/validation.py#L63
@@ -68,3 +74,37 @@ def inner_f(*args: Any, **kwargs: Any) -> T:
6874
return _inner_deprecate_positional_args(func)
6975

7076
return _inner_deprecate_positional_args # type: ignore[return-value]
77+
78+
79+
def _reshape_view(arr: "NDArray[Any]", shape: tuple[int, ...]) -> "NDArray[Any]":
80+
"""Reshape an array without copying data.
81+
82+
This function provides compatibility across NumPy versions for reshaping arrays
83+
as views. On NumPy >= 2.1, it uses ``reshape(copy=False)`` which explicitly
84+
fails if a view cannot be created. On older versions, it uses direct shape
85+
assignment which has the same behavior but is deprecated in 2.5+.
86+
87+
Parameters
88+
----------
89+
arr : NDArray
90+
The array to reshape.
91+
shape : tuple of int
92+
The new shape.
93+
94+
Returns
95+
-------
96+
NDArray
97+
A reshaped view of the array.
98+
99+
Raises
100+
------
101+
AttributeError
102+
If a view cannot be created (the array is not contiguous) on NumPy < 2.1.
103+
ValueError
104+
If a view cannot be created (the array is not contiguous) on NumPy >= 2.1.
105+
"""
106+
if Version(np.__version__) >= Version("2.1"):
107+
return arr.reshape(shape, copy=False) # type: ignore[call-overload, no-any-return]
108+
else:
109+
arr.shape = shape
110+
return arr

0 commit comments

Comments
 (0)