diff --git a/changes/4502.feature.md b/changes/4502.feature.md new file mode 100644 index 0000000000..0cd1108349 --- /dev/null +++ b/changes/4502.feature.md @@ -0,0 +1 @@ +Added public import paths for the metadata classes that `Array.metadata` and `Group.metadata` return: `zarr.metadata.ArrayV2Metadata`, `ArrayV3Metadata`, `ArrayMetadata`, `GroupMetadata`, and `ConsolidatedMetadata`. Added `zarr.abc.codec.ArraySpec`, the chunk description passed to codec methods. The API reference lists the members of each class that are public; construct the metadata classes with `from_dict`. diff --git a/docs/api/zarr/abc/codec.md b/docs/api/zarr/abc/codec.md index d4eaecabe9..619891591c 100644 --- a/docs/api/zarr/abc/codec.md +++ b/docs/api/zarr/abc/codec.md @@ -3,3 +3,21 @@ title: codec --- ::: zarr.abc.codec + options: + filters: + - "!^_[^_]" + - "!^ArraySpec$" + +Codecs receive an `ArraySpec` describing the chunk they encode or decode. The members +listed below are its public API. Its other attributes and its constructor may change +without a deprecation cycle. + +::: zarr.abc.codec.ArraySpec + options: + members: + - shape + - dtype + - fill_value + - ndim + - order + - prototype diff --git a/docs/api/zarr/metadata.md b/docs/api/zarr/metadata.md index 12eb909086..0d5128078b 100644 --- a/docs/api/zarr/metadata.md +++ b/docs/api/zarr/metadata.md @@ -3,4 +3,70 @@ title: metadata --- ::: zarr.metadata + options: + members: false + +The members listed for each class below are its public API. Other attributes and +methods, and the class constructors, may change without a deprecation cycle; build +these objects with `from_dict`. + +::: zarr.metadata.ArrayMetadata + +::: zarr.metadata.ArrayV3Metadata + options: + members: + - shape + - data_type + - dtype + - ndim + - chunks + - shards + - fill_value + - codecs + - attributes + - dimension_names + - storage_transformers + - zarr_format + - node_type + - from_dict + - to_dict + +::: zarr.metadata.ArrayV2Metadata + options: + members: + - shape + - chunks + - shards + - dtype + - ndim + - fill_value + - order + - filters + - compressor + - dimension_separator + - attributes + - zarr_format + - from_dict + - to_dict + +::: zarr.metadata.GroupMetadata + options: + members: + - attributes + - zarr_format + - node_type + - consolidated_metadata + - from_dict + - to_dict + +::: zarr.metadata.ConsolidatedMetadata + options: + members: + - metadata + - flattened_metadata + - kind + - must_understand + - from_dict + - to_dict + ::: zarr.metadata.migrate_v3 diff --git a/src/zarr/abc/codec.py b/src/zarr/abc/codec.py index c5e753d120..a2c4d97e0a 100644 --- a/src/zarr/abc/codec.py +++ b/src/zarr/abc/codec.py @@ -7,6 +7,7 @@ from typing_extensions import ReadOnly, TypedDict from zarr.abc.metadata import Metadata +from zarr.core.array_spec import ArraySpec from zarr.core.buffer import Buffer, NDBuffer from zarr.core.common import NamedConfig, concurrent_map from zarr.core.config import config @@ -16,7 +17,6 @@ from typing import Self from zarr.abc.store import ByteGetter, ByteSetter, Store - from zarr.core.array_spec import ArraySpec from zarr.core.dtype.wrapper import TBaseDType, TBaseScalar, ZDType from zarr.core.indexing import SelectorTuple from zarr.core.metadata import ArrayMetadata @@ -27,6 +27,7 @@ "ArrayBytesCodec", "ArrayBytesCodecPartialDecodeMixin", "ArrayBytesCodecPartialEncodeMixin", + "ArraySpec", "BaseCodec", "BytesBytesCodec", "CodecInput", diff --git a/src/zarr/metadata/__init__.py b/src/zarr/metadata/__init__.py index e69de29bb2..d63afa0c10 100644 --- a/src/zarr/metadata/__init__.py +++ b/src/zarr/metadata/__init__.py @@ -0,0 +1,18 @@ +"""Models of the metadata documents that describe Zarr arrays and groups. + +`zarr.Array.metadata` is an `ArrayV2Metadata` or an `ArrayV3Metadata`, and +`zarr.Group.metadata` is a `GroupMetadata`. Construct these objects with `from_dict`. +""" + +from zarr.core.group import ConsolidatedMetadata, GroupMetadata +from zarr.core.metadata import ArrayMetadata +from zarr.core.metadata.v2 import ArrayV2Metadata +from zarr.core.metadata.v3 import ArrayV3Metadata + +__all__ = [ + "ArrayMetadata", + "ArrayV2Metadata", + "ArrayV3Metadata", + "ConsolidatedMetadata", + "GroupMetadata", +] diff --git a/tests/test_public_exports.py b/tests/test_public_exports.py new file mode 100644 index 0000000000..a842f5e137 --- /dev/null +++ b/tests/test_public_exports.py @@ -0,0 +1,45 @@ +"""Public import paths for types that the public API returns or passes to extensions.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +import pytest + +import zarr.abc.codec +import zarr.metadata +from zarr.core.array_spec import ArraySpec +from zarr.core.group import ConsolidatedMetadata, GroupMetadata +from zarr.core.metadata import ArrayMetadata +from zarr.core.metadata.v2 import ArrayV2Metadata +from zarr.core.metadata.v3 import ArrayV3Metadata + +if TYPE_CHECKING: + from zarr.types import ZarrFormat + + +@pytest.mark.parametrize( + ("public", "private"), + [ + (zarr.metadata.ArrayMetadata, ArrayMetadata), + (zarr.metadata.ArrayV2Metadata, ArrayV2Metadata), + (zarr.metadata.ArrayV3Metadata, ArrayV3Metadata), + (zarr.metadata.ConsolidatedMetadata, ConsolidatedMetadata), + (zarr.metadata.GroupMetadata, GroupMetadata), + (zarr.abc.codec.ArraySpec, ArraySpec), + ], +) +def test_public_path_is_the_implementation(public: Any, private: Any) -> None: + """Each public name is the object zarr itself uses, so isinstance checks agree.""" + assert public is private + + +@pytest.mark.parametrize("zarr_format", [2, 3]) +def test_array_and_group_metadata_types(zarr_format: ZarrFormat) -> None: + """The metadata of arrays and groups is an instance of a public metadata type.""" + store: dict[str, Any] = {} + group = zarr.group(store=store, zarr_format=zarr_format) + array = group.create_array("a", shape=(2,), dtype="i4") + expected = zarr.metadata.ArrayV2Metadata if zarr_format == 2 else zarr.metadata.ArrayV3Metadata + assert isinstance(array.metadata, expected) + assert isinstance(group.metadata, zarr.metadata.GroupMetadata)