From 8da13336dfa60c2b4412097bc5e58488aebbb66c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 31 May 2026 19:28:07 +0200 Subject: [PATCH 1/2] chore(deps): bump the actions group across 1 directory with 8 updates (#176) Bumps the actions group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) | `0.9.5` | `0.9.6` | | [codecov/codecov-action](https://github.com/codecov/codecov-action) | `6.0.0` | `6.0.1` | | [github/issue-metrics](https://github.com/github/issue-metrics) | `4.2.2` | `4.2.7` | | [j178/prek-action](https://github.com/j178/prek-action) | `2.0.3` | `2.0.4` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` | | [actions/download-artifact](https://github.com/actions/download-artifact) | `7.0.0` | `8.0.1` | | [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` | | [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.3` | `0.5.6` | Updates `prefix-dev/setup-pixi` from 0.9.5 to 0.9.6 - [Release notes](https://github.com/prefix-dev/setup-pixi/releases) - [Commits](https://github.com/prefix-dev/setup-pixi/compare/1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0...5185adfbffb4bd703da3010310260805d89ebb11) Updates `codecov/codecov-action` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/57e3a136b779b570ffcdbf80b3bdc90e7fab3de2...e79a6962e0d4c0c17b229090214935d2e33f8354) Updates `github/issue-metrics` from 4.2.2 to 4.2.7 - [Release notes](https://github.com/github/issue-metrics/releases) - [Commits](https://github.com/github/issue-metrics/compare/c9e9838147fd355dace335ba787f01b6641a400a...1e38d5e62363e14db8019ed7d106b9855bdba6cc) Updates `j178/prek-action` from 2.0.3 to 2.0.4 - [Release notes](https://github.com/j178/prek-action/releases) - [Commits](https://github.com/j178/prek-action/compare/6ad80277337ad479fe43bd70701c3f7f8aa74db3...bdca6f102f98e2b4c7029491a53dfd366469e33d) Updates `actions/upload-artifact` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v7...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) Updates `actions/download-artifact` from 7.0.0 to 8.0.1 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v7...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c) Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.13.0...cef221092ed1bacb1cc03d23a2d87d1d172e277b) Updates `zizmorcore/zizmor-action` from 0.5.3 to 0.5.6 - [Release notes](https://github.com/zizmorcore/zizmor-action/releases) - [Commits](https://github.com/zizmorcore/zizmor-action/compare/b1d7e1fb5de872772f31590499237e7cce841e8e...5f14fd08f7cf1cb1609c1e344975f152c7ee938d) --- updated-dependencies: - dependency-name: prefix-dev/setup-pixi dependency-version: 0.9.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: codecov/codecov-action dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: github/issue-metrics dependency-version: 4.2.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: j178/prek-action dependency-version: 2.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: actions/upload-artifact dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: actions/download-artifact dependency-version: 8.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.14.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: zizmorcore/zizmor-action dependency-version: 0.5.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/downstream.yml | 2 +- .github/workflows/gpu_test.yml | 2 +- .github/workflows/hypothesis.yaml | 2 +- .github/workflows/issue-metrics.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 4 ++-- .github/workflows/zarr-metadata-release.yml | 12 ++++++------ .github/workflows/zizmor.yml | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index 74026233c4..3eb6898895 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -34,7 +34,7 @@ jobs: persist-credentials: false - name: Set up pixi - uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5 + uses: prefix-dev/setup-pixi@5185adfbffb4bd703da3010310260805d89ebb11 # v0.9.6 with: manifest-path: xarray/pixi.toml diff --git a/.github/workflows/gpu_test.yml b/.github/workflows/gpu_test.yml index 403441b306..333769cb9e 100644 --- a/.github/workflows/gpu_test.yml +++ b/.github/workflows/gpu_test.yml @@ -76,7 +76,7 @@ jobs: hatch env run --env "$HATCH_ENV" run-coverage - name: Upload coverage - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} flags: gpu diff --git a/.github/workflows/hypothesis.yaml b/.github/workflows/hypothesis.yaml index 4f9467be7d..a456b2aa0a 100644 --- a/.github/workflows/hypothesis.yaml +++ b/.github/workflows/hypothesis.yaml @@ -93,7 +93,7 @@ jobs: key: cache-hypothesis-${{ runner.os }}-${{ github.run_id }} - name: Upload coverage - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} flags: tests diff --git a/.github/workflows/issue-metrics.yml b/.github/workflows/issue-metrics.yml index 14fba5b9ec..510849ef3e 100644 --- a/.github/workflows/issue-metrics.yml +++ b/.github/workflows/issue-metrics.yml @@ -33,7 +33,7 @@ jobs: echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" - name: Run issue-metrics tool - uses: github/issue-metrics@c9e9838147fd355dace335ba787f01b6641a400a # v4.2.2 + uses: github/issue-metrics@1e38d5e62363e14db8019ed7d106b9855bdba6cc # v4.2.7 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} SEARCH_QUERY: 'repo:zarr-developers/zarr-python is:issue created:${{ env.last_month }} -reason:"not planned"' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 768e660ec2..fec211b4dd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,4 +30,4 @@ jobs: uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: enable-cache: true - - uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2.0.3 + - uses: j178/prek-action@bdca6f102f98e2b4c7029491a53dfd366469e33d # v2.0.4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03143d3e5b..62e571856b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,7 +78,7 @@ jobs: hatch env run --env "$HATCH_ENV" run-coverage - name: Upload coverage if: ${{ matrix.dependency-set == 'optional' && matrix.os == 'ubuntu-latest' }} - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} flags: tests @@ -125,7 +125,7 @@ jobs: run: | hatch env run --env "$HATCH_ENV" run-coverage - name: Upload coverage - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} flags: tests diff --git a/.github/workflows/zarr-metadata-release.yml b/.github/workflows/zarr-metadata-release.yml index 809d502f16..9639fcfdd3 100644 --- a/.github/workflows/zarr-metadata-release.yml +++ b/.github/workflows/zarr-metadata-release.yml @@ -35,7 +35,7 @@ jobs: - name: Build run: hatch build - - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: zarr-metadata-dist path: packages/zarr-metadata/dist @@ -45,7 +45,7 @@ jobs: needs: [build] runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: zarr-metadata-dist path: dist @@ -76,7 +76,7 @@ jobs: id-token: write # required for OIDC trusted publishing attestations: write # required for artifact attestations steps: - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: zarr-metadata-dist path: dist @@ -87,7 +87,7 @@ jobs: subject-path: dist/* - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 upload_testpypi: name: Upload to TestPyPI @@ -101,7 +101,7 @@ jobs: id-token: write attestations: write steps: - - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: zarr-metadata-dist path: dist @@ -112,6 +112,6 @@ jobs: subject-path: dist/* - name: Publish package to TestPyPI - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: repository-url: https://test.pypi.org/legacy/ diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index da19f22421..7ac4fe5d0e 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -32,4 +32,4 @@ jobs: persist-credentials: false - name: Run zizmor - uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 + uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 From dc2a7b0c7be72b8a3b064feff8c21a9870ed52f9 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Tue, 16 Jun 2026 13:19:50 +0200 Subject: [PATCH 2/2] test: reduce redundancy in store/zarr_format parametrization and codec sync tests Section C of the test-suite audit (redundancy / simplification): - Add shared store-parametrization constants to tests/conftest.py (MEMORY_STORE, LOCAL_STORE, LOCAL_MEMORY_STORES, ALL_STORES) and replace the repeated inline literal lists at ~136 call sites. One-off lists (e.g. ["memory", "memory_get_latency"], reversed orderings) are left inline. Normalize indirect=["store"] to indirect=True for single-store parametrizations. - Remove the module-level `store` fixture in tests/test_group.py that shadowed the conftest `store` fixture (source of the pytest 9.1.0 "duplicate parametrization" collision). Add explicit @pytest.mark.parametrize("store", ALL_STORES, indirect=True) to the tests that relied on its default params so store coverage is preserved (collection count unchanged at 538). Move the isinstance(result, Store) guard into the conftest `store` fixture. Fix test_create_rooted_hierarchy_invalid, which previously relied on the fixture *function object* being in scope as a name. - Drop 24 redundant @pytest.mark.parametrize("zarr_format", [2, 3]) decorators where the test already receives zarr_format from the conftest fixture (params=(2, 3)). Variants like [None, 2, 3], [3], etc. are kept. - Collapse the byte-identical per-codec sync tests into two parametrized tests in tests/test_codecs/test_codecs.py (test_codec_supports_sync over all codec instances, and test_bytes_to_bytes_codec_sync_roundtrip over the bytes->bytes codecs). Delete the per-file duplicates (test_crc32c.py removed entirely). Structurally distinct roundtrips (BytesCodec/endian, TransposeCodec) are kept. Follow-up (out of scope here): shared array-construction helpers. Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/benchmarks/test_indexing.py | 9 ++- tests/conftest.py | 17 ++++- tests/test_api.py | 8 +- tests/test_array.py | 62 +++++++-------- tests/test_attributes.py | 1 - tests/test_cli/test_migrate_v3.py | 2 - tests/test_codecs/test_blosc.py | 27 +------ tests/test_codecs/test_codecs.py | 74 ++++++++++++++++-- tests/test_codecs/test_crc32c.py | 33 -------- tests/test_codecs/test_endian.py | 10 +-- tests/test_codecs/test_gzip.py | 31 +------- tests/test_codecs/test_sharding.py | 46 ++++++------ tests/test_codecs/test_transpose.py | 12 +-- tests/test_codecs/test_vlen.py | 11 +-- tests/test_codecs/test_zstd.py | 31 +------- tests/test_config.py | 13 ++-- tests/test_group.py | 96 ++++++++++++++++-------- tests/test_indexing.py | 6 +- tests/test_metadata/test_consolidated.py | 3 - tests/test_store/test_core.py | 2 - tests/test_store/test_logging.py | 5 +- tests/test_store/test_memory.py | 2 - tests/test_store/test_wrapper.py | 5 +- tests/test_v2.py | 3 +- 24 files changed, 235 insertions(+), 274 deletions(-) delete mode 100644 tests/test_codecs/test_crc32c.py diff --git a/tests/benchmarks/test_indexing.py b/tests/benchmarks/test_indexing.py index 385a85b5b5..82679d308d 100644 --- a/tests/benchmarks/test_indexing.py +++ b/tests/benchmarks/test_indexing.py @@ -11,6 +11,7 @@ import pytest +from tests.conftest import MEMORY_STORE from zarr import create_array indexers = ( @@ -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, @@ -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, @@ -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, @@ -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, diff --git a/tests/conftest.py b/tests/conftest.py index 207fba0a44..4955b7dd3d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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 @@ -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 diff --git a/tests/test_api.py b/tests/test_api.py index 788519969d..2bf9a56c44 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -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, @@ -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) @@ -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() @@ -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" @@ -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"]) diff --git a/tests/test_array.py b/tests/test_array.py index 0d6d2d5906..0f5f9ff609 100644 --- a/tests/test_array.py +++ b/tests/test_array.py @@ -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 ( @@ -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( @@ -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: @@ -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: @@ -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: @@ -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) @@ -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)], @@ -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( @@ -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: @@ -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" @@ -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: """ @@ -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() @@ -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 @@ -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), @@ -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: @@ -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) @@ -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( @@ -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( @@ -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) @@ -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( @@ -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( @@ -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"), [(" None: @@ -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) @@ -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]) @@ -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)]) @@ -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( @@ -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 @@ -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" diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 269704d2a0..c291ad9a68 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -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}] ) diff --git a/tests/test_cli/test_migrate_v3.py b/tests/test_cli/test_migrate_v3.py index 7213aada12..b985cd0af9 100644 --- a/tests/test_cli/test_migrate_v3.py +++ b/tests/test_cli/test_migrate_v3.py @@ -552,7 +552,6 @@ def test_migrate_incorrect_compressor(local_store: LocalStore) -> None: ) -@pytest.mark.parametrize("zarr_format", [2, 3]) def test_remove_metadata_fails_without_force( local_store: LocalStore, zarr_format: ZarrFormat ) -> None: @@ -566,7 +565,6 @@ def test_remove_metadata_fails_without_force( assert str(result.exception).startswith(f"Cannot remove v{zarr_format} metadata at file") -@pytest.mark.parametrize("zarr_format", [2, 3]) def test_remove_metadata_succeeds_with_force( local_store: LocalStore, zarr_format: ZarrFormat, expected_paths_no_metadata: list[Path] ) -> None: diff --git a/tests/test_codecs/test_blosc.py b/tests/test_codecs/test_blosc.py index f5f13f4d05..f229eb256a 100644 --- a/tests/test_codecs/test_blosc.py +++ b/tests/test_codecs/test_blosc.py @@ -9,7 +9,6 @@ from packaging.version import Version import zarr -from zarr.abc.codec import SupportsSyncCodec from zarr.codecs import BloscCodec from zarr.codecs.blosc import ( BLOSC_CNAME, @@ -21,7 +20,7 @@ ) from zarr.core.array_spec import ArrayConfig, ArraySpec from zarr.core.buffer import default_buffer_prototype -from zarr.core.dtype import UInt16, get_data_type_from_native_dtype +from zarr.core.dtype import UInt16 from zarr.storage import MemoryStore, StorePath @@ -133,30 +132,6 @@ async def test_typesize() -> None: assert size == expected_size, msg -def test_blosc_codec_supports_sync() -> None: - assert isinstance(BloscCodec(), SupportsSyncCodec) - - -def test_blosc_codec_sync_roundtrip() -> None: - codec = BloscCodec(typesize=8) - arr = np.arange(100, dtype="float64") - zdtype = get_data_type_from_native_dtype(arr.dtype) - spec = ArraySpec( - shape=arr.shape, - dtype=zdtype, - fill_value=zdtype.cast_scalar(0), - config=ArrayConfig(order="C", write_empty_chunks=True), - prototype=default_buffer_prototype(), - ) - buf = default_buffer_prototype().buffer.from_array_like(arr.view("B")) - - encoded = codec._encode_sync(buf, spec) - assert encoded is not None - decoded = codec._decode_sync(encoded, spec) - result = np.frombuffer(decoded.as_numpy_array(), dtype="float64") - np.testing.assert_array_equal(arr, result) - - @pytest.mark.parametrize("cname", BLOSC_CNAME) def test_blosc_codec_accepts_all_cnames(cname: BloscCnameLiteral) -> None: """ diff --git a/tests/test_codecs/test_codecs.py b/tests/test_codecs/test_codecs.py index 6e3e3f6d28..4819b757c7 100644 --- a/tests/test_codecs/test_codecs.py +++ b/tests/test_codecs/test_codecs.py @@ -10,14 +10,22 @@ import zarr import zarr.api import zarr.api.asynchronous +from tests.conftest import LOCAL_MEMORY_STORES from zarr import Array, AsyncArray, config +from zarr.abc.codec import SupportsSyncCodec from zarr.codecs import ( + BloscCodec, BytesCodec, GzipCodec, ShardingCodec, TransposeCodec, + ZstdCodec, ) +from zarr.codecs.crc32c_ import Crc32cCodec +from zarr.codecs.vlen_utf8 import VLenBytesCodec, VLenUTF8Codec +from zarr.core.array_spec import ArrayConfig, ArraySpec from zarr.core.buffer import default_buffer_prototype +from zarr.core.dtype import get_data_type_from_native_dtype from zarr.core.indexing import BasicSelection, decode_morton, morton_order_iter from zarr.core.metadata.v3 import ArrayV3Metadata from zarr.dtype import UInt8 @@ -27,7 +35,7 @@ if TYPE_CHECKING: from zarr.abc.codec import Codec from zarr.abc.store import Store - from zarr.core.buffer.core import NDArrayLikeOrScalar + from zarr.core.buffer.core import Buffer, NDArrayLikeOrScalar from zarr.core.common import MemoryOrder from zarr.types import AnyAsyncArray @@ -65,7 +73,7 @@ def test_sharding_pickle() -> None: """ -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("input_order", ["F", "C"]) @pytest.mark.parametrize("store_order", ["F", "C"]) @pytest.mark.parametrize("runtime_write_order", ["F", "C"]) @@ -115,7 +123,7 @@ async def test_order( assert read_data.flags["C_CONTIGUOUS"] -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("input_order", ["F", "C"]) @pytest.mark.parametrize("runtime_write_order", ["F", "C"]) @pytest.mark.parametrize("runtime_read_order", ["F", "C"]) @@ -157,7 +165,7 @@ def test_order_implicit( assert read_data.flags["C_CONTIGUOUS"] -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_open(store: Store) -> None: spath = StorePath(store) a = zarr.create_array( @@ -262,7 +270,7 @@ def test_morton_ordering(shape: tuple[int, ...]) -> None: assert coord == decode_morton(i, shape) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_write_partial_chunks(store: Store) -> None: data = np.arange(0, 256, dtype="uint16").reshape((16, 16)) spath = StorePath(store) @@ -277,7 +285,7 @@ def test_write_partial_chunks(store: Store) -> None: assert np.array_equal(a[0:16, 0:16], data) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) async def test_delete_empty_chunks(store: Store) -> None: data = np.ones((16, 16)) path = "delete_empty_chunks" @@ -295,7 +303,7 @@ async def test_delete_empty_chunks(store: Store) -> None: assert await store.get(f"{path}/c0/0", prototype=default_buffer_prototype()) is None -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) async def test_dimension_names(store: Store) -> None: data = np.arange(0, 256, dtype="uint16").reshape((16, 16)) path = "dimension_names" @@ -375,7 +383,7 @@ def test_invalid_metadata_create_array() -> None: ) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) async def test_resize(store: Store) -> None: data = np.zeros((16, 18), dtype="uint16") path = "resize" @@ -402,3 +410,53 @@ async def test_resize(store: Store) -> None: assert await store.get(f"{path}/0.1", prototype=default_buffer_prototype()) is not None assert await store.get(f"{path}/1.0", prototype=default_buffer_prototype()) is None assert await store.get(f"{path}/1.1", prototype=default_buffer_prototype()) is None + + +# Consolidated codec sync-support tests. These replace the per-codec +# ``test_*_codec_supports_sync`` and ``test_*_codec_sync_roundtrip`` duplicates that were +# byte-identical (apart from the codec instance) across the individual codec test modules. +@pytest.mark.parametrize( + "codec", + [ + ZstdCodec(), + Crc32cCodec(), + GzipCodec(), + BytesCodec(), + BloscCodec(), + TransposeCodec(order=(0, 1)), + VLenUTF8Codec(), + VLenBytesCodec(), + ], + ids=lambda codec: type(codec).__name__, +) +def test_codec_supports_sync(codec: Codec) -> None: + assert isinstance(codec, SupportsSyncCodec) + + +@pytest.mark.parametrize( + "codec", + [ + ZstdCodec(level=1), + Crc32cCodec(), + GzipCodec(level=1), + BloscCodec(typesize=8), + ], + ids=lambda codec: type(codec).__name__, +) +def test_bytes_to_bytes_codec_sync_roundtrip(codec: SupportsSyncCodec[Buffer, Buffer]) -> None: + arr = np.arange(100, dtype="float64") + zdtype = get_data_type_from_native_dtype(arr.dtype) + spec = ArraySpec( + shape=arr.shape, + dtype=zdtype, + fill_value=zdtype.cast_scalar(0), + config=ArrayConfig(order="C", write_empty_chunks=True), + prototype=default_buffer_prototype(), + ) + buf = default_buffer_prototype().buffer.from_array_like(arr.view("B")) + + encoded = codec._encode_sync(buf, spec) + assert encoded is not None + decoded = codec._decode_sync(encoded, spec) + result = np.frombuffer(decoded.as_numpy_array(), dtype="float64") + np.testing.assert_array_equal(arr, result) diff --git a/tests/test_codecs/test_crc32c.py b/tests/test_codecs/test_crc32c.py deleted file mode 100644 index 3ab1070f60..0000000000 --- a/tests/test_codecs/test_crc32c.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import annotations - -import numpy as np - -from zarr.abc.codec import SupportsSyncCodec -from zarr.codecs.crc32c_ import Crc32cCodec -from zarr.core.array_spec import ArrayConfig, ArraySpec -from zarr.core.buffer import default_buffer_prototype -from zarr.core.dtype import get_data_type_from_native_dtype - - -def test_crc32c_codec_supports_sync() -> None: - assert isinstance(Crc32cCodec(), SupportsSyncCodec) - - -def test_crc32c_codec_sync_roundtrip() -> None: - codec = Crc32cCodec() - arr = np.arange(100, dtype="float64") - zdtype = get_data_type_from_native_dtype(arr.dtype) - spec = ArraySpec( - shape=arr.shape, - dtype=zdtype, - fill_value=zdtype.cast_scalar(0), - config=ArrayConfig(order="C", write_empty_chunks=True), - prototype=default_buffer_prototype(), - ) - buf = default_buffer_prototype().buffer.from_array_like(arr.view("B")) - - encoded = codec._encode_sync(buf, spec) - assert encoded is not None - decoded = codec._decode_sync(encoded, spec) - result = np.frombuffer(decoded.as_numpy_array(), dtype="float64") - np.testing.assert_array_equal(arr, result) diff --git a/tests/test_codecs/test_endian.py b/tests/test_codecs/test_endian.py index c505cee828..066e78274e 100644 --- a/tests/test_codecs/test_endian.py +++ b/tests/test_codecs/test_endian.py @@ -4,7 +4,7 @@ import pytest import zarr -from zarr.abc.codec import SupportsSyncCodec +from tests.conftest import LOCAL_MEMORY_STORES from zarr.abc.store import Store from zarr.codecs import BytesCodec from zarr.core.array_spec import ArrayConfig, ArraySpec @@ -16,7 +16,7 @@ @pytest.mark.filterwarnings("ignore:The endianness of the requested serializer") -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("endian", ["big", "little"]) async def test_endian(store: Store, endian: Literal["big", "little"]) -> None: data = np.arange(0, 256, dtype="uint16").reshape((16, 16)) @@ -37,10 +37,6 @@ async def test_endian(store: Store, endian: Literal["big", "little"]) -> None: assert np.array_equal(data, readback_data) -def test_bytes_codec_supports_sync() -> None: - assert isinstance(BytesCodec(), SupportsSyncCodec) - - def test_bytes_codec_sync_roundtrip() -> None: codec = BytesCodec() arr = np.arange(100, dtype="float64") @@ -63,7 +59,7 @@ def test_bytes_codec_sync_roundtrip() -> None: @pytest.mark.filterwarnings("ignore:The endianness of the requested serializer") -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("dtype_input_endian", [">u2", " None: data = np.arange(0, 256, dtype="uint16").reshape((16, 16)) @@ -26,27 +23,3 @@ def test_gzip(store: Store) -> None: a[:, :] = data assert np.array_equal(data, a[:, :]) - - -def test_gzip_codec_supports_sync() -> None: - assert isinstance(GzipCodec(), SupportsSyncCodec) - - -def test_gzip_codec_sync_roundtrip() -> None: - codec = GzipCodec(level=1) - arr = np.arange(100, dtype="float64") - zdtype = get_data_type_from_native_dtype(arr.dtype) - spec = ArraySpec( - shape=arr.shape, - dtype=zdtype, - fill_value=zdtype.cast_scalar(0), - config=ArrayConfig(order="C", write_empty_chunks=True), - prototype=default_buffer_prototype(), - ) - buf = default_buffer_prototype().buffer.from_array_like(arr.view("B")) - - encoded = codec._encode_sync(buf, spec) - assert encoded is not None - decoded = codec._decode_sync(encoded, spec) - result = np.frombuffer(decoded.as_numpy_array(), dtype="float64") - np.testing.assert_array_equal(arr, result) diff --git a/tests/test_codecs/test_sharding.py b/tests/test_codecs/test_sharding.py index 856d29ef7a..ad16440f73 100644 --- a/tests/test_codecs/test_sharding.py +++ b/tests/test_codecs/test_sharding.py @@ -24,11 +24,11 @@ from zarr.core.indexing import c_order_iter from zarr.storage import MemoryStore, StorePath, ZipStore -from ..conftest import ArrayRequest +from ..conftest import ALL_STORES, LOCAL_MEMORY_STORES, LOCAL_STORE, ArrayRequest from .test_codecs import _AsyncArrayProxy, order_from_dim -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) @pytest.mark.parametrize("index_location", ["start", "end"]) @pytest.mark.parametrize( "array_fixture", @@ -76,7 +76,7 @@ def test_sharding( assert np.array_equal(data, read_data) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) @pytest.mark.parametrize("index_location", ["start", "end"]) @pytest.mark.parametrize("offset", [0, 10]) def test_sharding_scalar( @@ -106,7 +106,7 @@ def test_sharding_scalar( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) @pytest.mark.parametrize( "array_fixture", [ @@ -142,7 +142,7 @@ def test_sharding_partial( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) @pytest.mark.parametrize( "array_fixture", [ @@ -181,7 +181,7 @@ def test_sharding_partial_readwrite( indirect=["array_fixture"], ) @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_partial_read( store: Store, array_fixture: npt.NDArray[Any], index_location: ShardingCodecIndexLocation ) -> None: @@ -203,7 +203,7 @@ def test_sharding_partial_read( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_multiple_chunks_partial_shard_read( store: Store, index_location: ShardingCodecIndexLocation, @@ -246,7 +246,7 @@ def test_sharding_multiple_chunks_partial_shard_read( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_duplicate_read_indexes( store: Store, index_location: ShardingCodecIndexLocation, @@ -284,7 +284,7 @@ def test_sharding_duplicate_read_indexes( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_read_empty_chunks_within_non_empty_shard_write_empty_false( store: Store, index_location: ShardingCodecIndexLocation ) -> None: @@ -323,7 +323,7 @@ def test_sharding_read_empty_chunks_within_non_empty_shard_write_empty_false( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_read_empty_chunks_within_empty_shard_write_empty_false( store: Store, index_location: ShardingCodecIndexLocation ) -> None: @@ -357,7 +357,7 @@ def test_sharding_read_empty_chunks_within_empty_shard_write_empty_false( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_partial_shard_read__index_load_fails( store: Store, index_location: ShardingCodecIndexLocation ) -> None: @@ -389,7 +389,7 @@ def test_sharding_partial_shard_read__index_load_fails( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_partial_shard_read__index_chunk_slice_fails( store: Store, index_location: ShardingCodecIndexLocation, @@ -424,7 +424,7 @@ def test_sharding_partial_shard_read__index_chunk_slice_fails( @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_partial_shard_read__chunk_load_fails( store: Store, index_location: ShardingCodecIndexLocation ) -> None: @@ -473,7 +473,7 @@ async def fail_chunk_reads(key: str, byte_ranges: Any, **kwargs: Any) -> Any: indirect=["array_fixture"], ) @pytest.mark.parametrize("index_location", ["start", "end"]) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_sharding_partial_overwrite( store: Store, array_fixture: npt.NDArray[Any], index_location: ShardingCodecIndexLocation ) -> None: @@ -522,7 +522,7 @@ def test_sharding_partial_overwrite( "inner_index_location", ["start", "end"], ) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_nested_sharding( store: Store, array_fixture: npt.NDArray[Any], @@ -570,7 +570,7 @@ def test_nested_sharding( "inner_index_location", ["start", "end"], ) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_nested_sharding_create_array( store: Store, array_fixture: npt.NDArray[Any], @@ -600,7 +600,7 @@ def test_nested_sharding_create_array( assert np.array_equal(data, read_data) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_open_sharding(store: Store) -> None: path = "open_sharding" spath = StorePath(store, path) @@ -618,7 +618,7 @@ def test_open_sharding(store: Store) -> None: assert a.metadata == b.metadata -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_write_partial_sharded_chunks(store: Store) -> None: data = np.arange(0, 16 * 16, dtype="uint16").reshape((16, 16)) spath = StorePath(store) @@ -635,7 +635,7 @@ def test_write_partial_sharded_chunks(store: Store) -> None: assert np.array_equal(a[0:16, 0:16], data) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_delete_empty_shards(store: Store) -> None: if not store.supports_deletes: pytest.skip("store does not support deletes") @@ -681,7 +681,7 @@ def test_pickle() -> None: assert restored.subchunk_write_order == "lexicographic" -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize( "index_location", [ShardingCodecIndexLocation.start, ShardingCodecIndexLocation.end] ) @@ -708,7 +708,7 @@ async def test_sharding_with_empty_inner_chunk( assert np.array_equal(data_read, data) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize( "index_location", [ShardingCodecIndexLocation.start, ShardingCodecIndexLocation.end], @@ -737,7 +737,7 @@ async def test_sharding_with_chunks_per_shard( assert np.array_equal(data_read, data) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_invalid_metadata(store: Store) -> None: spath1 = StorePath(store, "invalid_inner_chunk_shape") with pytest.raises(ValueError): @@ -779,7 +779,7 @@ def test_invalid_shard_shape() -> None: ) -@pytest.mark.parametrize("store", ["local"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_STORE, indirect=True) def test_sharding_mixed_integer_list_indexing(store: Store) -> None: """Regression test for https://github.com/zarr-developers/zarr-python/issues/3691. diff --git a/tests/test_codecs/test_transpose.py b/tests/test_codecs/test_transpose.py index 949bb72a62..dfab992a80 100644 --- a/tests/test_codecs/test_transpose.py +++ b/tests/test_codecs/test_transpose.py @@ -2,8 +2,8 @@ import pytest import zarr +from tests.conftest import LOCAL_MEMORY_STORES from zarr import AsyncArray, config -from zarr.abc.codec import SupportsSyncCodec from zarr.abc.store import Store from zarr.codecs import TransposeCodec from zarr.core.array_spec import ArrayConfig, ArraySpec @@ -19,7 +19,7 @@ @pytest.mark.parametrize("runtime_write_order", ["F", "C"]) @pytest.mark.parametrize("runtime_read_order", ["F", "C"]) @pytest.mark.parametrize("with_sharding", [True, False]) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) async def test_transpose( store: Store, input_order: MemoryOrder, @@ -61,7 +61,7 @@ async def test_transpose( assert read_data.flags["C_CONTIGUOUS"] -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("order", [[1, 2, 0], [1, 2, 3, 0], [3, 2, 4, 0, 1]]) def test_transpose_non_self_inverse(store: Store, order: list[int]) -> None: shape = [i + 3 for i in range(len(order))] @@ -80,7 +80,7 @@ def test_transpose_non_self_inverse(store: Store, order: list[int]) -> None: assert np.array_equal(data, read_data) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_transpose_invalid( store: Store, ) -> None: @@ -99,10 +99,6 @@ def test_transpose_invalid( ) -def test_transpose_codec_supports_sync() -> None: - assert isinstance(TransposeCodec(order=(0, 1)), SupportsSyncCodec) - - def test_transpose_codec_sync_roundtrip() -> None: codec = TransposeCodec(order=(1, 0)) arr = np.arange(12, dtype="float64").reshape(3, 4) diff --git a/tests/test_codecs/test_vlen.py b/tests/test_codecs/test_vlen.py index 3422090a28..1c36188685 100644 --- a/tests/test_codecs/test_vlen.py +++ b/tests/test_codecs/test_vlen.py @@ -5,10 +5,9 @@ import zarr from zarr import Array -from zarr.abc.codec import Codec, SupportsSyncCodec +from zarr.abc.codec import Codec from zarr.abc.store import Store from zarr.codecs import ZstdCodec -from zarr.codecs.vlen_utf8 import VLenBytesCodec, VLenUTF8Codec from zarr.core.dtype import get_data_type_from_native_dtype from zarr.core.metadata.v3 import ArrayV3Metadata from zarr.storage import StorePath @@ -65,11 +64,3 @@ def test_vlen_string( assert np.array_equal(data, b[:, :]) assert b.metadata.data_type == get_data_type_from_native_dtype(data.dtype) assert a.dtype == data.dtype - - -def test_vlen_utf8_codec_supports_sync() -> None: - assert isinstance(VLenUTF8Codec(), SupportsSyncCodec) - - -def test_vlen_bytes_codec_supports_sync() -> None: - assert isinstance(VLenBytesCodec(), SupportsSyncCodec) diff --git a/tests/test_codecs/test_zstd.py b/tests/test_codecs/test_zstd.py index 3f3f15a41a..84458c8483 100644 --- a/tests/test_codecs/test_zstd.py +++ b/tests/test_codecs/test_zstd.py @@ -2,16 +2,13 @@ import pytest import zarr -from zarr.abc.codec import SupportsSyncCodec +from tests.conftest import LOCAL_MEMORY_STORES from zarr.abc.store import Store from zarr.codecs import ZstdCodec -from zarr.core.array_spec import ArrayConfig, ArraySpec -from zarr.core.buffer import default_buffer_prototype -from zarr.core.dtype import get_data_type_from_native_dtype from zarr.storage import StorePath -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("checksum", [True, False]) def test_zstd(store: Store, checksum: bool) -> None: data = np.arange(0, 256, dtype="uint16").reshape((16, 16)) @@ -27,27 +24,3 @@ def test_zstd(store: Store, checksum: bool) -> None: a[:, :] = data assert np.array_equal(data, a[:, :]) - - -def test_zstd_codec_supports_sync() -> None: - assert isinstance(ZstdCodec(), SupportsSyncCodec) - - -def test_zstd_codec_sync_roundtrip() -> None: - codec = ZstdCodec(level=1) - arr = np.arange(100, dtype="float64") - zdtype = get_data_type_from_native_dtype(arr.dtype) - spec = ArraySpec( - shape=arr.shape, - dtype=zdtype, - fill_value=zdtype.cast_scalar(0), - config=ArrayConfig(order="C", write_empty_chunks=True), - prototype=default_buffer_prototype(), - ) - buf = default_buffer_prototype().buffer.from_array_like(arr.view("B")) - - encoded = codec._encode_sync(buf, spec) - assert encoded is not None - decoded = codec._decode_sync(encoded, spec) - result = np.frombuffer(decoded.as_numpy_array(), dtype="float64") - np.testing.assert_array_equal(arr, result) diff --git a/tests/test_config.py b/tests/test_config.py index 4e293e968f..76c36a5379 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -8,6 +8,7 @@ import pytest import zarr +from tests.conftest import LOCAL_MEMORY_STORES from zarr import zeros from zarr.abc.codec import CodecPipeline from zarr.abc.store import ByteSetter, Store @@ -129,7 +130,7 @@ class MockClass: ) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_config_codec_pipeline_class(store: Store) -> None: # has default value assert get_pipeline_class().__name__ != "" @@ -181,7 +182,7 @@ class MockEnvCodecPipeline(CodecPipeline): @pytest.mark.filterwarnings("error") -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_config_codec_implementation(store: Store) -> None: # has default value assert fully_qualified_name(get_codec_class("blosc")) == config.defaults[0]["codecs"]["blosc"] @@ -218,7 +219,7 @@ class NewBloscCodec(BloscCodec): assert get_codec_class("blosc", reload_config=True) == NewBloscCodec -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_config_ndbuffer_implementation(store: Store) -> None: # set custom ndbuffer with TestNDArrayLike implementation register_ndbuffer(NDBufferUsingTestNDArrayLike) @@ -321,7 +322,7 @@ class NewCodec2(BytesCodec): get_codec_class("new_codec") -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize( "kwargs", [ @@ -356,7 +357,7 @@ def test_config_read_missing_chunks(store: Store, kwargs: dict[str, Any]) -> Non assert np.array_equal(result, np.arange(16, dtype="int32").reshape(4, 4)) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_config_read_missing_chunks_sharded_inner(store: Store) -> None: """Because the shard index and inner chunks should be stored together in a single storage object (read: a file or blob), @@ -394,7 +395,7 @@ def test_config_read_missing_chunks_sharded_inner(store: Store) -> None: a[4:] -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_config_read_missing_chunks_write_empty_chunks(store: Store) -> None: """write_empty_chunks=False drops chunks equal to fill_value, which then appear missing to read_missing_chunks=False.""" diff --git a/tests/test_group.py b/tests/test_group.py index e05df0dfcb..3a77a9d7f9 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -19,7 +19,6 @@ import zarr.api.synchronous import zarr.storage from zarr import Array, AsyncArray, AsyncGroup, Group -from zarr.abc.store import Store from zarr.core import sync_group from zarr.core._info import GroupInfo from zarr.core.buffer import default_buffer_prototype @@ -51,25 +50,22 @@ from zarr.storage._utils import _join_paths, normalize_path from zarr.testing.store import LatencyStore -from .conftest import meta_from_array, parse_store +from .conftest import ( + ALL_STORES, + LOCAL_MEMORY_STORES, + LOCAL_STORE, + MEMORY_STORE, + meta_from_array, +) if TYPE_CHECKING: from collections.abc import Callable - from _pytest.compat import LEGACY_PATH - + from zarr.abc.store import Store 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)) - if not isinstance(result, Store): - raise TypeError(f"Wrong store class returned by test fixture! got {result} instead") - return result - - @pytest.fixture(params=[True, False]) def overwrite(request: pytest.FixtureRequest) -> bool: result = request.param @@ -78,6 +74,7 @@ def overwrite(request: pytest.FixtureRequest) -> bool: return result +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_init(store: Store, zarr_format: ZarrFormat) -> None: """ Test that initializing a group from an asyncgroup works. @@ -87,6 +84,7 @@ def test_group_init(store: Store, zarr_format: ZarrFormat) -> None: assert group._async_group == agroup +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_create_creates_parents(store: Store, zarr_format: ZarrFormat) -> None: # prepare a root node, with some data set await zarr.api.asynchronous.open_group( @@ -139,7 +137,7 @@ async def test_create_creates_parents(store: Store, zarr_format: ZarrFormat) -> assert g.attrs == {} -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("root_name", ["", "/", "a", "/a"]) @pytest.mark.parametrize("branch_name", ["foo", "/foo", "foo/bar", "/foo/bar"]) def test_group_name_properties( @@ -163,6 +161,7 @@ def test_group_name_properties( @pytest.mark.parametrize("consolidated_metadata", [True, False]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_members(store: Store, zarr_format: ZarrFormat, consolidated_metadata: bool) -> None: """ Test that `Group.members` returns correct values, i.e. the arrays and groups @@ -249,6 +248,7 @@ def test_group_members(store: Store, zarr_format: ZarrFormat, consolidated_metad members_observed = group.members(max_depth=-1) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group(store: Store, zarr_format: ZarrFormat) -> None: """ Test basic Group routines. @@ -293,6 +293,7 @@ def test_group(store: Store, zarr_format: ZarrFormat) -> None: assert dict(bar3.attrs) == {"baz": "qux", "name": "bar"} +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_create(store: Store, overwrite: bool, zarr_format: ZarrFormat) -> None: """ Test that `Group.from_store` works as expected. @@ -309,6 +310,7 @@ def test_group_create(store: Store, overwrite: bool, zarr_format: ZarrFormat) -> _ = Group.from_store(store, overwrite=overwrite, zarr_format=zarr_format) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_open(store: Store, zarr_format: ZarrFormat, overwrite: bool) -> None: """ Test the `Group.open` method. @@ -346,6 +348,7 @@ def test_group_open(store: Store, zarr_format: ZarrFormat, overwrite: bool) -> N @pytest.mark.parametrize("consolidated", [True, False]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_getitem(store: Store, zarr_format: ZarrFormat, consolidated: bool) -> None: """ Test the `Group.__getitem__` method. @@ -425,6 +428,7 @@ def test_group_getitem(store: Store, zarr_format: ZarrFormat, consolidated: bool group["subarray/subsubarray"] +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_get_with_default(store: Store, zarr_format: ZarrFormat) -> None: group = Group.from_store(store, zarr_format=zarr_format) @@ -448,6 +452,7 @@ def test_group_get_with_default(store: Store, zarr_format: ZarrFormat) -> None: @pytest.mark.parametrize("consolidated", [True, False]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_delitem(store: Store, zarr_format: ZarrFormat, consolidated: bool) -> None: """ Test the `Group.__delitem__` method. @@ -492,6 +497,7 @@ def test_group_delitem(store: Store, zarr_format: ZarrFormat, consolidated: bool group["subarray"] +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_iter(store: Store, zarr_format: ZarrFormat) -> None: """ Test the `Group.__iter__` method. @@ -501,6 +507,7 @@ def test_group_iter(store: Store, zarr_format: ZarrFormat) -> None: assert list(group) == [] +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_len(store: Store, zarr_format: ZarrFormat) -> None: """ Test the `Group.__len__` method. @@ -510,6 +517,7 @@ def test_group_len(store: Store, zarr_format: ZarrFormat) -> None: assert len(group) == 0 +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_setitem(store: Store, zarr_format: ZarrFormat) -> None: """ Test the `Group.__setitem__` method. @@ -536,6 +544,7 @@ def test_group_setitem(store: Store, zarr_format: ZarrFormat) -> None: np.testing.assert_array_equal(group[key], arr) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_contains(store: Store, zarr_format: ZarrFormat) -> None: """ Test the `Group.__contains__` method @@ -547,6 +556,7 @@ def test_group_contains(store: Store, zarr_format: ZarrFormat) -> None: @pytest.mark.parametrize("consolidate", [True, False]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_child_iterators(store: Store, zarr_format: ZarrFormat, consolidate: bool): group = Group.from_store(store, zarr_format=zarr_format) expected_group_keys = ["g0", "g1"] @@ -673,6 +683,7 @@ def test_group_child_iterators(store: Store, zarr_format: ZarrFormat, consolidat assert sorted(group.array_values(), key=lambda x: x.name) == expected_array_values +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_update_attributes(store: Store, zarr_format: ZarrFormat) -> None: """ Test the behavior of `Group.update_attributes` @@ -692,6 +703,7 @@ def test_group_update_attributes(store: Store, zarr_format: ZarrFormat) -> None: assert new_group.attrs == updated_attrs +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_group_update_attributes_async(store: Store, zarr_format: ZarrFormat) -> None: """ Test the behavior of `Group.update_attributes_async` @@ -709,6 +721,7 @@ async def test_group_update_attributes_async(store: Store, zarr_format: ZarrForm @pytest.mark.parametrize("name", ["a", "/a"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_create_array( store: Store, zarr_format: ZarrFormat, @@ -739,6 +752,7 @@ def test_group_create_array( @pytest.mark.parametrize("method", ["create_array", "create_group"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_create_with_parent_array(store: Store, zarr_format: ZarrFormat, method: str): """Test that groups/arrays cannot be created under a parent array.""" @@ -816,6 +830,7 @@ def test_group_array_like_creation( assert np.all(new_arr[:] == expect_fill) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_group_array_creation( store: Store, zarr_format: ZarrFormat, @@ -884,8 +899,7 @@ def test_group_array_creation( assert full_like_array.store_path.store == store -@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_group_creation_existing_node( @@ -933,6 +947,7 @@ def test_group_creation_existing_node( ) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_create( store: Store, overwrite: bool, @@ -975,6 +990,7 @@ async def test_asyncgroup_create( ) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_attrs(store: Store, zarr_format: ZarrFormat) -> None: attributes = {"foo": 100} agroup = await AsyncGroup.from_store(store, zarr_format=zarr_format, attributes=attributes) @@ -982,6 +998,7 @@ async def test_asyncgroup_attrs(store: Store, zarr_format: ZarrFormat) -> None: assert agroup.attrs == agroup.metadata.attributes == attributes +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_open( store: Store, zarr_format: ZarrFormat, @@ -1003,6 +1020,7 @@ async def test_asyncgroup_open( assert group_w == group_r +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_open_wrong_format( store: Store, zarr_format: ZarrFormat, @@ -1030,6 +1048,7 @@ async def test_asyncgroup_open_wrong_format( {"zarr_format": 2, "attributes": {"foo": 100}}, ], ) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_asyncgroup_from_dict(store: Store, data: dict[str, Any]) -> None: """ Test that we can create an AsyncGroup from a dict @@ -1045,6 +1064,7 @@ def test_asyncgroup_from_dict(store: Store, data: dict[str, Any]) -> None: # todo: replace this with a declarative API where we model a full hierarchy +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_getitem(store: Store, zarr_format: ZarrFormat) -> None: """ Create an `AsyncGroup`, then create members of that group, and ensure that we can access those @@ -1065,6 +1085,7 @@ async def test_asyncgroup_getitem(store: Store, zarr_format: ZarrFormat) -> None await agroup.getitem("foo") +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_delitem(store: Store, zarr_format: ZarrFormat) -> None: if not store.supports_deletes: pytest.skip("store does not support deletes") @@ -1102,6 +1123,7 @@ async def test_asyncgroup_delitem(store: Store, zarr_format: ZarrFormat) -> None @pytest.mark.parametrize("name", ["a", "/a"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_create_group( store: Store, name: str, @@ -1120,6 +1142,7 @@ async def test_asyncgroup_create_group( assert subgroup.metadata.zarr_format == zarr_format +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_create_array( store: Store, zarr_format: ZarrFormat, overwrite: bool ) -> None: @@ -1157,6 +1180,7 @@ async def test_asyncgroup_create_array( assert subnode.metadata.zarr_format == zarr_format +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_asyncgroup_update_attributes(store: Store, zarr_format: ZarrFormat) -> None: """ Test that the AsyncGroup.update_attributes method works correctly. @@ -1177,8 +1201,7 @@ async def test_asyncgroup_update_attributes(store: Store, zarr_format: ZarrForma assert agroup_new_attributes.attrs == attributes_updated -@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_group(store: LocalStore, zarr_format: ZarrFormat) -> None: expected = await AsyncGroup.from_store( store=store, attributes={"foo": 999}, zarr_format=zarr_format @@ -1188,8 +1211,7 @@ async def test_serializable_async_group(store: LocalStore, zarr_format: ZarrForm assert actual == expected -@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_group(store: LocalStore, zarr_format: ZarrFormat) -> None: expected = Group.from_store(store=store, attributes={"foo": 999}, zarr_format=zarr_format) p = pickle.dumps(expected) @@ -1198,6 +1220,7 @@ def test_serializable_sync_group(store: LocalStore, zarr_format: ZarrFormat) -> @pytest.mark.parametrize("consolidated_metadata", [True, False]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_group_members_async(store: Store, consolidated_metadata: bool) -> None: group = await AsyncGroup.from_store( store=store, @@ -1291,6 +1314,7 @@ async def test_group_members_async(store: Store, consolidated_metadata: bool) -> await group.nmembers(max_depth=-1) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_require_group(store: LocalStore | MemoryStore, zarr_format: ZarrFormat) -> None: root = await AsyncGroup.from_store(store=store, zarr_format=zarr_format) @@ -1321,6 +1345,7 @@ async def test_require_group(store: LocalStore | MemoryStore, zarr_format: ZarrF await foo_group.require_group("bar") +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_require_groups(store: LocalStore | MemoryStore, zarr_format: ZarrFormat) -> None: root = await AsyncGroup.from_store(store=store, zarr_format=zarr_format) # create foo group @@ -1342,6 +1367,7 @@ async def test_require_groups(store: LocalStore | MemoryStore, zarr_format: Zarr assert no_group == () +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_require_array(store: Store, zarr_format: ZarrFormat) -> None: root = await AsyncGroup.from_store(store=store, zarr_format=zarr_format) foo1 = await root.require_array("foo", shape=(10,), dtype="i8", attributes={"foo": 101}) @@ -1368,6 +1394,7 @@ async def test_require_array(store: Store, zarr_format: ZarrFormat) -> None: @pytest.mark.parametrize("consolidate", [True, False]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_members_name(store: Store, consolidate: bool, zarr_format: ZarrFormat): group = Group.from_store(store=store, zarr_format=zarr_format) a = group.create_group(name="a") @@ -1439,6 +1466,7 @@ async def test_open_ambiguous_node(): class TestConsolidated: + @pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_group_getitem_consolidated(self, store: Store) -> None: root = await AsyncGroup.from_store(store=store) # Set up the test structure with @@ -1497,6 +1525,7 @@ async def test_group_getitem_consolidated(self, store: Store) -> None: rg2 = await rg1.getitem("g2") assert rg2.metadata.consolidated_metadata == ConsolidatedMetadata(metadata={}) + @pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_group_delitem_consolidated(self, store: Store) -> None: if isinstance(store, ZipStore): raise pytest.skip("Not implemented") @@ -1541,6 +1570,7 @@ async def test_group_delitem_consolidated(self, store: Store) -> None: assert len(group.metadata.consolidated_metadata.metadata) == 1 assert "g0" not in group.metadata.consolidated_metadata.metadata + @pytest.mark.parametrize("store", ALL_STORES, indirect=True) def test_open_consolidated_raises(self, store: Store) -> None: if isinstance(store, ZipStore): raise pytest.skip("Not implemented") @@ -1565,6 +1595,7 @@ def test_open_consolidated_raises(self, store: Store) -> None: group = zarr.open_group(store=store, use_consolidated=False) assert group.metadata.consolidated_metadata is None + @pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_open_consolidated_raises_async(self, store: Store) -> None: if isinstance(store, ZipStore): raise pytest.skip("Not implemented") @@ -1642,7 +1673,7 @@ def test_update_attrs() -> None: assert root.attrs["foo"] == "bar" -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) def test_delitem_removes_children(store: Store, zarr_format: ZarrFormat) -> None: # https://github.com/zarr-developers/zarr-python/issues/2191 g1 = zarr.group(store=store, zarr_format=zarr_format) @@ -1655,7 +1686,7 @@ def test_delitem_removes_children(store: Store, zarr_format: ZarrFormat) -> None g1["0/0"] -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_nodes( impl: Literal["async", "sync"], store: Store, zarr_format: ZarrFormat @@ -1681,7 +1712,7 @@ async def test_create_nodes( assert node_spec == {k: v.metadata for k, v in observed_nodes.items()} -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) def test_create_nodes_concurrency_limit(store: MemoryStore) -> None: """ Test that the execution time of create_nodes can be constrained by the async concurrency @@ -1741,7 +1772,7 @@ def test_consistent_signatures( assert wrong["wrong_type"] == [] -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("overwrite", [True, False]) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_hierarchy( @@ -1793,7 +1824,7 @@ async def test_create_hierarchy( assert expected_meta == {k: v.metadata for k, v in created.items()} -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("extant_node", ["array", "group"]) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_hierarchy_existing_nodes( @@ -1850,7 +1881,7 @@ async def test_create_hierarchy_existing_nodes( ).metadata.attributes == {"extant": True} -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("overwrite", [True, False]) @pytest.mark.parametrize("group_path", ["", "foo"]) @pytest.mark.parametrize("impl", ["async", "sync"]) @@ -1909,7 +1940,7 @@ async def test_group_create_hierarchy( ) -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("overwrite", [True, False]) def test_group_create_hierarchy_no_root( store: Store, zarr_format: ZarrFormat, overwrite: bool @@ -1971,7 +2002,7 @@ def test_implicit_groups() -> None: assert observed == expected -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) def test_group_create_hierarchy_invalid_mixed_zarr_format( store: Store, zarr_format: ZarrFormat ) -> None: @@ -1991,7 +2022,7 @@ def test_group_create_hierarchy_invalid_mixed_zarr_format( _ = tuple(g.create_hierarchy(tree)) -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("defect", ["array/array", "array/group"]) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_hierarchy_invalid_nested( @@ -2021,7 +2052,7 @@ async def test_create_hierarchy_invalid_nested( await _collect_aiterator(create_hierarchy(store=store, nodes=hierarchy_spec)) -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_hierarchy_invalid_mixed_format( impl: Literal["async", "sync"], store: Store @@ -2061,7 +2092,6 @@ async def test_create_hierarchy_invalid_mixed_format( @pytest.mark.parametrize("store", ["memory", "local"], indirect=True) -@pytest.mark.parametrize("zarr_format", [2, 3]) @pytest.mark.parametrize("root_key", ["", "root"]) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_rooted_hierarchy_group( @@ -2112,7 +2142,6 @@ async def test_create_rooted_hierarchy_group( @pytest.mark.parametrize("store", ["memory", "local"], indirect=True) -@pytest.mark.parametrize("zarr_format", [2, 3]) @pytest.mark.parametrize("root_key", ["", "root"]) @pytest.mark.parametrize("impl", ["async", "sync"]) async def test_create_rooted_hierarchy_array( @@ -2152,6 +2181,7 @@ async def test_create_rooted_hierarchy_invalid(impl: Literal["async", "sync"]) - "b": GroupMetadata(zarr_format=zarr_format), } msg = "The input does not specify a root node. " + store = MemoryStore() if impl == "sync": with pytest.raises(ValueError, match=msg): sync_group.create_rooted_hierarchy(store=store, nodes=nodes) @@ -2162,7 +2192,7 @@ async def test_create_rooted_hierarchy_invalid(impl: Literal["async", "sync"]) - raise ValueError(f"Invalid impl: {impl}") -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) def test_group_members_performance(store: Store) -> None: """ Test that the execution time of Group.members is less than the number of members times the @@ -2193,7 +2223,7 @@ def test_group_members_performance(store: Store) -> None: assert elapsed < (num_groups * get_latency) -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) def test_group_members_concurrency_limit(store: MemoryStore) -> None: """ Test that the execution time of Group.members can be constrained by the async concurrency diff --git a/tests/test_indexing.py b/tests/test_indexing.py index a9358e4fcf..9b3f56be0f 100644 --- a/tests/test_indexing.py +++ b/tests/test_indexing.py @@ -11,7 +11,7 @@ from numpy.testing import assert_array_equal import zarr -from tests.conftest import Expect, ExpectFail +from tests.conftest import LOCAL_MEMORY_STORES, MEMORY_STORE, Expect, ExpectFail from zarr import Array from zarr.core.buffer import default_buffer_prototype from zarr.core.indexing import ( @@ -1978,7 +1978,7 @@ def test_indexing_with_zarr_array(store: StorePath) -> None: assert_array_equal(a[ii], za.oindex[zii]) -@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"]) +@pytest.mark.parametrize("store", LOCAL_MEMORY_STORES, indirect=True) @pytest.mark.parametrize("shape", [(0, 2, 3), (0,), (3, 0)]) def test_zero_sized_chunks(store: StorePath, shape: list[int]) -> None: """Arrays with zero-extent dimensions can be created and indexed without error; reading back returns the fill value.""" @@ -1989,7 +1989,7 @@ def test_zero_sized_chunks(store: StorePath, shape: list[int]) -> None: assert_array_equal(z[...], np.zeros(shape, dtype="f8")) -@pytest.mark.parametrize("store", ["memory"], indirect=["store"]) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) def test_vectorized_indexing_incompatible_shape(store) -> None: """Regression for GH2469: vectorized set-indexing raises ValueError when the value shape is incompatible with the indexer shape.""" # GH2469 diff --git a/tests/test_metadata/test_consolidated.py b/tests/test_metadata/test_consolidated.py index 3596d2bcaa..187e7ed287 100644 --- a/tests/test_metadata/test_consolidated.py +++ b/tests/test_metadata/test_consolidated.py @@ -548,7 +548,6 @@ def test_to_dict_empty(self) -> None: } assert result == expected - @pytest.mark.parametrize("zarr_format", [2, 3]) async def test_to_dict_order( self, memory_store: zarr.storage.MemoryStore, zarr_format: ZarrFormat ) -> None: @@ -585,7 +584,6 @@ async def test_to_dict_order( "c/e", ] - @pytest.mark.parametrize("zarr_format", [2, 3]) async def test_open_consolidated_raises_async(self, zarr_format: ZarrFormat) -> None: store = zarr.storage.MemoryStore() await AsyncGroup.from_store(store, zarr_format=zarr_format) @@ -665,7 +663,6 @@ async def test_consolidated_metadata_v2(self) -> None: ) assert result.metadata == expected - @pytest.mark.parametrize("zarr_format", [2, 3]) async def test_use_consolidated_false( self, memory_store: zarr.storage.MemoryStore, zarr_format: ZarrFormat ) -> None: diff --git a/tests/test_store/test_core.py b/tests/test_store/test_core.py index f2c81b87f9..7fafb151dd 100644 --- a/tests/test_store/test_core.py +++ b/tests/test_store/test_core.py @@ -53,7 +53,6 @@ def store_like( @pytest.mark.parametrize("path", ["foo", "foo/bar"]) @pytest.mark.parametrize("write_group", [True, False]) -@pytest.mark.parametrize("zarr_format", [2, 3]) async def test_contains_group( local_store: LocalStore, path: str, write_group: bool, zarr_format: ZarrFormat ) -> None: @@ -69,7 +68,6 @@ async def test_contains_group( @pytest.mark.parametrize("path", ["foo", "foo/bar"]) @pytest.mark.parametrize("write_array", [True, False]) -@pytest.mark.parametrize("zarr_format", [2, 3]) async def test_contains_array( local_store: LocalStore, path: str, write_array: bool, zarr_format: ZarrFormat ) -> None: diff --git a/tests/test_store/test_logging.py b/tests/test_store/test_logging.py index 96cd184938..5b9242e9ef 100644 --- a/tests/test_store/test_logging.py +++ b/tests/test_store/test_logging.py @@ -6,6 +6,7 @@ import pytest import zarr +from tests.conftest import ALL_STORES from zarr.core.buffer import Buffer, cpu, default_buffer_prototype from zarr.storage import LocalStore, LoggingStore from zarr.testing.store import StoreTests @@ -127,7 +128,7 @@ async def test_with_read_only_round_trip(self, local_store: LocalStore) -> None: await wrapped_ro.set("bar", buf) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_logging_store(store: Store, caplog: pytest.LogCaptureFixture) -> None: wrapped = LoggingStore(store=store, log_level="DEBUG") buffer = default_buffer_prototype().buffer @@ -151,7 +152,7 @@ async def test_logging_store(store: Store, caplog: pytest.LogCaptureFixture) -> assert f"Finished {type(store).__name__}.list" in caplog.record_tuples[1][2] -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_logging_store_counter(store: Store) -> None: wrapped = LoggingStore(store=store, log_level="DEBUG") diff --git a/tests/test_store/test_memory.py b/tests/test_store/test_memory.py index 1e3ee89e92..8c3ee1f148 100644 --- a/tests/test_store/test_memory.py +++ b/tests/test_store/test_memory.py @@ -58,7 +58,6 @@ async def test_list_prefix(self, store: MemoryStore) -> None: assert True @pytest.mark.parametrize("dtype", ["uint8", "float32", "int64"]) - @pytest.mark.parametrize("zarr_format", [2, 3]) async def test_deterministic_size( self, store: MemoryStore, dtype: npt.DTypeLike, zarr_format: ZarrFormat ) -> None: @@ -255,7 +254,6 @@ def test_store_supports_listing(self, store: ManagedMemoryStore) -> None: assert store.supports_listing @pytest.mark.parametrize("dtype", ["uint8", "float32", "int64"]) - @pytest.mark.parametrize("zarr_format", [2, 3]) async def test_deterministic_size( self, store: MemoryStore, dtype: npt.DTypeLike, zarr_format: ZarrFormat ) -> None: diff --git a/tests/test_store/test_wrapper.py b/tests/test_store/test_wrapper.py index b34a63d5d0..74a16e0fa2 100644 --- a/tests/test_store/test_wrapper.py +++ b/tests/test_store/test_wrapper.py @@ -4,6 +4,7 @@ import pytest +from tests.conftest import ALL_STORES from zarr.abc.store import ByteRequest, Store from zarr.core.buffer import Buffer from zarr.core.buffer.cpu import Buffer as CPUBuffer @@ -88,7 +89,7 @@ def test_is_open_setter_raises(self, store: WrapperStore[LocalStore]) -> None: @pytest.mark.filterwarnings( "ignore:coroutine 'ClientCreatorContext.__aexit__' was never awaited:RuntimeWarning" ) -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=True) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_wrapped_set(store: Store, capsys: pytest.CaptureFixture[str]) -> None: # define a class that prints when it sets class NoisySetter(WrapperStore[Store]): @@ -106,7 +107,7 @@ async def set(self, key: str, value: Buffer) -> None: @pytest.mark.filterwarnings("ignore:Unclosed client session:ResourceWarning") -@pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=True) +@pytest.mark.parametrize("store", ALL_STORES, indirect=True) async def test_wrapped_get(store: Store, capsys: pytest.CaptureFixture[str]) -> None: # define a class that prints when it sets class NoisyGetter(WrapperStore[Any]): diff --git a/tests/test_v2.py b/tests/test_v2.py index 3a063ac509..e9a8cbdb62 100644 --- a/tests/test_v2.py +++ b/tests/test_v2.py @@ -11,6 +11,7 @@ import zarr import zarr.core.buffer import zarr.storage +from tests.conftest import MEMORY_STORE from zarr import config from zarr.abc.store import Store from zarr.core.buffer.core import default_buffer_prototype @@ -135,7 +136,7 @@ def test_v2_filters_codecs(filters: Any, order: Literal["C", "F"]) -> None: @pytest.mark.filterwarnings("ignore") -@pytest.mark.parametrize("store", ["memory"], indirect=True) +@pytest.mark.parametrize("store", MEMORY_STORE, indirect=True) def test_create_array_defaults(store: Store) -> None: """ Test that passing compressor=None results in no compressor. Also test that the default value of the compressor