11from __future__ import annotations
22
3- from typing import Final , Literal , NotRequired
4-
53from pydantic import BaseModel , field_validator
64from pydantic .experimental .missing_sentinel import MISSING
7- from typing_extensions import TypedDict
8-
9- from eopf_geozarr .data_api .geozarr .common import (
10- ZarrConventionMetadata ,
11- ZarrConventionMetadataJSON ,
12- )
13-
14- ConventionID = Literal ["d35379db-88df-4056-af3a-620245f8e347" ]
15- CONVENTION_ID : Final [ConventionID ] = "d35379db-88df-4056-af3a-620245f8e347"
16-
17- ConventionSchemaURL = Literal [
18- "https://raw.githubusercontent.com/zarr-conventions/multiscales/refs/tags/v1/schema.json"
19- ]
20- CONVENTION_SCHEMA_URL : Final [ConventionSchemaURL ] = (
21- "https://raw.githubusercontent.com/zarr-conventions/multiscales/refs/tags/v1/schema.json"
22- )
23-
24- ConventionSpecURL = Literal ["https://github.com/zarr-conventions/multiscales/blob/v1/README.md" ]
25- CONVENTION_SPEC_URL : Final [ConventionSpecURL ] = (
26- "https://github.com/zarr-conventions/multiscales/blob/v1/README.md"
27- )
28-
29- ConventionDescription = Literal ["Multiscale layout of zarr datasets" ]
30- CONVENTION_DESCRIPTION : Final [ConventionDescription ] = "Multiscale layout of zarr datasets"
31-
32- ConventionName = Literal ["multiscales" ]
33- CONVENTION_NAME : Final [ConventionName ] = "multiscales"
34-
35-
36- class MultiscaleConventionMetadata (ZarrConventionMetadata ):
37- uuid : ConventionID = CONVENTION_ID
38- schema_url : ConventionSchemaURL = CONVENTION_SCHEMA_URL
39- name : ConventionName = CONVENTION_NAME
40- description : ConventionDescription = CONVENTION_DESCRIPTION
41- spec_url : ConventionSpecURL = CONVENTION_SPEC_URL
42-
43-
44- class MultiscaleConventionMetadataJSON (TypedDict ):
45- """
46- A TypedDict representation of the Multiscales convention metadata
47- """
5+ from zarr_cm import ConventionMetadataObject
6+ from zarr_cm import multiscales as multiscales_cm
487
49- uuid : NotRequired [ConventionID ]
50- schema_url : NotRequired [ConventionSchemaURL ]
51- name : NotRequired [ConventionName ]
52- description : NotRequired [ConventionDescription ]
53- spec_url : NotRequired [ConventionSpecURL ]
8+ # Convention constants from zarr-cm
9+ CONVENTION_ID = multiscales_cm .UUID
10+ CONVENTION_SCHEMA_URL = multiscales_cm .SCHEMA_URL
11+ CONVENTION_SPEC_URL = multiscales_cm .SPEC_URL
12+ CONVENTION_NAME = multiscales_cm .CMO ["name" ]
13+ CONVENTION_DESCRIPTION = multiscales_cm .CMO ["description" ]
5414
55-
56- # A final dict representation of the Multiscales convention metadata
57- MULTISCALE_CONVENTION_METADATA : Final [MultiscaleConventionMetadataJSON ] = {
58- "uuid" : CONVENTION_ID ,
59- "schema_url" : CONVENTION_SCHEMA_URL ,
60- "name" : CONVENTION_NAME ,
61- "description" : CONVENTION_DESCRIPTION ,
62- "spec_url" : CONVENTION_SPEC_URL ,
63- }
15+ # Re-export zarr-cm TypedDicts
16+ TransformJSON = multiscales_cm .Transform
17+ ScaleLevelJSON = multiscales_cm .LayoutObject
18+ MultiscalesJSON = multiscales_cm .MultiscalesAttrs
19+ MultiscalesConventionAttrsJSON = multiscales_cm .MultiscalesConventionAttrs
6420
6521
6622class ZarrConventionAttrs (BaseModel ):
67- zarr_conventions : tuple [ZarrConventionMetadata , ...]
23+ zarr_conventions : tuple [ConventionMetadataObject , ...]
6824
6925 model_config = {"extra" : "allow" }
7026
@@ -74,11 +30,6 @@ class Transform(BaseModel):
7430 translation : tuple [float , ...] | MISSING = MISSING
7531
7632
77- class TransformJSON (TypedDict ):
78- scale : NotRequired [tuple [float , ...]]
79- translation : NotRequired [tuple [float , ...]]
80-
81-
8233class ScaleLevel (BaseModel ):
8334 asset : str
8435 derived_from : str | MISSING = MISSING
@@ -88,52 +39,29 @@ class ScaleLevel(BaseModel):
8839 model_config = {"extra" : "allow" }
8940
9041
91- class ScaleLevelJSON (TypedDict ):
92- asset : str
93- derived_from : NotRequired [str ]
94- transform : TransformJSON
95- resampling_method : NotRequired [str ]
96-
97-
9842class Multiscales (BaseModel ):
9943 layout : tuple [ScaleLevel , ...]
10044 resampling_method : str | MISSING = MISSING
10145
10246 model_config = {"extra" : "allow" }
10347
10448
105- class MultiscalesJSON (TypedDict ):
106- version : NotRequired [str ]
107- layout : tuple [ScaleLevelJSON , ...]
108- resampling_method : NotRequired [str ]
109-
110-
11149class MultiscalesAttrs (ZarrConventionAttrs ):
11250 multiscales : Multiscales
11351 model_config = {"extra" : "allow" }
11452
11553 @field_validator ("zarr_conventions" , mode = "after" )
11654 @classmethod
11755 def ensure_multiscales_convention (
118- cls , value : tuple [ZarrConventionMetadata , ...]
119- ) -> tuple [ZarrConventionMetadata , ...]:
56+ cls , value : tuple [ConventionMetadataObject , ...]
57+ ) -> tuple [ConventionMetadataObject , ...]:
12058 """
12159 Iterate over the elements of zarr_conventions and check that at least one of them is
12260 multiscales
12361 """
124- success : bool = False
125- errors : dict [int , ValueError ] = {}
126- for idx , convention_meta in enumerate (value ):
127- try :
128- MultiscaleConventionMetadata (** convention_meta .model_dump ())
129- success = True
130- except ValueError as e :
131- errors [idx ] = e
132- if not success :
133- raise ValueError ("Multiscales convention not found. Errors: " + str (errors ))
62+ expected_uuid = multiscales_cm .CMO ["uuid" ]
63+ if not any (c ["uuid" ] == expected_uuid for c in value ):
64+ raise ValueError (
65+ f"Multiscales convention (uuid={ expected_uuid } ) not found in zarr_conventions"
66+ )
13467 return value
135-
136-
137- class MultiscalesAttrsJSON (TypedDict ):
138- zarr_conventions : tuple [ZarrConventionMetadataJSON , ...]
139- multiscales : MultiscalesJSON
0 commit comments