Skip to content

Commit 21950a2

Browse files
committed
Merge branch 'ig/typesize_for_blosc' of github.com:ilan-gold/zarr-python into ig/typesize_for_blosc
2 parents 45693bf + 03f298a commit 21950a2

File tree

8 files changed

+71
-30
lines changed

8 files changed

+71
-30
lines changed

changes/2978.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed sharding with GPU buffers.

pyproject.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ test = [
8383
remote_tests = [
8484
'zarr[remote]',
8585
"botocore",
86-
"s3fs",
86+
"s3fs>=2023.10.0",
8787
"moto[s3,server]",
8888
"requests",
8989
]
@@ -104,7 +104,7 @@ docs = [
104104
# Optional dependencies to run examples
105105
'numcodecs[msgpack]',
106106
'rich',
107-
's3fs',
107+
's3fs>=2023.10.0',
108108
'astroid<4'
109109
]
110110

@@ -348,27 +348,27 @@ python_version = "3.11"
348348
ignore_missing_imports = true
349349
namespace_packages = false
350350

351-
352351
strict = true
353352
warn_unreachable = true
354-
355353
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
356354

355+
357356
[[tool.mypy.overrides]]
358357
module = [
359-
"zarr.v2.*",
358+
"tests.package_with_entrypoint.*",
359+
"tests.test_codecs.test_transpose",
360+
"tests.test_config"
360361
]
361-
ignore_errors = true
362+
strict = false
362363

364+
# TODO: Move the next modules up to the strict = false section
365+
# and fix the errors
363366
[[tool.mypy.overrides]]
364367
module = [
365368
"zarr.testing.stateful", # lots of hypothesis decorator errors
366-
"tests.package_with_entrypoint.*",
367369
"tests.test_codecs.test_codecs",
368-
"tests.test_codecs.test_transpose",
369370
"tests.test_metadata.*",
370371
"tests.test_store.*",
371-
"tests.test_config",
372372
"tests.test_group",
373373
"tests.test_indexing",
374374
"tests.test_properties",

src/zarr/codecs/sharding.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ def _get_index_chunk_spec(self, chunks_per_shard: ChunkCoords) -> ArraySpec:
683683
config=ArrayConfig(
684684
order="C", write_empty_chunks=False
685685
), # Note: this is hard-coded for simplicity -- it is not surfaced into user code,
686-
prototype=numpy_buffer_prototype(),
686+
prototype=default_buffer_prototype(),
687687
)
688688

689689
def _get_chunk_spec(self, shard_spec: ArraySpec) -> ArraySpec:

src/zarr/testing/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def has_cupy() -> bool:
4444
# Decorator for GPU tests
4545
def gpu_test(func: T_Callable) -> T_Callable:
4646
return cast(
47-
T_Callable,
47+
"T_Callable",
4848
pytest.mark.gpu(
4949
pytest.mark.skipif(not has_cupy(), reason="CuPy not installed or no GPU available")(
5050
func

tests/package_with_entrypoint/__init__.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from collections.abc import Iterable
2+
from typing import Any
23

3-
from numpy import ndarray
4+
import numpy as np
5+
import numpy.typing as npt
46

57
import zarr.core.buffer
6-
from zarr.abc.codec import ArrayBytesCodec, CodecInput, CodecOutput, CodecPipeline
8+
from zarr.abc.codec import ArrayBytesCodec, CodecInput, CodecPipeline
79
from zarr.codecs import BytesCodec
810
from zarr.core.array_spec import ArraySpec
911
from zarr.core.buffer import Buffer, NDBuffer
10-
from zarr.core.common import BytesLike
1112

1213

1314
class TestEntrypointCodec(ArrayBytesCodec):
@@ -16,14 +17,14 @@ class TestEntrypointCodec(ArrayBytesCodec):
1617
async def encode(
1718
self,
1819
chunks_and_specs: Iterable[tuple[CodecInput | None, ArraySpec]],
19-
) -> Iterable[CodecOutput | None]:
20-
pass
20+
) -> Iterable[Buffer | None]:
21+
return [None]
2122

2223
async def decode(
2324
self,
2425
chunks_and_specs: Iterable[tuple[CodecInput | None, ArraySpec]],
25-
) -> ndarray:
26-
pass
26+
) -> npt.NDArray[Any]:
27+
return np.array(1)
2728

2829
def compute_encoded_size(self, input_byte_length: int, chunk_spec: ArraySpec) -> int:
2930
return input_byte_length
@@ -35,13 +36,13 @@ def __init__(self, batch_size: int = 1) -> None:
3536

3637
async def encode(
3738
self, chunks_and_specs: Iterable[tuple[CodecInput | None, ArraySpec]]
38-
) -> BytesLike:
39-
pass
39+
) -> Iterable[Buffer | None]:
40+
return [None]
4041

4142
async def decode(
4243
self, chunks_and_specs: Iterable[tuple[CodecInput | None, ArraySpec]]
43-
) -> ndarray:
44-
pass
44+
) -> Iterable[NDBuffer | None]:
45+
return np.array(1)
4546

4647

4748
class TestEntrypointBuffer(Buffer):

tests/test_buffer.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,34 @@ async def test_codecs_use_of_gpu_prototype() -> None:
148148
assert cp.array_equal(expect, got)
149149

150150

151+
@gpu_test
152+
@pytest.mark.asyncio
153+
async def test_sharding_use_of_gpu_prototype() -> None:
154+
with zarr.config.enable_gpu():
155+
expect = cp.zeros((10, 10), dtype="uint16", order="F")
156+
157+
a = await zarr.api.asynchronous.create_array(
158+
StorePath(MemoryStore()) / "test_codecs_use_of_gpu_prototype",
159+
shape=expect.shape,
160+
chunks=(5, 5),
161+
shards=(10, 10),
162+
dtype=expect.dtype,
163+
fill_value=0,
164+
)
165+
expect[:] = cp.arange(100).reshape(10, 10)
166+
167+
await a.setitem(
168+
selection=(slice(0, 10), slice(0, 10)),
169+
value=expect[:],
170+
prototype=gpu.buffer_prototype,
171+
)
172+
got = await a.getitem(
173+
selection=(slice(0, 10), slice(0, 10)), prototype=gpu.buffer_prototype
174+
)
175+
assert isinstance(got, cp.ndarray)
176+
assert cp.array_equal(expect, got)
177+
178+
151179
def test_numpy_buffer_prototype() -> None:
152180
buffer = cpu.buffer_prototype.buffer.create_zero_length()
153181
ndbuffer = cpu.buffer_prototype.nd_buffer.create(shape=(1, 2), dtype=np.dtype("int64"))
@@ -157,6 +185,16 @@ def test_numpy_buffer_prototype() -> None:
157185
ndbuffer.as_scalar()
158186

159187

188+
@gpu_test
189+
def test_gpu_buffer_prototype() -> None:
190+
buffer = gpu.buffer_prototype.buffer.create_zero_length()
191+
ndbuffer = gpu.buffer_prototype.nd_buffer.create(shape=(1, 2), dtype=cp.dtype("int64"))
192+
assert isinstance(buffer.as_array_like(), cp.ndarray)
193+
assert isinstance(ndbuffer.as_ndarray_like(), cp.ndarray)
194+
with pytest.raises(ValueError, match="Buffer does not contain a single scalar value"):
195+
ndbuffer.as_scalar()
196+
197+
160198
# TODO: the same test for other buffer classes
161199
def test_cpu_buffer_as_scalar() -> None:
162200
buf = cpu.buffer_prototype.nd_buffer.create(shape=(), dtype="int64")

tests/test_codecs/test_transpose.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ async def test_transpose(
4848
read_data = await _AsyncArrayProxy(a)[:, :].get()
4949
assert np.array_equal(data, read_data)
5050

51+
assert isinstance(read_data, np.ndarray)
5152
if runtime_read_order == "F":
5253
assert read_data.flags["F_CONTIGUOUS"]
5354
assert not read_data.flags["C_CONTIGUOUS"]
@@ -90,5 +91,5 @@ def test_transpose_invalid(
9091
dtype=data.dtype,
9192
fill_value=0,
9293
chunk_key_encoding={"name": "v2", "separator": "."},
93-
filters=[TransposeCodec(order=order)],
94+
filters=[TransposeCodec(order=order)], # type: ignore[arg-type]
9495
)

tests/test_config.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import zarr
1111
import zarr.api
1212
from zarr import zeros
13-
from zarr.abc.codec import CodecInput, CodecOutput, CodecPipeline
13+
from zarr.abc.codec import CodecPipeline
1414
from zarr.abc.store import ByteSetter, Store
1515
from zarr.codecs import (
1616
BloscCodec,
@@ -21,6 +21,7 @@
2121
)
2222
from zarr.core.array_spec import ArraySpec
2323
from zarr.core.buffer import NDBuffer
24+
from zarr.core.buffer.core import Buffer
2425
from zarr.core.codec_pipeline import BatchedCodecPipeline
2526
from zarr.core.config import BadConfigError, config
2627
from zarr.core.indexing import SelectorTuple
@@ -144,7 +145,7 @@ def test_config_codec_pipeline_class(store: Store) -> None:
144145
class MockCodecPipeline(BatchedCodecPipeline):
145146
async def write(
146147
self,
147-
batch_info: Iterable[tuple[ByteSetter, ArraySpec, SelectorTuple, SelectorTuple]],
148+
batch_info: Iterable[tuple[ByteSetter, ArraySpec, SelectorTuple, SelectorTuple, bool]],
148149
value: NDBuffer,
149150
drop_axes: tuple[int, ...] = (),
150151
) -> None:
@@ -174,7 +175,7 @@ async def write(
174175
class MockEnvCodecPipeline(CodecPipeline):
175176
pass
176177

177-
register_pipeline(MockEnvCodecPipeline)
178+
register_pipeline(MockEnvCodecPipeline) # type: ignore[type-abstract]
178179

179180
with mock.patch.dict(
180181
os.environ, {"ZARR_CODEC_PIPELINE__PATH": fully_qualified_name(MockEnvCodecPipeline)}
@@ -191,10 +192,9 @@ def test_config_codec_implementation(store: Store) -> None:
191192
_mock = Mock()
192193

193194
class MockBloscCodec(BloscCodec):
194-
async def _encode_single(
195-
self, chunk_data: CodecInput, chunk_spec: ArraySpec
196-
) -> CodecOutput | None:
195+
async def _encode_single(self, chunk_bytes: Buffer, chunk_spec: ArraySpec) -> Buffer | None:
197196
_mock.call()
197+
return None
198198

199199
register_codec("blosc", MockBloscCodec)
200200
with config.set({"codecs.blosc": fully_qualified_name(MockBloscCodec)}):
@@ -245,7 +245,7 @@ def test_config_buffer_implementation() -> None:
245245
# has default value
246246
assert fully_qualified_name(get_buffer_class()) == config.defaults[0]["buffer"]
247247

248-
arr = zeros(shape=(100), store=StoreExpectingTestBuffer())
248+
arr = zeros(shape=(100,), store=StoreExpectingTestBuffer())
249249

250250
# AssertionError of StoreExpectingTestBuffer when not using my buffer
251251
with pytest.raises(AssertionError):

0 commit comments

Comments
 (0)