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
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,6 @@ filterwarnings = [
"ignore:Exception ignored ((on calling weakref callback)|(in[\\s\\S]*Session was never entered)):pytest.PytestUnraisableExceptionWarning",
]
markers = [
"asyncio: mark test as asyncio test",
"gpu: mark a test as requiring CuPy and GPU",
"s3: mark a test as requiring a (mock) S3 backend via moto",
"slow_hypothesis: slow hypothesis tests",
Expand Down
29 changes: 14 additions & 15 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@
from contextlib import AbstractContextManager
from typing import Any, Literal

from _pytest.compat import LEGACY_PATH

from zarr.abc.codec import Codec
from zarr.core.array import CompressorsLike, FiltersLike, SerializerLike, ShardsLike
from zarr.core.chunk_key_encodings import (
Expand Down Expand Up @@ -121,14 +119,14 @@ def path_type(request: pytest.FixtureRequest) -> Any:

# todo: harmonize this with local_store fixture
@pytest.fixture
async def store_path(tmpdir: LEGACY_PATH) -> StorePath:
store = await LocalStore.open(str(tmpdir))
async def store_path(tmp_path: pathlib.Path) -> StorePath:
store = await LocalStore.open(str(tmp_path))
return StorePath(store)


@pytest.fixture
async def local_store(tmpdir: LEGACY_PATH) -> LocalStore:
return await LocalStore.open(str(tmpdir))
async def local_store(tmp_path: pathlib.Path) -> LocalStore:
return await LocalStore.open(str(tmp_path))


@pytest.fixture
Expand All @@ -142,26 +140,27 @@ async def memory_store() -> MemoryStore:


@pytest.fixture
async def zip_store(tmpdir: LEGACY_PATH) -> ZipStore:
return await ZipStore.open(str(tmpdir / "zarr.zip"), mode="w")
async def zip_store(tmp_path: pathlib.Path) -> ZipStore:
return await ZipStore.open(str(tmp_path / "zarr.zip"), mode="w")


@pytest.fixture
async def store(request: pytest.FixtureRequest, tmpdir: LEGACY_PATH) -> Store:
async def store(request: pytest.FixtureRequest, tmp_path: pathlib.Path) -> Store:
param = request.param
return await parse_store(param, str(tmpdir))
return await parse_store(param, str(tmp_path))


@pytest.fixture
async def store2(request: pytest.FixtureRequest, tmpdir: LEGACY_PATH) -> Store:
async def store2(request: pytest.FixtureRequest, tmp_path: pathlib.Path) -> Store:
"""Fixture to create a second store for testing copy operations between stores"""
param = request.param
store2_path = tmpdir.mkdir("store2")
store2_path = tmp_path / "store2"
store2_path.mkdir()
return await parse_store(param, str(store2_path))


@pytest.fixture(params=["local", "memory", "zip"])
def sync_store(request: pytest.FixtureRequest, tmp_path: LEGACY_PATH) -> Store:
def sync_store(request: pytest.FixtureRequest, tmp_path: pathlib.Path) -> Store:
result = sync(parse_store(request.param, str(tmp_path)))
if not isinstance(result, Store):
raise TypeError(f"Wrong store class returned by test fixture! got {result} instead")
Expand All @@ -176,10 +175,10 @@ class AsyncGroupRequest:


@pytest.fixture
async def async_group(request: pytest.FixtureRequest, tmpdir: LEGACY_PATH) -> AsyncGroup:
async def async_group(request: pytest.FixtureRequest, tmp_path: pathlib.Path) -> AsyncGroup:
param: AsyncGroupRequest = request.param

store = await parse_store(param.store, str(tmpdir))
store = await parse_store(param.store, str(tmp_path))
return await AsyncGroup.from_store(
store,
attributes=param.attributes,
Expand Down
7 changes: 3 additions & 4 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ def test_open_array_rectilinear_chunks(tmp_path: Path) -> None:
assert z.read_chunk_sizes == ((3, 3, 4), (5, 5))


@pytest.mark.asyncio
async def test_async_array_open_array_not_found() -> None:
"""Test that AsyncArray.open raises ArrayNotFoundError when array doesn't exist"""
store = MemoryStore()
Expand Down Expand Up @@ -352,16 +351,16 @@ async def test_open_group(memory_store: MemoryStore) -> None:


@pytest.mark.parametrize("zarr_format", [None, 2, 3])
async def test_open_group_unspecified_version(tmpdir: Path, zarr_format: ZarrFormat) -> None:
async def test_open_group_unspecified_version(tmp_path: Path, zarr_format: ZarrFormat) -> None:
"""Regression test for https://github.com/zarr-developers/zarr-python/issues/2175"""

# create a group with specified zarr format (could be 2, 3, or None)
_ = await zarr.api.asynchronous.open_group(
store=str(tmpdir), mode="w", zarr_format=zarr_format, attributes={"foo": "bar"}
store=str(tmp_path), mode="w", zarr_format=zarr_format, attributes={"foo": "bar"}
)

# now open that group without specifying the format
g2 = await zarr.api.asynchronous.open_group(store=str(tmpdir), mode="r")
g2 = await zarr.api.asynchronous.open_group(store=str(tmp_path), mode="r")

assert g2.attrs == {"foo": "bar"}

Expand Down
10 changes: 6 additions & 4 deletions tests/test_api/test_synchronous.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_docstrings_match(callable_name: str) -> None:
@pytest.mark.parametrize(
("parameter_name", "array_creation_routines"),
[
(
pytest.param(
("store", "path"),
(
asynchronous.create_array,
Expand All @@ -54,8 +54,9 @@ def test_docstrings_match(callable_name: str) -> None:
zarr.AsyncGroup.create_array,
zarr.Group.create_array,
),
id="store-path-create_array_group",
),
(
pytest.param(
(
"store",
"path",
Expand All @@ -65,8 +66,9 @@ def test_docstrings_match(callable_name: str) -> None:
synchronous.create,
zarr.Group.create,
),
id="store-path-create",
),
(
pytest.param(
(
(
"filters",
Expand All @@ -87,9 +89,9 @@ def test_docstrings_match(callable_name: str) -> None:
zarr.AsyncGroup.create_array,
zarr.Group.create_array,
),
id="encoding-params-create_and_array",
),
],
ids=str,
)
def test_docstring_consistent_parameters(
parameter_name: str, array_creation_routines: tuple[Callable[[Any], Any], ...]
Expand Down
5 changes: 0 additions & 5 deletions tests/test_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def test_nd_array_like(xp: types.ModuleType) -> None:
assert isinstance(ary, NDArrayLike)


@pytest.mark.asyncio
async def test_async_array_prototype() -> None:
"""Test the use of a custom buffer prototype"""

Expand Down Expand Up @@ -73,7 +72,6 @@ async def test_async_array_prototype() -> None:


@gpu_test
@pytest.mark.asyncio
async def test_async_array_gpu_prototype() -> None:
"""Test the use of the GPU buffer prototype"""

Expand All @@ -97,7 +95,6 @@ async def test_async_array_gpu_prototype() -> None:
assert cp.array_equal(expect, got)


@pytest.mark.asyncio
async def test_codecs_use_of_prototype() -> None:
expect = np.zeros((10, 10), dtype="uint16", order="F")
a = await zarr.api.asynchronous.create_array(
Expand Down Expand Up @@ -126,7 +123,6 @@ async def test_codecs_use_of_prototype() -> None:


@gpu_test
@pytest.mark.asyncio
async def test_codecs_use_of_gpu_prototype() -> None:
expect = cp.zeros((10, 10), dtype="uint16", order="F")
a = await zarr.api.asynchronous.create_array(
Expand Down Expand Up @@ -155,7 +151,6 @@ async def test_codecs_use_of_gpu_prototype() -> None:


@gpu_test
@pytest.mark.asyncio
async def test_sharding_use_of_gpu_prototype() -> None:
with zarr.config.enable_gpu():
expect = cp.zeros((10, 10), dtype="uint16", order="F")
Expand Down
20 changes: 7 additions & 13 deletions tests/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

from __future__ import annotations

import os
from collections import defaultdict
from pathlib import Path
from typing import TYPE_CHECKING, Any
Expand Down Expand Up @@ -82,7 +81,9 @@ def _session_params(root: Path) -> list[Any]:


@pytest.fixture
def docs_s3_backend(moto_server: str) -> Generator[None, None, None]:
def docs_s3_backend(
moto_server: str, monkeypatch: pytest.MonkeyPatch
) -> Generator[None, None, None]:
"""Point docs S3 examples at the shared moto server (tests/conftest.py) via a
process-wide AWS_ENDPOINT_URL, so a block can use a bare s3:// URL with no
storage_options (see spike in the design notes). The server lifecycle belongs to the
Expand All @@ -92,8 +93,7 @@ def docs_s3_backend(moto_server: str) -> Generator[None, None, None]:
botocore = pytest.importorskip("botocore")
requests = pytest.importorskip("requests")

prev_endpoint = os.environ.get("AWS_ENDPOINT_URL")
os.environ["AWS_ENDPOINT_URL"] = moto_server
monkeypatch.setenv("AWS_ENDPOINT_URL", moto_server)

session = botocore.session.Session()
client = session.create_client("s3", endpoint_url=moto_server, region_name="us-east-1")
Expand All @@ -103,15 +103,9 @@ def docs_s3_backend(moto_server: str) -> Generator[None, None, None]:
try:
yield
finally:
# Reset moto state and restore AWS_ENDPOINT_URL; the shared server keeps running
# (the moto_server fixture stops it at session end).
try:
requests.post(f"{moto_server}moto-api/reset")
finally:
if prev_endpoint is None:
os.environ.pop("AWS_ENDPOINT_URL", None)
else:
os.environ["AWS_ENDPOINT_URL"] = prev_endpoint
# Reset moto state; AWS_ENDPOINT_URL is restored automatically by monkeypatch.
# The shared server keeps running (the moto_server fixture stops it at session end).
requests.post(f"{moto_server}moto-api/reset")


def test_markers_attribute_is_parsed(tmp_path: Path) -> None:
Expand Down
7 changes: 3 additions & 4 deletions tests/test_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,16 @@
from .conftest import meta_from_array, parse_store

if TYPE_CHECKING:
import pathlib
from collections.abc import Callable

from _pytest.compat import LEGACY_PATH

from zarr.core.buffer.core import Buffer
from zarr.core.common import JSON, ZarrFormat


@pytest.fixture(params=["local", "memory", "zip"])
async def store(request: pytest.FixtureRequest, tmpdir: LEGACY_PATH) -> Store:
result = await parse_store(request.param, str(tmpdir))
async def store(request: pytest.FixtureRequest, tmp_path: pathlib.Path) -> Store:
result = await parse_store(request.param, str(tmp_path))
if not isinstance(result, Store):
raise TypeError(f"Wrong store class returned by test fixture! got {result} instead")
return result
Expand Down
4 changes: 0 additions & 4 deletions tests/test_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ def test_array_creates_implicit_groups(array):
# this decorator removes timeout; not ideal but it should avoid intermittent CI failures


@pytest.mark.asyncio
@settings(deadline=None)
@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
@given(data=st.data())
Expand All @@ -146,7 +145,6 @@ async def test_basic_indexing(data: st.DataObject) -> None:
# TODO test async setitem?


@pytest.mark.asyncio
@settings(deadline=None)
@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
@given(data=st.data())
Expand All @@ -156,7 +154,6 @@ async def test_basic_indexing_complex_rectilinear(data: st.DataObject) -> None:
assert_array_equal(nparray[indexer], zarray[indexer])


@pytest.mark.asyncio
@given(data=st.data())
@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
async def test_oindex(data: st.DataObject) -> None:
Expand Down Expand Up @@ -193,7 +190,6 @@ async def test_oindex(data: st.DataObject) -> None:
# note: async oindex setitem not yet implemented


@pytest.mark.asyncio
@given(data=st.data())
@pytest.mark.filterwarnings("ignore::zarr.core.dtype.common.UnstableSpecificationWarning")
async def test_vindex(data: st.DataObject) -> None:
Expand Down
9 changes: 4 additions & 5 deletions tests/test_store/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from typing import Any, Literal

import pytest
from _pytest.compat import LEGACY_PATH

import zarr
from zarr import Group
Expand Down Expand Up @@ -163,18 +162,18 @@ async def test_make_store_path_none(path: str) -> None:
@pytest.mark.parametrize("store_type", [str, Path])
@pytest.mark.parametrize("mode", ["r", "w"])
async def test_make_store_path_local(
tmpdir: LEGACY_PATH,
tmp_path: Path,
store_type: type[str] | type[Path] | type[LocalStore],
path: str,
mode: AccessModeLiteral,
) -> None:
"""
Test the various ways of invoking make_store_path that create a LocalStore
"""
store_like = store_type(str(tmpdir))
store_like = store_type(str(tmp_path))
store_path = await make_store_path(store_like, path=path, mode=mode)
assert isinstance(store_path.store, LocalStore)
assert Path(store_path.store.root) == Path(tmpdir)
assert Path(store_path.store.root) == Path(tmp_path)
assert store_path.path == normalize_path(path)
assert store_path.read_only == (mode == "r")

Expand Down Expand Up @@ -336,7 +335,7 @@ def test_relativize_path_invalid() -> None:
_relativize_path(path="a/b/c", prefix="b")


def test_different_open_mode(tmp_path: LEGACY_PATH) -> None:
def test_different_open_mode(tmp_path: Path) -> None:
# Test with a store that implements .with_read_only()
store = MemoryStore()
zarr.create((100,), store=store, zarr_format=2, path="a")
Expand Down
4 changes: 2 additions & 2 deletions tests/test_store/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ async def set(self, store: LocalStore, key: str, value: Buffer) -> None:
(store.root / key).write_bytes(value.to_bytes())

@pytest.fixture
def store_kwargs(self, tmpdir: str) -> dict[str, str]:
return {"root": str(tmpdir)}
def store_kwargs(self, tmp_path: pathlib.Path) -> dict[str, str]:
return {"root": str(tmp_path)}

def test_store_repr(self, store: LocalStore) -> None:
assert str(store) == f"file://{store.root.as_posix()}"
Expand Down
Loading