Check tests folder with mypy by TomAugspurger · Pull Request #2150 · zarr-developers/zarr-python · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
14 changes: 11 additions & 3 deletions src/zarr/core/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
ZARRAY_JSON,
ZATTRS_JSON,
ChunkCoords,
ShapeLike,
ZarrFormat,
concurrent_map,
parse_shapelike,
product,
)
from zarr.core.config import config, parse_indexing_order
Expand Down Expand Up @@ -113,7 +115,7 @@ async def create(
store: StoreLike,
*,
# v2 and v3
shape: ChunkCoords,
shape: ShapeLike,
dtype: npt.DTypeLike,
zarr_format: ZarrFormat = 3,
fill_value: Any | None = None,
Expand All @@ -129,7 +131,7 @@ async def create(
codecs: Iterable[Codec | dict[str, JSON]] | None = None,
dimension_names: Iterable[str] | None = None,
# v2 only
chunks: ChunkCoords | None = None,
chunks: ShapeLike | None = None,
dimension_separator: Literal[".", "/"] | None = None,
order: Literal["C", "F"] | None = None,
filters: list[dict[str, JSON]] | None = None,
Expand All @@ -140,9 +142,14 @@ async def create(
) -> AsyncArray:
store_path = await make_store_path(store)

shape = parse_shapelike(shape)

if chunk_shape is None:
if chunks is None:
chunk_shape = chunks = _guess_chunks(shape=shape, typesize=np.dtype(dtype).itemsize)
else:
chunks = parse_shapelike(chunks)

chunk_shape = chunks
elif chunks is not None:
raise ValueError("Only one of chunk_shape or chunks must be provided.")
Expand Down Expand Up @@ -214,7 +221,7 @@ async def _create_v3(
cls,
store_path: StorePath,
*,
shape: ChunkCoords,
shape: ShapeLike,
dtype: npt.DTypeLike,
chunk_shape: ChunkCoords,
fill_value: Any | None = None,
Expand All @@ -232,6 +239,7 @@ async def _create_v3(
if not exists_ok:
await ensure_no_existing_node(store_path, zarr_format=3)

shape = parse_shapelike(shape)
codecs = list(codecs) if codecs is not None else [BytesCodec()]

if fill_value is None:
Expand Down
5 changes: 4 additions & 1 deletion src/zarr/core/chunk_grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
JSON,
ChunkCoords,
ChunkCoordsLike,
ShapeLike,
parse_named_configuration,
parse_shapelike,
)
Expand All @@ -26,7 +27,7 @@


def _guess_chunks(
shape: ChunkCoords,
shape: ShapeLike,
typesize: int,
*,
increment_bytes: int = 256 * 1024,
Expand Down Expand Up @@ -56,6 +57,8 @@ def _guess_chunks(
ChunkCoords

"""
if isinstance(shape, int):
shape = (shape,)

ndims = len(shape)
# require chunks to have non-zero length for all dimensions
Expand Down
9 changes: 5 additions & 4 deletions src/zarr/core/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
ZATTRS_JSON,
ZGROUP_JSON,
ChunkCoords,
ShapeLike,
ZarrFormat,
parse_shapelike,
)
Expand Down Expand Up @@ -366,7 +367,7 @@ async def create_array(
self,
name: str,
*,
shape: ChunkCoords,
shape: ShapeLike,
dtype: npt.DTypeLike = "float64",
fill_value: Any | None = None,
attributes: dict[str, JSON] | None = None,
Expand All @@ -381,7 +382,7 @@ async def create_array(
codecs: Iterable[Codec | dict[str, JSON]] | None = None,
dimension_names: Iterable[str] | None = None,
# v2 only
chunks: ChunkCoords | None = None,
chunks: ShapeLike | None = None,
dimension_separator: Literal[".", "/"] | None = None,
order: Literal["C", "F"] | None = None,
filters: list[dict[str, JSON]] | None = None,
Expand Down Expand Up @@ -891,7 +892,7 @@ def create_array(
self,
name: str,
*,
shape: ChunkCoords,
shape: ShapeLike,
dtype: npt.DTypeLike = "float64",
fill_value: Any | None = None,
attributes: dict[str, JSON] | None = None,
Expand All @@ -906,7 +907,7 @@ def create_array(
codecs: Iterable[Codec | dict[str, JSON]] | None = None,
dimension_names: Iterable[str] | None = None,
# v2 only
chunks: ChunkCoords | None = None,
chunks: ShapeLike | None = None,
dimension_separator: Literal[".", "/"] | None = None,
order: Literal["C", "F"] | None = None,
filters: list[dict[str, JSON]] | None = None,
Expand Down
4 changes: 2 additions & 2 deletions tests/v3/package_with_entrypoint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from numpy import ndarray

from zarr.abc.codec import ArrayBytesCodec, CodecInput, CodecPipeline
from zarr.abc.codec import ArrayBytesCodec, CodecInput, CodecOutput, CodecPipeline
from zarr.codecs import BytesCodec
from zarr.core.array_spec import ArraySpec
from zarr.core.buffer import Buffer, NDBuffer
Expand All @@ -15,7 +15,7 @@ class TestEntrypointCodec(ArrayBytesCodec):
async def encode(
self,
chunks_and_specs: Iterable[tuple[CodecInput | None, ArraySpec]],
) -> BytesLike | None:
) -> Iterable[CodecOutput | None]:
pass

async def decode(
Expand Down
60 changes: 34 additions & 26 deletions tests/v3/test_api.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import pathlib

import numpy as np
import pytest
from numpy.testing import assert_array_equal
from pytest_asyncio import fixture

import zarr
from zarr import Array, Group
from zarr.abc.store import Store
from zarr.api.synchronous import create, load, open, open_group, save, save_array, save_group
from zarr.store.memory import MemoryStore


def test_create_array(memory_store: Store) -> None:
Expand All @@ -30,7 +32,7 @@ def test_create_array(memory_store: Store) -> None:
assert z.chunks == (40,)


async def test_open_array(memory_store: Store) -> None:
async def test_open_array(memory_store: MemoryStore) -> None:
store = memory_store

# open array, create if doesn't exist
Expand All @@ -57,7 +59,7 @@ async def test_open_array(memory_store: Store) -> None:
open(store="doesnotexist", mode="r")


async def test_open_group(memory_store: Store) -> None:
async def test_open_group(memory_store: MemoryStore) -> None:
store = memory_store

# open group, create if doesn't exist
Expand Down Expand Up @@ -85,59 +87,65 @@ def test_save_errors() -> None:
save_group("data/group.zarr")
with pytest.raises(TypeError):
# no array provided
save_array("data/group.zarr")
save_array("data/group.zarr") # type: ignore[call-arg]
with pytest.raises(ValueError):
# no arrays provided
save("data/group.zarr")


@fixture
def tmppath(tmpdir):
return str(tmpdir / "example.zarr")


def test_open_with_mode_r(tmppath) -> None:
def test_open_with_mode_r(tmp_path: pathlib.Path) -> None:
# 'r' means read only (must exist)
with pytest.raises(FileNotFoundError):
zarr.open(store=tmppath, mode="r")
zarr.ones(store=tmppath, shape=(3, 3))
z2 = zarr.open(store=tmppath, mode="r")
zarr.open(store=tmp_path, mode="r")
zarr.ones(store=tmp_path, shape=(3, 3))
z2 = zarr.open(store=tmp_path, mode="r")
assert isinstance(z2, Array)
assert (z2[:] == 1).all()
with pytest.raises(ValueError):
z2[:] = 3


def test_open_with_mode_r_plus(tmppath) -> None:
def test_open_with_mode_r_plus(tmp_path: pathlib.Path) -> None:
# 'r+' means read/write (must exist)
with pytest.raises(FileNotFoundError):
zarr.open(store=tmppath, mode="r+")
zarr.ones(store=tmppath, shape=(3, 3))
z2 = zarr.open(store=tmppath, mode="r+")
zarr.open(store=tmp_path, mode="r+")
zarr.ones(store=tmp_path, shape=(3, 3))
z2 = zarr.open(store=tmp_path, mode="r+")
assert isinstance(z2, Array)
assert (z2[:] == 1).all()
z2[:] = 3


def test_open_with_mode_a(tmppath) -> None:
def test_open_with_mode_a(tmp_path: pathlib.Path) -> None:
# 'a' means read/write (create if doesn't exist)
zarr.open(store=tmppath, mode="a", shape=(3, 3))[...] = 1
z2 = zarr.open(store=tmppath, mode="a")
arr = zarr.open(store=tmp_path, mode="a", shape=(3, 3))
assert isinstance(arr, Array)
arr[...] = 1
z2 = zarr.open(store=tmp_path, mode="a")
assert isinstance(z2, Array)
assert (z2[:] == 1).all()
z2[:] = 3


def test_open_with_mode_w(tmppath) -> None:
def test_open_with_mode_w(tmp_path: pathlib.Path) -> None:
# 'w' means create (overwrite if exists);
zarr.open(store=tmppath, mode="w", shape=(3, 3))[...] = 3
z2 = zarr.open(store=tmppath, mode="w", shape=(3, 3))
arr = zarr.open(store=tmp_path, mode="w", shape=(3, 3))
assert isinstance(arr, Array)

arr[...] = 3
z2 = zarr.open(store=tmp_path, mode="w", shape=(3, 3))
assert isinstance(z2, Array)
assert not (z2[:] == 3).all()
z2[:] = 3


def test_open_with_mode_w_minus(tmppath) -> None:
def test_open_with_mode_w_minus(tmp_path: pathlib.Path) -> None:
# 'w-' means create (fail if exists)
zarr.open(store=tmppath, mode="w-", shape=(3, 3))[...] = 1
arr = zarr.open(store=tmp_path, mode="w-", shape=(3, 3))
assert isinstance(arr, Array)
arr[...] = 1
with pytest.raises(FileExistsError):
zarr.open(store=tmppath, mode="w-")
zarr.open(store=tmp_path, mode="w-")


# def test_lazy_loader():
Expand Down
26 changes: 16 additions & 10 deletions tests/v3/test_buffer.py