Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/mlcast-community/mlcast-dataset-validator)

### Fixed

- Detect Zarr v3 format from store files (`zarr.json`) instead of relying on `getattr(ds, "zarr_format", 2)` which always defaulted to v2, causing v3 stores to incorrectly fail the consolidated metadata check [\#27](https://github.com/mlcast-community/mlcast-dataset-validator/pull/27), @franchg

## [v0.2.0](https://github.com/mlcast-community/mlcast-dataset-validator/releases/tag/v0.2.0)

This release makes the validator easier to use from python and the specs defined in the validator easier to access. This done by allowing for direct calls to validation functions with `xr.Dataset` input. And introducing a cli arg to print selected spec to terminal and adding CI rendering of specs to HTML that are deployted to GitHub Pages for linkable, readable spec docs.
Expand Down
26 changes: 25 additions & 1 deletion mlcast_dataset_validator/checks/global_attributes/zarr_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ def has_consolidated_metadata(ds, storage_options=None):
return fs.exists(f"{store_root}/.zmetadata")


def _detect_zarr_format(ds, storage_options=None):
"""Detect Zarr format version from the store on disk.

Zarr v3 stores have a ``zarr.json`` file at the root, while v2 stores
have ``.zgroup``. xarray does not expose the format version as a
dataset attribute, so we inspect the store directly.
"""
store_path = ds.encoding.get("source")
if store_path is None:
return 2 # cannot determine, assume v2

if storage_options is None:
storage_options = ds.encoding.get("storage_options")

fs, _, paths = fsspec.get_fs_token_paths(
store_path, storage_options=storage_options
)
store_root = paths[0].rstrip("/")

if fs.exists(f"{store_root}/zarr.json"):
return 3
return 2


@log_function_call
def check_zarr_format(
ds: xr.Dataset,
Expand All @@ -55,7 +79,7 @@ def check_zarr_format(
if storage_options is None:
storage_options = ds.encoding.get("storage_options")

zarr_format = getattr(ds, "zarr_format", 2) # Default to Zarr v2
zarr_format = _detect_zarr_format(ds, storage_options)
if zarr_format in allowed_versions:
report.add(
SECTION_ID,
Expand Down
Loading