Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor Order and OrderCollection to not extend Feature and FeatureCollection #111

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ none
- Order field `id` must be a string, instead of previously allowing int. This is because while an
order ID may an integral numeric value, it is not a "number" in the sense that math will be performed
order ID values, so string represents this better.
- Order and OrderCollection extend _GeoJsonBase instead of Feature and FeatureCollection, to allow for tighter
constraints on fields

### Deprecated

Expand Down
41 changes: 37 additions & 4 deletions src/stapi_fastapi/models/order.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
from enum import Enum
from typing import Any, Generic, Literal, Optional, TypeVar
from typing import Any, Dict, Generic, Iterator, Literal, Optional, TypeVar, Union

from geojson_pydantic import Feature, FeatureCollection
from geojson_pydantic.base import _GeoJsonBase
from geojson_pydantic.geometries import Geometry
from pydantic import (
AwareDatetime,
BaseModel,
ConfigDict,
Field,
StrictStr,
field_validator,
)

from stapi_fastapi.models.opportunity import OpportunityProperties
from stapi_fastapi.models.shared import Link
from stapi_fastapi.types.datetime_interval import DatetimeInterval
from stapi_fastapi.types.filter import CQL2Filter

Props = TypeVar("Props", bound=Union[Dict[str, Any], BaseModel])
Geom = TypeVar("Geom", bound=Geometry)


class OrderParameters(BaseModel):
model_config = ConfigDict(extra="forbid")
Expand Down Expand Up @@ -71,14 +75,43 @@ class OrderProperties(BaseModel):
model_config = ConfigDict(extra="allow")


class Order(Feature[Geometry, OrderProperties]):
# derived from geojson_pydantic.Feature
class Order(_GeoJsonBase):
# We need to enforce that orders have an id defined, as that is required to
# retrieve them via the API
id: StrictStr
type: Literal["Feature"] = "Feature"

geometry: Geometry | None = Field(...)
properties: OrderProperties | None = Field(...)

links: list[Link] = Field(default_factory=list)

__geojson_exclude_if_none__ = {"bbox", "id"}

@field_validator("geometry", mode="before")
def set_geometry(cls, geometry: Any) -> Any:
"""set geometry from geo interface or input"""
if hasattr(geometry, "__geo_interface__"):
return geometry.__geo_interface__

return geometry

class OrderCollection(FeatureCollection[Order]):

# derived from geojson_pydantic.FeatureCollection
class OrderCollection(_GeoJsonBase):
type: Literal["FeatureCollection"] = "FeatureCollection"
features: list[Order]
links: list[Link] = Field(default_factory=list)

def __iter__(self) -> Iterator[Order]: # type: ignore [override]
"""iterate over features"""
return iter(self.features)

def __len__(self) -> int:
"""return features length"""
return len(self.features)

def __getitem__(self, index: int) -> Order:
"""get feature at a given index"""
return self.features[index]