Skip to content

Commit a008942

Browse files
committed
Factor out code for guessing zarr version
1 parent ee9c182 commit a008942

File tree

1 file changed

+44
-45
lines changed

1 file changed

+44
-45
lines changed

src/zarr/core/group.py

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,30 @@ def _parse_async_node(
131131
raise TypeError(f"Unknown node type, got {type(node)}")
132132

133133

134+
async def _get_zarr_version(store_path: StorePath) -> Literal[2, 3]:
135+
"""
136+
Guess Zarr format from present metadata files in a Store.
137+
"""
138+
(
139+
zarr_json_bytes,
140+
zgroup_bytes,
141+
) = await asyncio.gather(
142+
(store_path / ZARR_JSON).exists(),
143+
(store_path / ZGROUP_JSON).exists(),
144+
)
145+
if zarr_json_bytes and zgroup_bytes:
146+
# warn and favor v3
147+
msg = f"Both zarr.json (Zarr format 3) and .zgroup (Zarr format 2) metadata objects exist at {store_path}. Zarr format 3 will be used."
148+
warnings.warn(msg, category=ZarrUserWarning, stacklevel=1)
149+
if not zarr_json_bytes and not zgroup_bytes:
150+
raise FileNotFoundError(f"could not find zarr.json or .zgroup objects in {store_path}")
151+
# set zarr_format based on which keys were found
152+
if zarr_json_bytes:
153+
return 3
154+
else:
155+
return 2
156+
157+
134158
@dataclass(frozen=True)
135159
class ConsolidatedMetadata:
136160
"""
@@ -512,6 +536,14 @@ async def open(
512536
to load consolidated metadata from a non-default key.
513537
"""
514538
store_path = await make_store_path(store)
539+
# Guess zarr_format if not passed explicitly
540+
if zarr_format is None:
541+
zarr_format = await _get_zarr_version(store_path)
542+
return await cls.open(
543+
store=store, zarr_format=zarr_format, use_consolidated=use_consolidated
544+
)
545+
assert zarr_format is not None
546+
515547
if not store_path.store.supports_consolidated_metadata:
516548
# Fail if consolidated metadata was requested but the Store doesn't support it
517549
if use_consolidated:
@@ -523,12 +555,11 @@ async def open(
523555
# if use_consolidated was None (optional), the Store dictates it doesn't want consolidation
524556
use_consolidated = False
525557

526-
consolidated_key = ZMETADATA_V2_JSON
527-
528-
if (zarr_format == 2 or zarr_format is None) and isinstance(use_consolidated, str):
529-
consolidated_key = use_consolidated
530-
531558
if zarr_format == 2:
559+
consolidated_key = ZMETADATA_V2_JSON
560+
if isinstance(use_consolidated, str):
561+
consolidated_key = use_consolidated
562+
532563
paths = [store_path / ZGROUP_JSON, store_path / ZATTRS_JSON]
533564
if use_consolidated or use_consolidated is None:
534565
paths.append(store_path / consolidated_key)
@@ -545,43 +576,6 @@ async def open(
545576
else:
546577
maybe_consolidated_metadata_bytes = None
547578

548-
elif zarr_format == 3:
549-
zarr_json_bytes = await (store_path / ZARR_JSON).get()
550-
if zarr_json_bytes is None:
551-
raise FileNotFoundError(store_path)
552-
elif zarr_format is None:
553-
(
554-
zarr_json_bytes,
555-
zgroup_bytes,
556-
zattrs_bytes,
557-
maybe_consolidated_metadata_bytes,
558-
) = await asyncio.gather(
559-
(store_path / ZARR_JSON).get(),
560-
(store_path / ZGROUP_JSON).get(),
561-
(store_path / ZATTRS_JSON).get(),
562-
(store_path / str(consolidated_key)).get(),
563-
)
564-
if zarr_json_bytes is not None and zgroup_bytes is not None:
565-
# warn and favor v3
566-
msg = f"Both zarr.json (Zarr format 3) and .zgroup (Zarr format 2) metadata objects exist at {store_path}. Zarr format 3 will be used."
567-
warnings.warn(msg, category=ZarrUserWarning, stacklevel=1)
568-
if zarr_json_bytes is None and zgroup_bytes is None:
569-
raise FileNotFoundError(
570-
f"could not find zarr.json or .zgroup objects in {store_path}"
571-
)
572-
# set zarr_format based on which keys were found
573-
if zarr_json_bytes is not None:
574-
zarr_format = 3
575-
else:
576-
zarr_format = 2
577-
else:
578-
msg = f"Invalid value for 'zarr_format'. Expected 2, 3, or None. Got '{zarr_format}'." # type: ignore[unreachable]
579-
raise MetadataValidationError(msg)
580-
581-
if zarr_format == 2:
582-
# this is checked above, asserting here for mypy
583-
assert zgroup_bytes is not None
584-
585579
if use_consolidated and maybe_consolidated_metadata_bytes is None:
586580
# the user requested consolidated metadata, but it was missing
587581
raise ValueError(consolidated_key)
@@ -594,9 +588,11 @@ async def open(
594588
return cls._from_bytes_v2(
595589
store_path, zgroup_bytes, zattrs_bytes, maybe_consolidated_metadata_bytes
596590
)
597-
else:
598-
# V3 groups are comprised of a zarr.json object
599-
assert zarr_json_bytes is not None
591+
592+
elif zarr_format == 3:
593+
zarr_json_bytes = await (store_path / ZARR_JSON).get()
594+
if zarr_json_bytes is None:
595+
raise FileNotFoundError(store_path)
600596
if not isinstance(use_consolidated, bool | None):
601597
raise TypeError("use_consolidated must be a bool or None for Zarr format 3.")
602598

@@ -605,6 +601,9 @@ async def open(
605601
zarr_json_bytes,
606602
use_consolidated=use_consolidated,
607603
)
604+
else:
605+
msg = f"Invalid value for 'zarr_format'. Expected 2, 3, or None. Got '{zarr_format}'." # type: ignore[unreachable]
606+
raise MetadataValidationError(msg)
608607

609608
@classmethod
610609
def _from_bytes_v2(

0 commit comments

Comments
 (0)