Skip to content
Draft
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
9 changes: 5 additions & 4 deletions tests/benchmarks/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import pytest

from tests.conftest import MEMORY_STORE
from zarr import create_array

indexers = (
Expand Down Expand Up @@ -60,7 +61,7 @@ def test_slice_indexing(
)


@pytest.mark.parametrize("store", ["memory"], indirect=["store"])
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("shards", morton_shards, ids=str)
def test_sharded_morton_indexing(
store: Store,
Expand Down Expand Up @@ -113,7 +114,7 @@ def read_with_cache_clear() -> None:
)


@pytest.mark.parametrize("store", ["memory"], indirect=["store"])
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("shards", large_morton_shards, ids=str)
def test_sharded_morton_indexing_large(
store: Store,
Expand Down Expand Up @@ -155,7 +156,7 @@ def read_with_cache_clear() -> None:
benchmark(read_with_cache_clear)


@pytest.mark.parametrize("store", ["memory"], indirect=["store"])
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("shards", large_morton_shards, ids=str)
def test_sharded_morton_single_chunk(
store: Store,
Expand Down Expand Up @@ -232,7 +233,7 @@ def compute_morton_order() -> None:
benchmark(compute_morton_order)


@pytest.mark.parametrize("store", ["memory"], indirect=["store"])
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("shards", large_morton_shards, ids=str)
def test_sharded_morton_write_single_chunk(
store: Store,
Expand Down
17 changes: 16 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ async def parse_store(
raise AssertionError


# Shared store parametrization lists, used with
# ``@pytest.mark.parametrize("store", ..., indirect=True)`` together with the ``store`` fixture
# below. These replace the many ad-hoc literal lists that were previously repeated across the
# test suite. Only use a constant where the literal list matches it exactly (including order),
# so that test ids are preserved; leave one-off lists (e.g. ``["memory", "memory_get_latency"]``)
# inline.
MEMORY_STORE = ["memory"]
LOCAL_STORE = ["local"]
LOCAL_MEMORY_STORES = ["local", "memory"]
ALL_STORES = ["local", "memory", "zip"]


@pytest.fixture(params=[str, pathlib.Path])
def path_type(request: pytest.FixtureRequest) -> Any:
return request.param
Expand Down Expand Up @@ -149,7 +161,10 @@ async def zip_store(tmpdir: LEGACY_PATH) -> ZipStore:
@pytest.fixture
async def store(request: pytest.FixtureRequest, tmpdir: LEGACY_PATH) -> Store:
param = request.param
return await parse_store(param, str(tmpdir))
result = await parse_store(param, str(tmpdir))
if not isinstance(result, Store):
raise TypeError(f"Wrong store class returned by test fixture! got {result} instead")
return result


@pytest.fixture
Expand Down
8 changes: 4 additions & 4 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import zarr.api.asynchronous
import zarr.api.synchronous
import zarr.core.group
from tests.conftest import ALL_STORES, MEMORY_STORE
from zarr import Array, Group
from zarr.api.synchronous import (
create,
Expand Down Expand Up @@ -169,7 +170,7 @@ async def test_array_like_creation(


# TODO: parametrize over everything this function takes
@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_create_array(store: Store, zarr_format: ZarrFormat) -> None:
attrs: dict[str, JSON] = {"foo": 100} # explicit type annotation to avoid mypy error
shape = (10, 10)
Expand Down Expand Up @@ -214,7 +215,6 @@ def test_write_empty_chunks_warns(write_empty_chunks: bool, zarr_format: ZarrFor
)


@pytest.mark.parametrize("zarr_format", [2, 3])
def test_open_array_respects_write_empty_chunks_config(zarr_format: ZarrFormat) -> None:
"""Test that zarr.open() respects write_empty_chunks config."""
store = MemoryStore()
Expand Down Expand Up @@ -319,7 +319,7 @@ def test_v2_and_v3_exist_at_same_path(store: Store) -> None:
zarr.open(store=store)


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
async def test_create_group(store: Store, zarr_format: ZarrFormat) -> None:
attrs = {"foo": 100}
path = "node"
Expand Down Expand Up @@ -369,7 +369,7 @@ async def test_open_group_unspecified_version(tmpdir: Path, zarr_format: ZarrFor
assert g2.metadata.zarr_format == zarr_format


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"])
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
@pytest.mark.parametrize("n_args", [10, 1, 0])
@pytest.mark.parametrize("n_kwargs", [10, 1, 0])
@pytest.mark.parametrize("path", [None, "some_path"])
Expand Down
62 changes: 27 additions & 35 deletions tests/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import zarr.api.asynchronous
import zarr.api.synchronous as sync_api
from tests.conftest import skip_object_dtype
from tests.conftest import ALL_STORES, LOCAL_STORE, MEMORY_STORE, skip_object_dtype
from zarr import Array, Group
from zarr.abc.store import Store
from zarr.codecs import (
Expand Down Expand Up @@ -88,8 +88,7 @@
from zarr.abc.codec import CodecJSON_V3


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
@pytest.mark.parametrize("overwrite", [True, False])
@pytest.mark.parametrize("extant_node", ["array", "group"])
def test_array_creation_existing_node(
Expand Down Expand Up @@ -139,8 +138,7 @@ def test_array_creation_existing_node(
)


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
async def test_create_creates_parents(
store: LocalStore | MemoryStore, zarr_format: ZarrFormat
) -> None:
Expand Down Expand Up @@ -179,8 +177,7 @@ async def test_create_creates_parents(
assert isinstance(g, AsyncGroup)


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
def test_array_name_properties_no_group(
store: LocalStore | MemoryStore, zarr_format: ZarrFormat
) -> None:
Expand All @@ -192,8 +189,7 @@ def test_array_name_properties_no_group(
assert arr.basename == ""


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
def test_array_name_properties_with_group(
store: LocalStore | MemoryStore, zarr_format: ZarrFormat
) -> None:
Expand All @@ -212,7 +208,7 @@ def test_array_name_properties_with_group(


@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("specify_fill_value", [True, False])
@pytest.mark.parametrize(
"zdtype", zdtype_examples, ids=tuple(str(type(v)) for v in zdtype_examples)
Expand Down Expand Up @@ -252,7 +248,7 @@ def test_array_fill_value_default(
assert type(arr.fill_value) is type(np.array([arr.fill_value], dtype=arr.dtype)[0])


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize(
("dtype_str", "fill_value"),
[("bool", True), ("uint8", 99), ("float32", -99.9), ("complex64", 3 + 4j)],
Expand All @@ -272,7 +268,7 @@ def test_array_v3_fill_value(store: MemoryStore, fill_value: int, dtype_str: str
assert arr.fill_value.dtype == arr.dtype


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
async def test_array_v3_nan_fill_value(store: MemoryStore) -> None:
shape = (10,)
arr = zarr.create_array(
Expand All @@ -291,8 +287,7 @@ async def test_array_v3_nan_fill_value(store: MemoryStore) -> None:
assert len([a async for a in store.list_prefix("/")]) == 0


@pytest.mark.parametrize("store", ["local"], indirect=["store"])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize("store", LOCAL_STORE, indirect=True)
async def test_serializable_async_array(
store: LocalStore | MemoryStore, zarr_format: ZarrFormat
) -> None:
Expand All @@ -309,8 +304,7 @@ async def test_serializable_async_array(
# TODO: uncomment the parts of this test that will be impacted by the config/prototype changes in flight


@pytest.mark.parametrize("store", ["local"], indirect=["store"])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize("store", LOCAL_STORE, indirect=True)
def test_serializable_sync_array(store: LocalStore, zarr_format: ZarrFormat) -> None:
expected = zarr.create_array(
store=store, shape=(100,), chunks=(10,), zarr_format=zarr_format, dtype="i4"
Expand All @@ -324,7 +318,7 @@ def test_serializable_sync_array(store: LocalStore, zarr_format: ZarrFormat) ->
np.testing.assert_array_equal(actual[:], expected[:])


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("zarr_format", [2, 3, "invalid"])
def test_storage_transformers(store: MemoryStore, zarr_format: ZarrFormat | str) -> None:
"""
Expand Down Expand Up @@ -484,7 +478,6 @@ async def test_nbytes_stored_async() -> None:
assert result == 902 # the size with all chunks filled.


@pytest.mark.parametrize("zarr_format", [2, 3])
def test_update_attrs(zarr_format: ZarrFormat) -> None:
# regression test for https://github.com/zarr-developers/zarr-python/issues/2328
store = MemoryStore()
Expand Down Expand Up @@ -666,7 +659,7 @@ async def test_info_complete_async(
)


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_resize_1d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
z = zarr.create(
shape=105, chunks=10, dtype="i4", fill_value=0, store=store, zarr_format=zarr_format
Expand Down Expand Up @@ -712,7 +705,7 @@ def test_resize_1d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
assert new_shape == result.shape


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_resize_2d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
z = zarr.create(
shape=(105, 105),
Expand Down Expand Up @@ -785,7 +778,7 @@ def test_resize_2d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
assert new_shape == result.shape


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_resize_growing_skips_chunk_enumeration(
store: MemoryStore, zarr_format: ZarrFormat
) -> None:
Expand Down Expand Up @@ -852,7 +845,7 @@ def test_resize_growing_skips_chunk_enumeration(
np.testing.assert_array_equal(np.zeros((10, 5), dtype="i4"), z2[10:, :])


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_append_1d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
a = np.arange(105)
z = zarr.create(shape=a.shape, chunks=10, dtype=a.dtype, store=store, zarr_format=zarr_format)
Expand Down Expand Up @@ -881,7 +874,7 @@ def test_append_1d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
np.testing.assert_array_equal(f, z[:])


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_append_2d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
a = np.arange(105 * 105, dtype="i4").reshape((105, 105))
z = zarr.create(
Expand All @@ -904,7 +897,7 @@ def test_append_2d(store: MemoryStore, zarr_format: ZarrFormat) -> None:
np.testing.assert_array_equal(e, actual)


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_append_2d_axis(store: MemoryStore, zarr_format: ZarrFormat) -> None:
a = np.arange(105 * 105, dtype="i4").reshape((105, 105))
z = zarr.create(
Expand All @@ -925,7 +918,7 @@ def test_append_2d_axis(store: MemoryStore, zarr_format: ZarrFormat) -> None:
np.testing.assert_array_equal(e, z[:])


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
def test_append_bad_shape(store: MemoryStore, zarr_format: ZarrFormat) -> None:
a = np.arange(100)
z = zarr.create(shape=a.shape, chunks=10, dtype=a.dtype, store=store, zarr_format=zarr_format)
Expand All @@ -935,7 +928,7 @@ def test_append_bad_shape(store: MemoryStore, zarr_format: ZarrFormat) -> None:
z.append(b)


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("write_empty_chunks", [True, False])
@pytest.mark.parametrize("fill_value", [0, 5])
def test_write_empty_chunks_behavior(
Expand Down Expand Up @@ -975,7 +968,7 @@ def test_write_empty_chunks_behavior(
assert arr._nshards_initialized == arr._nshards


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.parametrize("fill_value", [0.0, -0.0])
@pytest.mark.parametrize("dtype", ["f4", "f2"])
def test_write_empty_chunks_negative_zero(
Expand Down Expand Up @@ -1153,7 +1146,7 @@ def test_chunks_and_shards() -> None:
assert arr_v2.shards is None


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
@pytest.mark.parametrize(
("dtype", "fill_value_expected"), [("<U4", ""), ("<S4", b""), ("i", 0), ("f", 0.0)]
Expand All @@ -1163,7 +1156,7 @@ def test_default_fill_value(dtype: str, fill_value_expected: object, store: Stor
assert a.fill_value == fill_value_expected


@pytest.mark.parametrize("store", ["memory"], indirect=True)
@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True)
class TestCreateArray:
@staticmethod
def test_chunks_and_shards(store: Store) -> None:
Expand Down Expand Up @@ -1694,7 +1687,6 @@ def test_default_endianness(


@pytest.mark.parametrize("value", [1, 1.4, "a", b"a", np.array(1)])
@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
def test_scalar_array(value: Any, zarr_format: ZarrFormat) -> None:
arr = zarr.array(value, zarr_format=zarr_format)
Expand All @@ -1704,7 +1696,7 @@ def test_scalar_array(value: Any, zarr_format: ZarrFormat) -> None:
assert isinstance(arr[()], NDArrayLikeOrScalar)


@pytest.mark.parametrize("store", ["local"], indirect=True)
@pytest.mark.parametrize("store", LOCAL_STORE, indirect=True)
@pytest.mark.parametrize("store2", ["local"], indirect=["store2"])
@pytest.mark.parametrize("src_format", [2, 3])
@pytest.mark.parametrize("new_format", [2, 3, None])
Expand Down Expand Up @@ -1751,7 +1743,7 @@ async def test_creation_from_other_zarr_format(
np.testing.assert_array_equal(result2[:], src[:])


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=True)
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
@pytest.mark.parametrize("store2", ["local", "memory", "zip"], indirect=["store2"])
@pytest.mark.parametrize("src_chunks", [(40, 10), (11, 50)])
@pytest.mark.parametrize("new_chunks", [(40, 10), (11, 50)])
Expand Down Expand Up @@ -1794,7 +1786,7 @@ async def test_from_array(
assert result.chunks == new_chunks


@pytest.mark.parametrize("store", ["local"], indirect=True)
@pytest.mark.parametrize("store", LOCAL_STORE, indirect=True)
@pytest.mark.parametrize("chunks", ["keep", "auto"])
@pytest.mark.parametrize("write_data", [True, False])
@pytest.mark.parametrize(
Expand Down Expand Up @@ -1915,7 +1907,7 @@ def _index_array(arr: AnyArray, index: Any) -> Any:
),
],
)
@pytest.mark.parametrize("store", ["local"], indirect=True)
@pytest.mark.parametrize("store", LOCAL_STORE, indirect=True)
@pytest.mark.parametrize("shards", [None, (20,)])
def test_multiprocessing(
store: Store, method: Literal["fork", "spawn", "forkserver"], shards: tuple[int, ...] | None
Expand Down Expand Up @@ -1972,7 +1964,7 @@ async def test_sharding_coordinate_selection() -> None:
assert (result == np.array([[12, 13, 14, 15], [16, 17, 18, 19]])).all()


@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"])
@pytest.mark.parametrize("store", ALL_STORES, indirect=True)
def test_array_repr(store: Store) -> None:
shape = (2, 3, 4)
dtype = "uint8"
Expand Down
1 change: 0 additions & 1 deletion tests/test_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from zarr.types import AnyArray


@pytest.mark.parametrize("zarr_format", [2, 3])
@pytest.mark.parametrize(
"data", [{"inf": np.inf, "-inf": -np.inf, "nan": np.nan}, {"a": 3, "c": 4}]
)
Expand Down
Loading
Loading