Skip to content

Mark V3 API experimental #1032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 23, 2022
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
4 changes: 4 additions & 0 deletions .github/workflows/minimal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ jobs:
activate-environment: minimal
- name: Tests
shell: "bash -l {0}"
env:
ZARR_V3_EXPERIMENTAL_API: 1
run: |
conda activate minimal
python -m pip install .
pytest -svx --timeout=300
- name: Fixture generation
shell: "bash -l {0}"
env:
ZARR_V3_EXPERIMENTAL_API: 1
run: |
conda activate minimal
rm -rf fixture/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
ZARR_TEST_ABS: 1
ZARR_TEST_MONGO: 1
ZARR_TEST_REDIS: 1
ZARR_V3_API_AVAILABLE: 1
ZARR_V3_EXPERIMENTAL_API: 1
run: |
conda activate zarr-env
mkdir ~/blob_emulator
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/windows-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
pytest -sv --timeout=300
env:
ZARR_TEST_ABS: 1
ZARR_V3_EXPERIMENTAL_API: 1
- name: Conda info
shell: bash -l {0}
run: conda info
Expand Down
2 changes: 1 addition & 1 deletion docs/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Enhancements
package has the necessary classes and functions for evaluating Zarr V3.
Since the format is not yet finalized, the classes and functions are not
automatically imported into the regular `zarr` name space. Setting the
`ZARR_V3_API_AVAILABLE` environment variable will activate them.
`ZARR_V3_EXPERIMENTAL_API` environment variable will activate them.
By :user:`Greggory Lee <grlee77>`; :issue:`898`, :issue:`1006`, and :issue:`1007`.

* **Create FSStore from an existing fsspec filesystem**. If you have created
Expand Down
10 changes: 9 additions & 1 deletion zarr/_storage/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@

DEFAULT_ZARR_VERSION = 2

v3_api_available = os.environ.get('ZARR_V3_API_AVAILABLE', '0').lower() not in ['0', 'false']
v3_api_available = os.environ.get('ZARR_V3_EXPERIMENTAL_API', '0').lower() not in ['0', 'false']


def assert_zarr_v3_api_available():
if not v3_api_available:
raise NotImplementedError(
"# V3 reading and writing is experimental! To enable support, set:\n"
"ZARR_V3_EXPERIMENTAL_API=1"
) # pragma: no cover


class BaseStore(MutableMapping):
Expand Down
5 changes: 4 additions & 1 deletion zarr/convenience.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import re
from collections.abc import Mapping, MutableMapping

from zarr._storage.store import data_root, meta_root
from zarr._storage.store import data_root, meta_root, assert_zarr_v3_api_available
from zarr.core import Array
from zarr.creation import array as _create_array
from zarr.creation import open_array
Expand Down Expand Up @@ -1209,6 +1209,8 @@ def is_zarr_key(key):

else:

assert_zarr_v3_api_available()

sfx = _get_metadata_suffix(store) # type: ignore

def is_zarr_key(key):
Expand Down Expand Up @@ -1288,6 +1290,7 @@ def open_consolidated(store: StoreLike, metadata_key=".zmetadata", mode="r+", **
if store._store_version == 2:
ConsolidatedStoreClass = ConsolidatedMetadataStore
else:
assert_zarr_v3_api_available()
ConsolidatedStoreClass = ConsolidatedMetadataStoreV3
# default is to store within 'consolidated' group on v3
if not metadata_key.startswith('meta/root/'):
Expand Down
5 changes: 4 additions & 1 deletion zarr/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import numpy as np
from numcodecs.compat import ensure_bytes, ensure_ndarray

from zarr._storage.store import _prefix_to_attrs_key
from zarr._storage.store import _prefix_to_attrs_key, assert_zarr_v3_api_available
from zarr.attrs import Attributes
from zarr.codecs import AsType, get_codec
from zarr.errors import ArrayNotFoundError, ReadOnlyError, ArrayIndexError
Expand Down Expand Up @@ -171,6 +171,9 @@ def __init__(
if zarr_version is None:
zarr_version = store._store_version

if zarr_version != 2:
assert_zarr_v3_api_available()

if chunk_store is not None:
chunk_store = normalize_store_arg(chunk_store,
zarr_version=zarr_version)
Expand Down
19 changes: 18 additions & 1 deletion zarr/hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

import numpy as np

from zarr._storage.store import _get_metadata_suffix, data_root, meta_root, DEFAULT_ZARR_VERSION
from zarr._storage.store import (_get_metadata_suffix, data_root, meta_root,
DEFAULT_ZARR_VERSION, assert_zarr_v3_api_available)
from zarr.attrs import Attributes
from zarr.core import Array
from zarr.creation import (array, create, empty, empty_like, full, full_like,
Expand Down Expand Up @@ -117,6 +118,10 @@ def __init__(self, store, path=None, read_only=False, chunk_store=None,
store: BaseStore = _normalize_store_arg(store, zarr_version=zarr_version)
if zarr_version is None:
zarr_version = getattr(store, '_store_version', DEFAULT_ZARR_VERSION)

if zarr_version != 2:
assert_zarr_v3_api_available()

if chunk_store is not None:
chunk_store: BaseStore = _normalize_store_arg(chunk_store, zarr_version=zarr_version)
self._store = store
Expand Down Expand Up @@ -1178,6 +1183,10 @@ def _normalize_store_arg(store, *, storage_options=None, mode="r",
zarr_version=None):
if zarr_version is None:
zarr_version = getattr(store, '_store_version', DEFAULT_ZARR_VERSION)

if zarr_version != 2:
assert_zarr_v3_api_available()

if store is None:
return MemoryStore() if zarr_version == 2 else MemoryStoreV3()
return normalize_store_arg(store,
Expand Down Expand Up @@ -1234,6 +1243,10 @@ def group(store=None, overwrite=False, chunk_store=None,
store = _normalize_store_arg(store, zarr_version=zarr_version)
if zarr_version is None:
zarr_version = getattr(store, '_store_version', DEFAULT_ZARR_VERSION)

if zarr_version != 2:
assert_zarr_v3_api_available()

if zarr_version == 3 and path is None:
raise ValueError(f"path must be provided for a v{zarr_version} group")
path = normalize_storage_path(path)
Expand Down Expand Up @@ -1305,6 +1318,10 @@ def open_group(store=None, mode='a', cache_attrs=True, synchronizer=None, path=N
zarr_version=zarr_version)
if zarr_version is None:
zarr_version = getattr(store, '_store_version', DEFAULT_ZARR_VERSION)

if zarr_version != 2:
assert_zarr_v3_api_available()

if chunk_store is not None:
chunk_store = _normalize_store_arg(chunk_store,
storage_options=storage_options,
Expand Down
22 changes: 15 additions & 7 deletions zarr/tests/test_convenience.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
meta_root,
getsize,
)
from zarr._storage.store import v3_api_available
from zarr._storage.v3 import (
ConsolidatedMetadataStoreV3,
DirectoryStoreV3,
Expand All @@ -44,6 +45,8 @@
)
from zarr.tests.util import have_fsspec

_VERSIONS = v3_api_available and (2, 3) or (2,)


def _init_creation_kwargs(zarr_version):
kwargs = {'zarr_version': zarr_version}
Expand All @@ -52,7 +55,7 @@ def _init_creation_kwargs(zarr_version):
return kwargs


@pytest.mark.parametrize('zarr_version', [2, 3])
@pytest.mark.parametrize('zarr_version', _VERSIONS)
def test_open_array(path_type, zarr_version):

store = tempfile.mkdtemp()
Expand Down Expand Up @@ -86,7 +89,7 @@ def test_open_array(path_type, zarr_version):
open('doesnotexist', mode='r')


@pytest.mark.parametrize("zarr_version", [2, 3])
@pytest.mark.parametrize("zarr_version", _VERSIONS)
def test_open_group(path_type, zarr_version):

store = tempfile.mkdtemp()
Expand Down Expand Up @@ -116,7 +119,7 @@ def test_open_group(path_type, zarr_version):
assert g.read_only


@pytest.mark.parametrize("zarr_version", [2, 3])
@pytest.mark.parametrize("zarr_version", _VERSIONS)
def test_save_errors(zarr_version):
with pytest.raises(ValueError):
# no arrays provided
Expand All @@ -129,6 +132,7 @@ def test_save_errors(zarr_version):
save('data/group.zarr', zarr_version=zarr_version)


@pytest.mark.skipif(not v3_api_available, reason="V3 is disabled")
def test_zarr_v3_save_multiple_unnamed():
x = np.ones(8)
y = np.zeros(8)
Expand All @@ -142,6 +146,7 @@ def test_zarr_v3_save_multiple_unnamed():
assert meta_root + 'dataset/arr_1.array.json' in store


@pytest.mark.skipif(not v3_api_available, reason="V3 is disabled")
def test_zarr_v3_save_errors():
x = np.ones(8)
with pytest.raises(ValueError):
Expand All @@ -155,7 +160,7 @@ def test_zarr_v3_save_errors():
save('data/group.zr3', x, zarr_version=3)


@pytest.mark.parametrize("zarr_version", [2, 3])
@pytest.mark.parametrize("zarr_version", _VERSIONS)
def test_lazy_loader(zarr_version):
foo = np.arange(100)
bar = np.arange(100, 0, -1)
Expand All @@ -173,7 +178,7 @@ def test_lazy_loader(zarr_version):
assert 'LazyLoader: ' in repr(loader)


@pytest.mark.parametrize("zarr_version", [2, 3])
@pytest.mark.parametrize("zarr_version", _VERSIONS)
def test_load_array(zarr_version):
foo = np.arange(100)
bar = np.arange(100, 0, -1)
Expand All @@ -192,7 +197,7 @@ def test_load_array(zarr_version):
assert_array_equal(bar, array)


@pytest.mark.parametrize("zarr_version", [2, 3])
@pytest.mark.parametrize("zarr_version", _VERSIONS)
def test_tree(zarr_version):
kwargs = _init_creation_kwargs(zarr_version)
g1 = zarr.group(**kwargs)
Expand All @@ -205,7 +210,7 @@ def test_tree(zarr_version):
assert str(zarr.tree(g1)) == str(g1.tree())


@pytest.mark.parametrize('zarr_version', [2, 3])
@pytest.mark.parametrize('zarr_version', _VERSIONS)
@pytest.mark.parametrize('stores_from_path', [False, True])
@pytest.mark.parametrize(
'with_chunk_store,listable',
Expand Down Expand Up @@ -531,6 +536,7 @@ def test_if_exists(self):
copy_store(source, dest, if_exists='foobar')


@pytest.mark.skipif(not v3_api_available, reason="V3 is disabled")
class TestCopyStoreV3(TestCopyStore):

_version = 3
Expand Down Expand Up @@ -666,6 +672,7 @@ def test_copy_all():
assert destination_group.subgroup.attrs["info"] == "sub attrs"


@pytest.mark.skipif(not v3_api_available, reason="V3 is disabled")
def test_copy_all_v3():
"""
https://github.com/zarr-developers/zarr-python/issues/269
Expand Down Expand Up @@ -931,6 +938,7 @@ def test_logging(self, source, dest, tmpdir):
copy(source['foo'], dest, dry_run=True, log=True)


@pytest.mark.skipif(not v3_api_available, reason="V3 is disabled")
class TestCopyV3(TestCopy):

@pytest.fixture(params=['zarr', 'hdf5'])
Expand Down
Loading