Skip to content

Commit c4472ac

Browse files
authored
Merge branch 'v3' into upath
2 parents 4268cd1 + 10ae5f3 commit c4472ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+733
-286
lines changed

.github/workflows/hypothesis.yaml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: Slow Hypothesis CI
2+
on:
3+
push:
4+
branches:
5+
- "main"
6+
- "v3"
7+
pull_request:
8+
branches:
9+
- "main"
10+
- "v3"
11+
types: [opened, reopened, synchronize, labeled]
12+
schedule:
13+
- cron: "0 0 * * *" # Daily “At 00:00” UTC
14+
workflow_dispatch: # allows you to trigger manually
15+
16+
env:
17+
FORCE_COLOR: 3
18+
19+
jobs:
20+
21+
hypothesis:
22+
name: Slow Hypothesis Tests
23+
runs-on: "ubuntu-latest"
24+
defaults:
25+
run:
26+
shell: bash -l {0}
27+
28+
strategy:
29+
matrix:
30+
python-version: ['3.11']
31+
numpy-version: ['1.26']
32+
dependency-set: ["optional"]
33+
34+
steps:
35+
- uses: actions/checkout@v4
36+
- name: Set up Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: ${{ matrix.python-version }}
40+
cache: 'pip'
41+
- name: Install Hatch
42+
run: |
43+
python -m pip install --upgrade pip
44+
pip install hatch
45+
- name: Set Up Hatch Env
46+
run: |
47+
hatch env create test.py${{ matrix.python-version }}-${{ matrix.numpy-version }}-${{ matrix.dependency-set }}
48+
hatch env run -e test.py${{ matrix.python-version }}-${{ matrix.numpy-version }}-${{ matrix.dependency-set }} list-env
49+
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache
50+
- name: Restore cached hypothesis directory
51+
id: restore-hypothesis-cache
52+
uses: actions/cache/restore@v4
53+
with:
54+
path: .hypothesis/
55+
key: cache-hypothesis-${{ runner.os }}-${{ github.run_id }}
56+
restore-keys: |
57+
cache-hypothesis-
58+
59+
- name: Run slow Hypothesis tests
60+
if: success()
61+
id: status
62+
run: |
63+
hatch env run --env test.py${{ matrix.python-version }}-${{ matrix.numpy-version }}-${{ matrix.dependency-set }} run-hypothesis
64+
65+
# explicitly save the cache so it gets updated, also do this even if it fails.
66+
- name: Save cached hypothesis directory
67+
id: save-hypothesis-cache
68+
if: always() && steps.status.outcome != 'skipped'
69+
uses: actions/cache/save@v4
70+
with:
71+
path: .hypothesis/
72+
key: cache-hypothesis-${{ runner.os }}-${{ github.run_id }}
73+
74+
- name: Generate and publish the report
75+
if: |
76+
failure()
77+
&& steps.status.outcome == 'failure'
78+
&& github.event_name == 'schedule'
79+
&& github.repository_owner == 'zarr-developers'
80+
uses: xarray-contrib/issue-from-pytest-log@v1
81+
with:
82+
log-path: output-${{ matrix.python-version }}-log.jsonl
83+
issue-title: "Nightly Hypothesis tests failed"
84+
issue-label: "topic-hypothesis"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,8 @@ src/zarr/_version.py
7878
#test_sync*
7979
data/*
8080
src/fixture/
81+
fixture/
8182

8283
.DS_Store
84+
tests/.hypothesis
85+
.hypothesis/

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ default_language_version:
77
python: python3
88
repos:
99
- repo: https://github.com/astral-sh/ruff-pre-commit
10-
rev: 'v0.5.4'
10+
rev: 'v0.5.7'
1111
hooks:
1212
- id: ruff
1313
args: ["--fix", "--show-fixes"]
@@ -22,7 +22,7 @@ repos:
2222
hooks:
2323
- id: check-yaml
2424
- repo: https://github.com/pre-commit/mirrors-mypy
25-
rev: v1.11.0
25+
rev: v1.11.1
2626
hooks:
2727
- id: mypy
2828
files: src

docs/_static/custom.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,3 @@ html[data-theme=dark] .sd-card .sd-card-footer {
117117
html[data-theme=dark] h1 {
118118
color: var(--pst-color-primary);
119119
}
120-
121-
html[data-theme=dark] h3 {
122-
color: #0a6774;
123-
}

pyproject.toml

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@ dependencies = [
2929
'numcodecs>=0.10.0',
3030
'fsspec>2024',
3131
'crc32c',
32-
'zstandard',
3332
'typing_extensions',
3433
'donfig',
35-
'pytest'
3634
]
3735
dynamic = [
3836
"version",
@@ -55,6 +53,22 @@ license = {text = "MIT License"}
5553
keywords = ["Python", "compressed", "ndimensional-arrays", "zarr"]
5654

5755
[project.optional-dependencies]
56+
test = [
57+
"coverage",
58+
"pytest",
59+
"pytest-cov",
60+
"msgpack",
61+
"lmdb",
62+
"s3fs",
63+
"pytest-asyncio",
64+
"moto[s3]",
65+
"flask-cors",
66+
"flask",
67+
"requests",
68+
"mypy",
69+
"hypothesis"
70+
]
71+
5872
jupyter = [
5973
'notebook',
6074
'ipytree>=0.2.2',
@@ -70,8 +84,8 @@ docs = [
7084
'pydata-sphinx-theme',
7185
'numpydoc',
7286
'numcodecs[msgpack]',
73-
"msgpack",
74-
"lmdb",
87+
'msgpack',
88+
'lmdb',
7589
]
7690
extra = [
7791
'msgpack',
@@ -109,21 +123,7 @@ dependencies = [
109123
"numpy~={matrix:numpy}",
110124
"universal_pathlib"
111125
]
112-
extra-dependencies = [
113-
"coverage",
114-
"pytest",
115-
"pytest-cov",
116-
"msgpack",
117-
"lmdb",
118-
"s3fs",
119-
"pytest-asyncio",
120-
"moto[s3]",
121-
"flask-cors",
122-
"flask",
123-
"requests",
124-
"mypy"
125-
]
126-
features = ["extra"]
126+
features = ["test", "extra"]
127127

128128
[[tool.hatch.envs.test.matrix]]
129129
python = ["3.10", "3.11", "3.12"]
@@ -140,6 +140,7 @@ run-coverage = "pytest --cov-config=pyproject.toml --cov=pkg --cov=tests"
140140
run = "run-coverage --no-cov"
141141
run-verbose = "run-coverage --verbose"
142142
run-mypy = "mypy src"
143+
run-hypothesis = "pytest --hypothesis-profile ci tests/v3/test_properties.py"
143144
list-env = "pip list"
144145

145146
[tool.hatch.envs.docs]
@@ -182,9 +183,11 @@ extend-select = [
182183
"UP", # pyupgrade
183184
"RSE",
184185
"RUF",
186+
"TRY", # tryceratops
185187
]
186188
ignore = [
187189
"RUF005",
190+
"TRY003",
188191
]
189192

190193
[tool.mypy]

src/zarr/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
zeros,
2727
zeros_like,
2828
)
29-
from zarr.array import Array, AsyncArray
30-
from zarr.config import config
31-
from zarr.group import AsyncGroup, Group
29+
from zarr.core.array import Array, AsyncArray
30+
from zarr.core.config import config
31+
from zarr.core.group import AsyncGroup, Group
3232

3333
# in case setuptools scm screw up and find version to be 0.0.0
3434
assert not __version__.startswith("0.0.0")

src/zarr/abc/codec.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,28 @@
88

99
from zarr.abc.metadata import Metadata
1010
from zarr.abc.store import ByteGetter, ByteSetter
11-
from zarr.buffer import Buffer, NDBuffer
12-
from zarr.chunk_grids import ChunkGrid
13-
from zarr.common import ChunkCoords, concurrent_map
14-
from zarr.config import config
11+
from zarr.core.buffer import Buffer, NDBuffer
12+
from zarr.core.chunk_grids import ChunkGrid
13+
from zarr.core.common import ChunkCoords, concurrent_map
14+
from zarr.core.config import config
1515

1616
if TYPE_CHECKING:
1717
from typing_extensions import Self
1818

19-
from zarr.array_spec import ArraySpec
20-
from zarr.common import JSON
21-
from zarr.indexing import SelectorTuple
19+
from zarr.core.array_spec import ArraySpec
20+
from zarr.core.common import JSON
21+
from zarr.core.indexing import SelectorTuple
22+
23+
__all__ = [
24+
"CodecInput",
25+
"CodecOutput",
26+
"ArrayArrayCodec",
27+
"ArrayBytesCodec",
28+
"BytesBytesCodec",
29+
"ArrayBytesCodecPartialDecodeMixin",
30+
"ArrayBytesCodecPartialEncodeMixin",
31+
"CodecPipeline",
32+
]
2233

2334
CodecInput = TypeVar("CodecInput", bound=NDBuffer | Buffer)
2435
CodecOutput = TypeVar("CodecOutput", bound=NDBuffer | Buffer)
@@ -112,7 +123,7 @@ async def decode(
112123
-------
113124
Iterable[CodecInput | None]
114125
"""
115-
return await batching_helper(self._decode_single, chunks_and_specs)
126+
return await _batching_helper(self._decode_single, chunks_and_specs)
116127

117128
async def _encode_single(
118129
self, chunk_data: CodecInput, chunk_spec: ArraySpec
@@ -135,7 +146,7 @@ async def encode(
135146
-------
136147
Iterable[CodecOutput | None]
137148
"""
138-
return await batching_helper(self._encode_single, chunks_and_specs)
149+
return await _batching_helper(self._encode_single, chunks_and_specs)
139150

140151

141152
class ArrayArrayCodec(_Codec[NDBuffer, NDBuffer]):
@@ -401,18 +412,18 @@ def from_dict(cls, data: Iterable[JSON | Codec]) -> Self:
401412
return cls(**data)
402413

403414

404-
async def batching_helper(
415+
async def _batching_helper(
405416
func: Callable[[CodecInput, ArraySpec], Awaitable[CodecOutput | None]],
406417
batch_info: Iterable[tuple[CodecInput | None, ArraySpec]],
407418
) -> list[CodecOutput | None]:
408419
return await concurrent_map(
409420
list(batch_info),
410-
noop_for_none(func),
421+
_noop_for_none(func),
411422
config.get("async.concurrency"),
412423
)
413424

414425

415-
def noop_for_none(
426+
def _noop_for_none(
416427
func: Callable[[CodecInput, ArraySpec], Awaitable[CodecOutput | None]],
417428
) -> Callable[[CodecInput | None, ArraySpec], Awaitable[CodecOutput | None]]:
418429
async def wrap(chunk: CodecInput | None, chunk_spec: ArraySpec) -> CodecOutput | None:

src/zarr/abc/metadata.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
from dataclasses import dataclass, fields
1010

11-
from zarr.common import JSON
11+
from zarr.core.common import JSON
12+
13+
__all__ = ["Metadata"]
1214

1315

1416
@dataclass(frozen=True)

src/zarr/abc/store.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
from typing_extensions import Self
66

7-
from zarr.buffer import Buffer, BufferPrototype
8-
from zarr.common import AccessModeLiteral, BytesLike
7+
from zarr.core.buffer import Buffer, BufferPrototype
8+
from zarr.core.common import AccessModeLiteral, BytesLike
9+
10+
__all__ = ["Store", "AccessMode", "ByteGetter", "ByteSetter", "set_or_delete"]
911

1012

1113
class AccessMode(NamedTuple):

src/zarr/api/asynchronous.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,45 @@
99
import numpy.typing as npt
1010

1111
from zarr.abc.codec import Codec
12-
from zarr.array import Array, AsyncArray
13-
from zarr.buffer import NDArrayLike
14-
from zarr.chunk_key_encodings import ChunkKeyEncoding
15-
from zarr.common import JSON, AccessModeLiteral, ChunkCoords, MemoryOrder, ZarrFormat
16-
from zarr.group import AsyncGroup
17-
from zarr.metadata import ArrayV2Metadata, ArrayV3Metadata
12+
from zarr.core.array import Array, AsyncArray
13+
from zarr.core.buffer import NDArrayLike
14+
from zarr.core.chunk_key_encodings import ChunkKeyEncoding
15+
from zarr.core.common import JSON, AccessModeLiteral, ChunkCoords, MemoryOrder, ZarrFormat
16+
from zarr.core.group import AsyncGroup
17+
from zarr.core.metadata import ArrayV2Metadata, ArrayV3Metadata
1818
from zarr.store import (
1919
StoreLike,
2020
make_store_path,
2121
)
2222

23+
__all__ = [
24+
"consolidate_metadata",
25+
"copy",
26+
"copy_all",
27+
"copy_store",
28+
"load",
29+
"open",
30+
"open_consolidated",
31+
"save",
32+
"save_array",
33+
"save_group",
34+
"tree",
35+
"array",
36+
"group",
37+
"open_group",
38+
"create",
39+
"empty",
40+
"empty_like",
41+
"full",
42+
"full_like",
43+
"ones",
44+
"ones_like",
45+
"open_array",
46+
"open_like",
47+
"zeros",
48+
"zeros_like",
49+
]
50+
2351
# TODO: this type could use some more thought, noqa to avoid "Variable "asynchronous.ArrayLike" is not valid as a type"
2452
ArrayLike = Union[AsyncArray | Array | npt.NDArray[Any]] # noqa
2553
PathLike = str
@@ -66,7 +94,7 @@ def _like_args(a: ArrayLike, kwargs: dict[str, Any]) -> dict[str, Any]:
6694
if isinstance(a.metadata, ArrayV3Metadata):
6795
new["codecs"] = a.metadata.codecs
6896
else:
69-
raise ValueError(f"Unsupported zarr format: {a.metadata.zarr_format}")
97+
raise TypeError(f"Unsupported zarr format: {a.metadata.zarr_format}")
7098
else:
7199
# TODO: set default values compressor/codecs
72100
# to do this, we may need to evaluate if this is a v2 or v3 array
@@ -862,7 +890,7 @@ async def open_array(
862890

863891
try:
864892
return await AsyncArray.open(store_path, zarr_format=zarr_format)
865-
except FileNotFoundError as e:
893+
except FileNotFoundError:
866894
if store_path.store.mode.create:
867895
return await create(
868896
store=store_path,
@@ -871,7 +899,7 @@ async def open_array(
871899
overwrite=store_path.store.mode.overwrite,
872900
**kwargs,
873901
)
874-
raise e
902+
raise
875903

876904

877905
async def open_like(a: ArrayLike, path: str, **kwargs: Any) -> AsyncArray:

0 commit comments

Comments
 (0)