Skip to content

Commit

Permalink
Merge commit 'f4426b43b4aa89ae56ea943ac4e543ea209d0c2c' of https://gi…
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentsarago committed May 20, 2024
2 parents 72d1ace + f4426b4 commit 3e6648d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 20 deletions.
11 changes: 1 addition & 10 deletions stac_pydantic/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from geojson_pydantic import Feature
from pydantic import AnyUrl, ConfigDict, Field, model_serializer, model_validator
from typing_extensions import Self

from stac_pydantic.links import Links
from stac_pydantic.shared import (
Expand All @@ -20,20 +19,12 @@ class ItemProperties(StacCommonMetadata):
https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/item-spec.md#properties-object
"""

# Overide the datetime field to be required
datetime: Optional[UtcDatetime]

# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(extra="allow")

@model_validator(mode="after")
def validate_datetime(self) -> Self:
if not self.datetime and (not self.start_datetime or not self.end_datetime):
raise ValueError(
"start_datetime and end_datetime must be specified when datetime is null"
)

return self


class Item(Feature, StacBaseModel):
"""
Expand Down
45 changes: 40 additions & 5 deletions stac_pydantic/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
BaseModel,
ConfigDict,
Field,
model_validator,
)
from typing_extensions import Annotated
from typing_extensions import Annotated, Self

from stac_pydantic.utils import AutoValueEnum

Expand Down Expand Up @@ -126,22 +127,49 @@ class Provider(StacBaseModel):

class StacCommonMetadata(StacBaseModel):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md#date-and-time-range
https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md
"""

# Basic
title: Optional[str] = None
description: Optional[str] = None
start_datetime: Optional[UtcDatetime] = None
end_datetime: Optional[UtcDatetime] = None
# Date and Time
datetime: Optional[UtcDatetime] = None
created: Optional[UtcDatetime] = None
updated: Optional[UtcDatetime] = None
# Date and Time Range
start_datetime: Optional[UtcDatetime] = None
end_datetime: Optional[UtcDatetime] = None
# Provider
providers: Optional[List[Provider]] = None
# Instrument
platform: Optional[str] = None
instruments: Optional[List[str]] = None
constellation: Optional[str] = None
mission: Optional[str] = None
providers: Optional[List[Provider]] = None
gsd: Optional[float] = Field(None, gt=0)

@model_validator(mode="after")
def validate_datetime_or_start_end(self) -> Self:
# When datetime is null, start_datetime and end_datetime must be specified
if not self.datetime and (not self.start_datetime or not self.end_datetime):
raise ValueError(
"start_datetime and end_datetime must be specified when datetime is null"
)

return self

@model_validator(mode="after")
def validate_start_end(self) -> Self:
# Using one of start_datetime or end_datetime requires the use of the other
if (self.start_datetime and not self.end_datetime) or (
not self.start_datetime and self.end_datetime
):
raise ValueError(
"use of start_datetime or end_datetime requires the use of the other"
)
return self


class Asset(StacCommonMetadata):
"""
Expand All @@ -157,3 +185,10 @@ class Asset(StacCommonMetadata):
model_config = ConfigDict(
populate_by_name=True, use_enum_values=True, extra="allow"
)

@model_validator(mode="after")
def validate_datetime_or_start_end(self) -> Self:
# Overriding the parent method to avoid requiring datetime or start/end_datetime
# Additional fields MAY be added on the Asset object, but are not required.
# https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/item-spec.md#additional-fields-for-assets
return self
30 changes: 25 additions & 5 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from stac_pydantic import Collection, Item, ItemProperties
from stac_pydantic.extensions import validate_extensions
from stac_pydantic.links import Link, Links
from stac_pydantic.shared import MimeTypes
from stac_pydantic.shared import MimeTypes, StacCommonMetadata

from .conftest import dict_match, request

Expand Down Expand Up @@ -169,10 +169,15 @@ def test_geo_interface() -> None:
"start_datetime": "2024-01-01T00:00:00Z",
"end_datetime": "2024-01-02T00:00:00Z",
},
{
"datetime": "2024-01-01T00:00:00Z",
"start_datetime": "2024-01-01T00:00:00Z",
"end_datetime": "2024-01-02T00:00:00Z",
},
],
)
def test_item_properties_dates(args) -> None:
ItemProperties(**args)
def test_stac_common_dates(args) -> None:
StacCommonMetadata(**args)


@pytest.mark.parametrize(
Expand All @@ -183,12 +188,27 @@ def test_item_properties_dates(args) -> None:
{"datetime": None, "end_datetime": "2024-01-01T00:00:00Z"},
],
)
def test_item_properties_no_dates(args) -> None:
def test_stac_common_no_dates(args) -> None:
with pytest.raises(
ValueError,
match="start_datetime and end_datetime must be specified when datetime is null",
):
ItemProperties(**args)
StacCommonMetadata(**args)


@pytest.mark.parametrize(
"args",
[
{"datetime": "2024-01-01T00:00:00Z", "start_datetime": "2024-01-01T00:00:00Z"},
{"datetime": "2024-01-01T00:00:00Z", "end_datetime": "2024-01-01T00:00:00Z"},
],
)
def test_stac_common_start_and_end(args) -> None:
with pytest.raises(
ValueError,
match="use of start_datetime or end_datetime requires the use of the other",
):
StacCommonMetadata(**args)


def test_declared_model() -> None:
Expand Down

0 comments on commit 3e6648d

Please sign in to comment.