-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathorder.py
More file actions
154 lines (114 loc) · 4.26 KB
/
order.py
File metadata and controls
154 lines (114 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from __future__ import annotations
import datetime
from collections.abc import Iterator
from enum import StrEnum
from typing import Any, Generic, Literal, TypeVar
from geojson_pydantic.base import _GeoJsonBase
from geojson_pydantic.geometries import Geometry
from pydantic import (
AwareDatetime,
BaseModel,
ConfigDict,
Field,
StrictStr,
field_validator,
)
from .constants import STAPI_VERSION
from .datetime_interval import DatetimeInterval
from .filter import CQL2Filter
from .opportunity import OpportunityProperties
from .shared import Link
Props = TypeVar("Props", bound=dict[str, Any] | BaseModel)
Geom = TypeVar("Geom", bound=Geometry)
class OrderParameters(BaseModel):
model_config = ConfigDict(extra="forbid")
OPP = TypeVar("OPP", bound=OpportunityProperties)
ORP = TypeVar("ORP", bound=OrderParameters)
class OrderStatusCode(StrEnum):
received = "received"
accepted = "accepted"
rejected = "rejected"
completed = "completed"
cancelled = "cancelled"
scheduled = "scheduled"
held = "held"
processing = "processing"
reserved = "reserved"
tasked = "tasked"
user_cancelled = "user_cancelled"
expired = "expired"
failed = "failed"
class OrderStatus(BaseModel):
timestamp: AwareDatetime
status_code: OrderStatusCode
reason_code: str | None = None
reason_text: str | None = None
links: list[Link] = Field(default_factory=list)
model_config = ConfigDict(extra="allow")
@classmethod
def new(
cls, status_code: OrderStatusCode, reason_code: str | None = None, reason_text: str | None = None
) -> OrderStatus:
"""Creates a new order status with timestamp set to now in UTC."""
return OrderStatus(
timestamp=datetime.datetime.now(tz=datetime.UTC),
status_code=status_code,
reason_code=reason_code,
reason_text=reason_text,
)
T = TypeVar("T", bound=OrderStatus)
class OrderStatuses(BaseModel, Generic[T]):
statuses: list[T]
links: list[Link] = Field(default_factory=list)
class OrderSearchParameters(BaseModel):
datetime: DatetimeInterval
geometry: Geometry
# TODO: validate the CQL2 filter?
filter: CQL2Filter | None = None # type: ignore [type-arg]
class OrderProperties(BaseModel, Generic[T]):
product_id: str
created: AwareDatetime
status: T
search_parameters: OrderSearchParameters
opportunity_properties: dict[str, Any]
order_parameters: dict[str, Any]
model_config = ConfigDict(extra="allow")
# derived from geojson_pydantic.Feature
class Order(_GeoJsonBase, Generic[T]):
# 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"
stapi_type: Literal["Order"] = "Order"
stapi_version: str = STAPI_VERSION
geometry: Geometry = Field(...)
properties: OrderProperties[T] = 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
# derived from geojson_pydantic.FeatureCollection
class OrderCollection(_GeoJsonBase, Generic[T]):
type: Literal["FeatureCollection"] = "FeatureCollection"
features: list[Order[T]]
links: list[Link] = Field(default_factory=list)
def __iter__(self) -> Iterator[Order[T]]: # 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[T]:
"""get feature at a given index"""
return self.features[index]
class OrderPayload(BaseModel, Generic[ORP]):
datetime: DatetimeInterval | None = Field(examples=["2018-02-12T00:00:00Z/2018-03-18T12:31:12Z"], default=None)
geometry: Geometry | None = None
# TODO: validate the CQL2 filter?
filter: CQL2Filter | None = None # type: ignore [type-arg]
order_parameters: ORP
model_config = ConfigDict(strict=True)