Skip to content

Commit ba6850f

Browse files
committed
rely even more on zarr-cm
1 parent 7318c6b commit ba6850f

11 files changed

Lines changed: 32 additions & 152 deletions

File tree

src/eopf_geozarr/data_api/geozarr/common.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from pydantic import AfterValidator, BaseModel, Field, model_validator
2323
from pydantic.experimental.missing_sentinel import MISSING
2424
from typing_extensions import Protocol, runtime_checkable
25-
from zarr_cm import ConventionMetadataObject
2625

2726
from eopf_geozarr.data_api.geozarr.projjson import ProjJSON # noqa: TC001
2827

@@ -40,25 +39,6 @@ class UNSET_TYPE:
4039
GEO_PROJ_VERSION: Final = "0.1"
4140

4241

43-
class ZarrConventionMetadata(BaseModel):
44-
uuid: str | MISSING = MISSING
45-
schema_url: str | MISSING = MISSING
46-
spec_url: str | MISSING = MISSING
47-
name: str | MISSING = MISSING
48-
description: str | MISSING = MISSING
49-
50-
@model_validator(mode="after")
51-
def ensure_identifiable(self) -> Self:
52-
if self.uuid is MISSING and self.schema_url is MISSING and self.spec_url is MISSING:
53-
raise ValueError("At least one of uuid, schema_url, or spec_url must be provided.")
54-
55-
return self
56-
57-
58-
# Re-export from zarr_cm for backwards compatibility
59-
ZarrConventionMetadataJSON = ConventionMetadataObject
60-
61-
6242
class ProjAttrs(BaseModel, extra="allow"):
6343
"""
6444
Zarr attributes for coordinate reference system (CRS) encoding.

src/eopf_geozarr/data_api/geozarr/geoproj.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pydantic import BaseModel, Field, model_validator
88
from zarr_cm import geo_proj
99

10-
from eopf_geozarr.data_api.geozarr.common import ZarrConventionMetadata, is_none
10+
from eopf_geozarr.data_api.geozarr.common import is_none
1111
from eopf_geozarr.data_api.geozarr.projjson import ProjJSON # noqa: TC001
1212

1313
PROJ_UUID = geo_proj.UUID
@@ -16,14 +16,6 @@
1616
ProjConvention = geo_proj.GeoProjAttrs
1717

1818

19-
class ProjConventionMetadata(ZarrConventionMetadata):
20-
uuid: str = geo_proj.CMO["uuid"]
21-
name: str = geo_proj.CMO["name"]
22-
schema_url: str = geo_proj.CMO["schema_url"]
23-
spec_url: str = geo_proj.CMO["spec_url"]
24-
description: str = geo_proj.CMO["description"]
25-
26-
2719
class Proj(BaseModel):
2820
# At least one of code, wkt2, or projjson must be provided
2921
code: str | None = Field(None, alias="proj:code", exclude_if=is_none)

src/eopf_geozarr/data_api/geozarr/multiscales/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
"""Zarr multiscales convention support."""
22

33
from .geozarr import MultiscaleGroupAttrs, MultiscaleMeta
4-
from .zcm import MULTISCALE_CONVENTION_METADATA, Multiscales, ScaleLevel, ScaleLevelJSON
4+
from .zcm import Multiscales, ScaleLevel, ScaleLevelJSON
55

66
__all__ = [
7-
"MULTISCALE_CONVENTION_METADATA",
87
"MultiscaleGroupAttrs",
98
"MultiscaleMeta",
109
"Multiscales",

src/eopf_geozarr/data_api/geozarr/multiscales/geozarr.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
from __future__ import annotations
22

3-
from typing import NotRequired, Self
3+
from typing import TYPE_CHECKING, NotRequired, Self
44

55
from pydantic import BaseModel, model_validator
66
from pydantic.experimental.missing_sentinel import MISSING
77
from typing_extensions import TypedDict
88

9-
from eopf_geozarr.data_api.geozarr.common import ZarrConventionMetadata # noqa: TC001
10-
119
from . import tms, zcm
1210

11+
if TYPE_CHECKING:
12+
from zarr_cm import ConventionMetadataObject
13+
1314

1415
class MultiscaleMeta(BaseModel):
1516
"""
@@ -56,7 +57,7 @@ class MultiscaleGroupAttrs(BaseModel):
5657
multiscales: MultiscaleAttrs
5758
"""
5859

59-
zarr_conventions: tuple[ZarrConventionMetadata, ...] | MISSING = MISSING
60+
zarr_conventions: tuple[ConventionMetadataObject, ...] | MISSING = MISSING
6061
multiscales: MultiscaleMeta
6162

6263
_zcm_multiscales: zcm.Multiscales | None = None

src/eopf_geozarr/data_api/geozarr/multiscales/zcm.py

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
from __future__ import annotations
22

3-
from typing import Final
4-
53
from pydantic import BaseModel, field_validator
64
from pydantic.experimental.missing_sentinel import MISSING
75
from zarr_cm import ConventionMetadataObject
86
from zarr_cm import multiscales as multiscales_cm
97

10-
from eopf_geozarr.data_api.geozarr.common import ZarrConventionMetadata
11-
128
# Convention constants from zarr-cm
139
CONVENTION_ID = multiscales_cm.UUID
1410
CONVENTION_SCHEMA_URL = multiscales_cm.SCHEMA_URL
@@ -22,20 +18,9 @@
2218
MultiscalesJSON = multiscales_cm.MultiscalesAttrs
2319
MultiscalesConventionAttrsJSON = multiscales_cm.MultiscalesConventionAttrs
2420

25-
# A final dict representation of the Multiscales convention metadata
26-
MULTISCALE_CONVENTION_METADATA: Final[ConventionMetadataObject] = multiscales_cm.CMO
27-
28-
29-
class MultiscaleConventionMetadata(ZarrConventionMetadata):
30-
uuid: str = multiscales_cm.CMO["uuid"]
31-
schema_url: str = multiscales_cm.CMO["schema_url"]
32-
name: str = multiscales_cm.CMO["name"]
33-
description: str = multiscales_cm.CMO["description"]
34-
spec_url: str = multiscales_cm.CMO["spec_url"]
35-
3621

3722
class ZarrConventionAttrs(BaseModel):
38-
zarr_conventions: tuple[ZarrConventionMetadata, ...]
23+
zarr_conventions: tuple[ConventionMetadataObject, ...]
3924

4025
model_config = {"extra": "allow"}
4126

@@ -68,20 +53,15 @@ class MultiscalesAttrs(ZarrConventionAttrs):
6853
@field_validator("zarr_conventions", mode="after")
6954
@classmethod
7055
def ensure_multiscales_convention(
71-
cls, value: tuple[ZarrConventionMetadata, ...]
72-
) -> tuple[ZarrConventionMetadata, ...]:
56+
cls, value: tuple[ConventionMetadataObject, ...]
57+
) -> tuple[ConventionMetadataObject, ...]:
7358
"""
7459
Iterate over the elements of zarr_conventions and check that at least one of them is
7560
multiscales
7661
"""
77-
success: bool = False
78-
errors: dict[int, ValueError] = {}
79-
for idx, convention_meta in enumerate(value):
80-
try:
81-
MultiscaleConventionMetadata(**convention_meta.model_dump())
82-
success = True
83-
except ValueError as e:
84-
errors[idx] = e
85-
if not success:
86-
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+
)
8767
return value

src/eopf_geozarr/data_api/geozarr/spatial.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,14 @@
77
from pydantic import BaseModel, Field, model_validator
88
from zarr_cm import spatial as spatial_cm
99

10-
from eopf_geozarr.data_api.geozarr.common import ZarrConventionMetadata, is_none
10+
from eopf_geozarr.data_api.geozarr.common import is_none
1111

1212
SPATIAL_UUID = spatial_cm.UUID
1313

1414
# Re-export the zarr-cm TypedDict for the convention metadata object
1515
SpatialConvention = spatial_cm.SpatialAttrs
1616

1717

18-
class SpatialConventionMetadata(ZarrConventionMetadata):
19-
uuid: str = spatial_cm.CMO["uuid"]
20-
name: str = spatial_cm.CMO["name"]
21-
schema_url: str = spatial_cm.CMO["schema_url"]
22-
spec_url: str = spatial_cm.CMO["spec_url"]
23-
description: str = spatial_cm.CMO["description"]
24-
25-
2618
class Spatial(BaseModel):
2719
dimensions: list[str] = Field(alias="spatial:dimensions") # Required field
2820
bbox: list[float] | None = Field(None, alias="spatial:bbox", exclude_if=is_none)

src/eopf_geozarr/s2_optimization/s2_multiscale.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,20 @@
1515
from dask.array import from_delayed
1616
from pydantic.experimental.missing_sentinel import MISSING
1717
from pyproj import CRS
18+
from zarr_cm import geo_proj
19+
from zarr_cm import multiscales as multiscales_cm
20+
from zarr_cm import spatial as spatial_cm
1821

1922
from eopf_geozarr.conversion.fs_utils import sanitize_dataset_attributes
2023
from eopf_geozarr.conversion.geozarr import (
2124
_create_tile_matrix_limits,
2225
create_native_crs_tile_matrix_set,
2326
)
24-
from eopf_geozarr.data_api.geozarr.geoproj import ProjConventionMetadata
2527
from eopf_geozarr.data_api.geozarr.multiscales import tms, zcm
2628
from eopf_geozarr.data_api.geozarr.multiscales.geozarr import (
2729
MultiscaleGroupAttrs,
2830
MultiscaleMeta,
2931
)
30-
from eopf_geozarr.data_api.geozarr.spatial import SpatialConventionMetadata
3132
from eopf_geozarr.data_api.geozarr.types import (
3233
CF_SCALE_OFFSET_KEYS,
3334
XARRAY_ENCODING_KEYS,
@@ -625,9 +626,9 @@ def add_multiscales_metadata_to_parent(
625626
# Create convention metadata for all three conventions
626627
multiscale_attrs = MultiscaleGroupAttrs(
627628
zarr_conventions=(
628-
zcm.MultiscaleConventionMetadata(),
629-
SpatialConventionMetadata(),
630-
ProjConventionMetadata(),
629+
multiscales_cm.CMO,
630+
spatial_cm.CMO,
631+
geo_proj.CMO,
631632
),
632633
multiscales=MultiscaleMeta(
633634
layout=layout,
@@ -1016,8 +1017,8 @@ def write_geo_metadata(
10161017

10171018
# Add zarr convention declarations
10181019
conventions = [
1019-
SpatialConventionMetadata().model_dump(),
1020-
ProjConventionMetadata().model_dump(),
1020+
spatial_cm.CMO,
1021+
geo_proj.CMO,
10211022
]
10221023
dataset.attrs["zarr_conventions"] = conventions
10231024

tests/test_data_api/test_geoproj.py

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,10 @@
55
from pydantic import ValidationError
66
from pydantic_zarr.core import tuplify_json
77

8-
from eopf_geozarr.data_api.geozarr.geoproj import GeoProj, Proj, ProjConventionMetadata
8+
from eopf_geozarr.data_api.geozarr.geoproj import GeoProj, Proj
99
from tests.test_data_api.conftest import view_json_diff
1010

1111

12-
class TestProjConventionMetadata:
13-
"""Test the ProjConventionMetadata class."""
14-
15-
def test_default_values(self) -> None:
16-
"""Test that default values are correctly set."""
17-
metadata = ProjConventionMetadata()
18-
19-
assert metadata.uuid == "f17cb550-5864-4468-aeb7-f3180cfb622f"
20-
assert metadata.name == "proj:"
21-
assert (
22-
metadata.schema_url
23-
== "https://raw.githubusercontent.com/zarr-experimental/geo-proj/refs/tags/v1/schema.json"
24-
)
25-
assert (
26-
metadata.spec_url == "https://github.com/zarr-experimental/geo-proj/blob/v1/README.md"
27-
)
28-
assert metadata.description == "Coordinate reference system information for geospatial data"
29-
30-
def test_serialization(self) -> None:
31-
"""Test that metadata can be serialized correctly."""
32-
metadata = ProjConventionMetadata()
33-
result = metadata.model_dump()
34-
35-
expected = {
36-
"uuid": "f17cb550-5864-4468-aeb7-f3180cfb622f",
37-
"name": "proj:",
38-
"schema_url": "https://raw.githubusercontent.com/zarr-experimental/geo-proj/refs/tags/v1/schema.json",
39-
"spec_url": "https://github.com/zarr-experimental/geo-proj/blob/v1/README.md",
40-
"description": "Coordinate reference system information for geospatial data",
41-
}
42-
43-
assert result == expected
44-
45-
4612
class TestProj:
4713
"""Test the Proj model class."""
4814

tests/test_data_api/test_geozarr/test_multiscales/test_geozarr.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44
from pydantic.experimental.missing_sentinel import MISSING
5+
from zarr_cm import multiscales as multiscales_cm
56

67
from eopf_geozarr.data_api.geozarr.multiscales import tms, zcm
78
from eopf_geozarr.data_api.geozarr.multiscales.geozarr import (
@@ -27,7 +28,7 @@ def test_multiscale_group_attrs(multiscale_flavor: set[Literal["zcm", "tms"]]) -
2728
),
2829
)
2930
zcm_meta = zcm.Multiscales(layout=layout, resampling_method="nearest").model_dump()
30-
zarr_conventions_meta = (zcm.MULTISCALE_CONVENTION_METADATA,)
31+
zarr_conventions_meta = (multiscales_cm.CMO,)
3132
if "tms" in multiscale_flavor:
3233
tile_matrix_set = tms.TileMatrixSet(
3334
id="example_tms",

tests/test_data_api/test_spatial.py

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,7 @@
55
import pytest
66
from pydantic import ValidationError
77

8-
from eopf_geozarr.data_api.geozarr.spatial import Spatial, SpatialConventionMetadata
9-
10-
11-
class TestSpatialConventionMetadata:
12-
"""Test the SpatialConventionMetadata class."""
13-
14-
def test_default_values(self) -> None:
15-
"""Test that default values are correctly set."""
16-
metadata = SpatialConventionMetadata()
17-
18-
assert metadata.uuid == "689b58e2-cf7b-45e0-9fff-9cfc0883d6b4"
19-
assert metadata.name == "spatial:"
20-
assert (
21-
metadata.schema_url
22-
== "https://raw.githubusercontent.com/zarr-conventions/spatial/refs/tags/v1/schema.json"
23-
)
24-
assert metadata.spec_url == "https://github.com/zarr-conventions/spatial/blob/v1/README.md"
25-
assert metadata.description == "Spatial coordinate information"
26-
27-
def test_serialization(self) -> None:
28-
"""Test that metadata can be serialized correctly."""
29-
metadata = SpatialConventionMetadata()
30-
result = metadata.model_dump()
31-
32-
expected = {
33-
"uuid": "689b58e2-cf7b-45e0-9fff-9cfc0883d6b4",
34-
"name": "spatial:",
35-
"schema_url": "https://raw.githubusercontent.com/zarr-conventions/spatial/refs/tags/v1/schema.json",
36-
"spec_url": "https://github.com/zarr-conventions/spatial/blob/v1/README.md",
37-
"description": "Spatial coordinate information",
38-
}
39-
40-
assert result == expected
8+
from eopf_geozarr.data_api.geozarr.spatial import Spatial
419

4210

4311
class TestSpatial:

0 commit comments

Comments
 (0)