Skip to content

Commit 92ca596

Browse files
committed
use enum values and fix fields pydantic validation
1 parent 3f1ffa3 commit 92ca596

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

CHANGES.md

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

33
## [Unreleased]
44

5+
### Fixed
6+
7+
- use Relation's `value` for `POST` prev/next links
8+
- return `JSONResponse` directly from `/items` endpoint when `fields` parameter is pass and avoid Pydantic validation
9+
10+
### Changed
11+
12+
- avoid re-use of internal `CoreCrudClient.post_search` in `CoreCrudClient.get_search` method to allow customization
13+
514
## [4.0.1] - 2025-02-06
615

716
### Added

stac_fastapi/pgstac/core.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
import orjson
1010
from asyncpg.exceptions import InvalidDatetimeFormatError
1111
from buildpg import render
12-
from fastapi import HTTPException, Request
13-
from pydantic import ValidationError
12+
from fastapi import Request
1413
from pygeofilter.backends.cql2_json import to_cql2
1514
from pygeofilter.parsers.cql2_text import parse as parse_cql2_text
1615
from pypgstac.hydration import hydrate
@@ -401,7 +400,14 @@ async def item_collection(
401400
).get_links(extra_links=item_collection["links"])
402401
item_collection["links"] = links
403402

404-
return item_collection
403+
# If we have the `fields` extension enabled
404+
# we need to avoid Pydantic validation because the
405+
# Items might not be a valid STAC Item objects
406+
if fields := getattr(search_request, "fields", None):
407+
if fields.include or fields.exclude:
408+
return JSONResponse(item_collection) # type: ignore
409+
410+
return ItemCollection(**item_collection)
405411

406412
async def get_item(
407413
self, item_id: str, collection_id: str, request: Request, **kwargs
@@ -500,15 +506,17 @@ async def get_search(
500506
filter_lang=filter_lang,
501507
)
502508

503-
# Do the request
504-
try:
505-
search_request = self.pgstac_search_model(**clean)
506-
except ValidationError as e:
507-
raise HTTPException(
508-
status_code=400, detail=f"Invalid parameters provided {e}"
509-
) from e
509+
search_request = self.pgstac_search_model(**clean)
510+
item_collection = await self._search_base(search_request, request=request)
511+
512+
# If we have the `fields` extension enabled
513+
# we need to avoid Pydantic validation because the
514+
# Items might not be a valid STAC Item objects
515+
if fields := getattr(search_request, "fields", None):
516+
if fields.include or fields.exclude:
517+
return JSONResponse(item_collection) # type: ignore
510518

511-
return await self.post_search(search_request, request=request)
519+
return ItemCollection(**item_collection)
512520

513521
def _clean_search_args( # noqa: C901
514522
self,

stac_fastapi/pgstac/models/links.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ def link_next(self) -> Optional[Dict[str, Any]]:
140140

141141
if method == "POST":
142142
return {
143-
"rel": Relations.next,
144-
"type": MimeTypes.geojson,
143+
"rel": Relations.next.value,
144+
"type": MimeTypes.geojson.value,
145145
"method": method,
146146
"href": f"{self.request.url}",
147147
"body": {**self.request.postbody, "token": f"next:{self.next}"},
@@ -164,8 +164,8 @@ def link_prev(self) -> Optional[Dict[str, Any]]:
164164

165165
if method == "POST":
166166
return {
167-
"rel": Relations.previous,
168-
"type": MimeTypes.geojson,
167+
"rel": Relations.previous.value,
168+
"type": MimeTypes.geojson.value,
169169
"method": method,
170170
"href": f"{self.request.url}",
171171
"body": {**self.request.postbody, "token": f"prev:{self.prev}"},

tests/resources/test_item.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,13 @@ async def test_field_extension_get(app_client, load_test_data, load_test_collect
10721072
)
10731073
assert resp.status_code == 201
10741074

1075+
params = {"fields": "+properties.proj:epsg,+properties.gsd,+collection"}
1076+
resp = await app_client.get(
1077+
f"/collections/{test_item['collection']}/items", params=params
1078+
)
1079+
feat_properties = resp.json()["features"][0]["properties"]
1080+
assert not set(feat_properties) - {"proj:epsg", "gsd", "datetime"}
1081+
10751082
params = {"fields": "+properties.proj:epsg,+properties.gsd,+collection"}
10761083
resp = await app_client.get("/search", params=params)
10771084
feat_properties = resp.json()["features"][0]["properties"]

0 commit comments

Comments
 (0)