Skip to content

Commit 290af5c

Browse files
fix collection-search POST model (#803)
1 parent c71a355 commit 290af5c

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## [Unreleased]
44

5+
### Fixed
6+
7+
- Fix collection-search POST request model:
8+
- Fix pydantic model to make sure class variables `_start_date` and `_end_date` not edited (ported from stac-pydantic)
9+
- Fix bbox validation to allow anti-meridian crossing (ported from stac-pydantic)
10+
511
## [5.0.2] - 2025-01-30
612

713
### Fixed

stac_fastapi/extensions/stac_fastapi/extensions/core/collection_search/request.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import attr
77
from fastapi import Query
8-
from pydantic import BaseModel, Field, field_validator
8+
from pydantic import BaseModel, Field, PrivateAttr, ValidationInfo, field_validator
99
from stac_pydantic.api.search import SearchDatetime
1010
from stac_pydantic.shared import BBox
1111
from typing_extensions import Annotated
@@ -64,8 +64,8 @@ class BaseCollectionSearchPostRequest(BaseModel):
6464

6565
# Private properties to store the parsed datetime values.
6666
# Not part of the model schema.
67-
_start_date: Optional[dt] = None
68-
_end_date: Optional[dt] = None
67+
_start_date: Optional[dt] = PrivateAttr(default=None)
68+
_end_date: Optional[dt] = PrivateAttr(default=None)
6969

7070
# Properties to return the private values
7171
@property
@@ -94,35 +94,33 @@ def validate_bbox(cls, v: BBox) -> BBox:
9494
raise ValueError(
9595
"Maximum elevation must greater than minimum elevation"
9696
)
97-
98-
if xmax < xmin:
99-
raise ValueError(
100-
"Maximum longitude must be greater than minimum longitude"
101-
)
97+
# Validate against WGS84
98+
if xmin < -180 or ymin < -90 or xmax > 180 or ymax > 90:
99+
raise ValueError("Bounding box must be within (-180, -90, 180, 90)")
102100

103101
if ymax < ymin:
104102
raise ValueError(
105103
"Maximum longitude must be greater than minimum longitude"
106104
)
107105

108-
# Validate against WGS84
109-
if xmin < -180 or ymin < -90 or xmax > 180 or ymax > 90:
110-
raise ValueError("Bounding box must be within (-180, -90, 180, 90)")
111-
112106
return v
113107

114-
@field_validator("datetime")
108+
@field_validator("datetime", mode="after")
115109
@classmethod
116-
def validate_datetime(cls, value: str) -> str:
110+
def validate_datetime(
111+
cls, value: Optional[str], info: ValidationInfo
112+
) -> Optional[str]:
117113
"""validate datetime."""
118114
# Split on "/" and replace no value or ".." with None
115+
if value is None:
116+
return value
119117
values = [v if v and v != ".." else None for v in value.split("/")]
120118

121119
# If there are more than 2 dates, it's invalid
122120
if len(values) > 2:
123121
raise ValueError(
124-
"""Invalid datetime range. Too many values.
125-
Must match format: {begin_date}/{end_date}"""
122+
"""Invalid datetime range. Too many values. """
123+
"""Must match format: {begin_date}/{end_date}"""
126124
)
127125

128126
# If there is only one date, duplicate to use for both start and end dates
@@ -149,8 +147,8 @@ def validate_datetime(cls, value: str) -> str:
149147
)
150148

151149
# Store the parsed dates
152-
cls._start_date = dates[0]
153-
cls._end_date = dates[1]
150+
info.data["_start_date"] = dates[0]
151+
info.data["_end_date"] = dates[1]
154152

155153
# Return the original string value
156154
return value

stac_fastapi/extensions/tests/test_collection_search.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
from datetime import datetime, timezone
23
from urllib.parse import quote_plus
34

45
import attr
@@ -88,6 +89,19 @@ def post_all_collections(
8889
return search_request.model_dump()
8990

9091

92+
def test_datetime_clean():
93+
# ref: https://github.com/stac-utils/stac-pydantic/issues/170
94+
utcnow = datetime.now(timezone.utc)
95+
utcnow_str = utcnow.isoformat()
96+
search = BaseCollectionSearchPostRequest(datetime=utcnow_str)
97+
assert search.start_date == utcnow
98+
assert search.end_date == utcnow
99+
100+
search = BaseCollectionSearchPostRequest()
101+
assert not search.start_date
102+
assert not search.end_date
103+
104+
91105
def test_collection_search_extension_default():
92106
"""Test GET - /collections endpoint with collection-search ext."""
93107
api = StacApi(

0 commit comments

Comments
 (0)