Repository navigation
Validate Zarr v3 with zarr-python and make zarr an optional extra - #1971
h-mayorquin wants to merge 2 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1971 +/- ##
==========================================
+ Coverage 90.83% 90.92% +0.09%
==========================================
Files 92 92
Lines 14190 14220 +30
==========================================
+ Hits 12889 12930 +41
+ Misses 1301 1290 -11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
is that something to bring up with tensorstore? if that is permitted by Zarr v3 but they reject, is that just an omission or conscious decision to validate additional restrictions/additions beyond it? |
I think it is an omission. tensorstore does not support variable-length data types at all, and there is an issue about it open since 2023: That issue is about Zarr v2 but the limitation is the same, and one of the maintainers said there that supporting variable-length data types "will be quite involved". In Zarr v3, So I don't think there is anything new to bring up with them. For the inspector, I opened #1972 as a draft because of the limit above. |
didn't know about such feature! boosted to 5 and added you to "exclusion list" . FTR: URL https://github.com/dandi/dandi-cli/settings/interaction_limits |
| scope=Scope.FILE, | ||
| path=self.filepath, | ||
| message=( | ||
| f"Validating Zarr assets requires zarr-python 3.x ({found}). " |
There was a problem hiding this comment.
Would we be ok validating zarr v2 as well?
There was a problem hiding this comment.
Yes, zarr-python 3 reads Zarr v2 stores. I checked it with an NWB file written in Zarr v2 by hdmf-zarr, and the existing Zarr v2 tests run with zarr-python 3 in this PR. That is what the use_consolidated=False change below is for.
| # 2.x, such as object arrays with a fill value of 0 or the | ||
| # `json2` codec, both found in NWB files written by hdmf-zarr. | ||
| # `_is_empty_group` already tolerates such members. | ||
| data = zarr.open(str(self.filepath), mode="r", use_consolidated=False) |
There was a problem hiding this comment.
"not sure" on reasoning here as we are changing behavior for which we did not have an issue reported.
There was a problem hiding this comment.
I don't understand the quotes in "not sure", did I write a comment there?
This restores what dandi did with zarr-python 2, where zarr.open never reads .zmetadata:
https://github.com/zarr-developers/zarr-python/blob/3ad97b9c783fecef6e9528c41e44aad417ca2447/zarr/convenience.py#L44-L139
zarr-python 3 reads it by default and can't parse some of the metadata that hdmf-zarr wrote with zarr-python 2. This is something that broke once Kabi's #1653 got merged, we just do not have a test for that and people do not upload too many NWB datasets I guess. I added a test here that fails on the master branch. I am happy to open an issue but the fix is basically here.
It fits here as this PR makes zarr-python 3 required. On master it would require something like this, as use_consolidated does not exist in zarr-python 2:
kwargs = {"use_consolidated": False} if Version(zarr.__version__).major >= 3 else {}
data = zarr.open(str(self.filepath), mode="r", **kwargs)Then we would need to remove it again when we drop zarr-python 2 in this PR.
|
"not sure" yet as could we potentially "do both" and just issue a warning if tensorstore pukes for that unsupported reason? I worry that we might be relaxing validation beyond the underlying issue. |
Dropping tensorstore was already the plan. The tensorstore functions added in #1614 say:
Lines 158 to 159 in 152e941 I am following that plan and I agree with it for the following reasons. tensorstore's check is about what tensorstore can compute with and not about what is valid Zarr. The zarr3 driver matches the data type against its own numeric types and anything else throws an error:
Doing both has its own costs:
But maybe you have a specific check in mind that tensorstore catches and we need? I put an agent to look over the source code of tensorstore. It is stricter when parsing metadata (for example unknown keys inside a codec or blosc settings out of range) but all the cases it found need hand-edited metadata. On the IBL file from #1918 the only arrays tensorstore rejected were the 113 string arrays which are indeed valid. Now that I think about it, doing both does not block us, so I am happy to go with it if you want to cover "unknown unknowns". I think keeping more dependencies goes against your own idea of supporting more systems that moved zarr to an extra in the first place (more dependencies is less or equal environments supported). |
|
Thanks for the detail! I just wish there was a proper Zarr and OME-Zarr in particular validation! ATM our validation is ridiculously trivial unfortunately, so by at least testing against two and only ignoring known "non problems" is somewhat of a "non-relaxing" the original amount of validation. May be check out (address?) while on this trail? ;-) with that, likely we can indeed just drop that . |
|
Yes! This is what I was thinking about while working on this. First I found pydantic-zarr but it is limited on versions: it requires Python 3.12 and pydantic 2.12 (ome-zarr-models for #1409 also requires Python 3.12, and pydantic < 2.13). But then I found zarr-metadata, the package pydantic-zarr builds on:
I can give it a try if you think that's useful. |

tensorstore rejects the string arrays that every NWB file has, and in #1918 I asked whether zarr-python could do the validation instead. This PR validates Zarr v3 arrays with zarr-python, drops
tensorstore, and moveszarrto azarrextra so only validating Zarr assets needspip install "dandi[zarr]". I also open Zarr v2 stores without consolidated metadata as zarr-python 3 can't parse some arrays that hdmf-zarr wrote with zarr-python 2, and raised thenwbinspectorfloor to 0.7.2, the first release that does not requirehdmf-zarr. This should close #1918.I made zarr an extra because of the concern @yarikoptic raised in the DANDI meeting on September 28 about forcing upgrades on users who don't need the new zarr. With the extra,
pip install dandidoes not install zarr at all, and validating a Zarr asset without it gives an error that says to installdandi[zarr]. My preference is still a regular dependency with a floor of 3. zarr 3 runs on Python 3.11 and zarr-python 2 has not had a release since April 2025. So the extra mostly serves environments that pin an unmaintained version, and in exchange everyone who uploads Zarr has one more install step and we have one more code path to maintain. But I am fine with the extra as a first step if that is easier to agree on.Finally, this needs an upgrade of
nwbinspectorto 0.7.2, the first release that does not requirehdmf-zarr, and I am not sure if you want to handle that separately.