Skip to content

Commit c55c253

Browse files
add description and examples (#734)
* add description and examples * update docs * update changelog * Update stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py
1 parent 599742c commit c55c253

File tree

10 files changed

+293
-47
lines changed

10 files changed

+293
-47
lines changed

CHANGES.md

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

33
## [Unreleased] - TBD
44

5+
* add more openapi metadata in input models [#734](https://github.com/stac-utils/stac-fastapi/pull/734)
6+
57
## [3.0.0b2] - 2024-07-09
68

79
### Changed

docs/src/migrations/v3.0.0.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,12 @@ e.g the BaseSearchGetRequest, default for the `GET - /search` endpoint:
9595
class BaseSearchGetRequest(APIRequest):
9696
"""Base arguments for GET Request."""
9797

98-
collections: Annotated[Optional[str], Query()] = attr.ib(
99-
default=None, converter=str2list
100-
)
101-
ids: Annotated[Optional[str], Query()] = attr.ib(default=None, converter=str2list)
102-
bbox: Annotated[Optional[BBox], Query()] = attr.ib(default=None, converter=str2bbox)
98+
collections: Optional[List[str]] = attr.ib(default=None, converter=_collection_converter)
99+
ids: Optional[List[str]] = attr.ib(default=None, converter=_ids_converter)
100+
bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter)
103101
intersects: Annotated[Optional[str], Query()] = attr.ib(default=None)
104-
datetime: Annotated[Optional[DateTimeType], Query()] = attr.ib(
105-
default=None, converter=str_to_interval
102+
datetime: Optional[DateTimeType] = attr.ib(
103+
default=None, converter=_datetime_converter
106104
)
107105
limit: Annotated[Optional[int], Query()] = attr.ib(default=10)
108106
```
@@ -115,6 +113,26 @@ class SomeRequest(APIRequest):
115113
user_number: Annotated[Optional[int], Query(alias="user-number")] = attr.ib(default=None)
116114
```
117115

116+
Note: when an attribute has a `converter` (e.g `_ids_converter`), the **Type Hint** should be defined directly in the converter:
117+
118+
```python
119+
def _ids_converter(
120+
val: Annotated[
121+
Optional[str],
122+
Query(
123+
description="Array of Item ids to return.",
124+
),
125+
] = None,
126+
) -> Optional[List[str]]:
127+
return str2list(val)
128+
129+
@attr.s
130+
class BaseSearchGetRequest(APIRequest):
131+
"""Base arguments for GET Request."""
132+
133+
ids: Optional[List[str]] = attr.ib(default=None, converter=_ids_converter)
134+
```
135+
118136
## Filter extension
119137

120138
`default_includes` attribute has been removed from the `ApiSettings` object. If you need `defaults` includes you can overwrite the `FieldExtension` models (see https://github.com/stac-utils/stac-fastapi/pull/706).

stac_fastapi/api/stac_fastapi/api/models.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
APIRequest,
1515
BaseSearchGetRequest,
1616
BaseSearchPostRequest,
17-
str2bbox,
18-
str_to_interval,
17+
_bbox_converter,
18+
_datetime_converter,
1919
)
2020

2121
try:
@@ -114,9 +114,9 @@ class ItemCollectionUri(APIRequest):
114114

115115
collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
116116
limit: Annotated[int, Query()] = attr.ib(default=10)
117-
bbox: Annotated[Optional[BBox], Query()] = attr.ib(default=None, converter=str2bbox)
118-
datetime: Annotated[Optional[DateTimeType], Query()] = attr.ib(
119-
default=None, converter=str_to_interval
117+
bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter)
118+
datetime: Optional[DateTimeType] = attr.ib(
119+
default=None, converter=_datetime_converter
120120
)
121121

122122

stac_fastapi/extensions/stac_fastapi/extensions/core/aggregation/request.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,26 @@
1414
)
1515

1616

17+
def _agg_converter(
18+
val: Annotated[
19+
Optional[str],
20+
Query(description="A list of aggregations to compute and return."),
21+
] = None,
22+
) -> Optional[List[str]]:
23+
return str2list(val)
24+
25+
1726
@attr.s
1827
class AggregationExtensionGetRequest(BaseSearchGetRequest):
1928
"""Aggregation Extension GET request model."""
2029

21-
aggregations: Annotated[Optional[str], Query()] = attr.ib(
22-
default=None, converter=str2list
23-
)
30+
aggregations: Optional[List[str]] = attr.ib(default=None, converter=_agg_converter)
2431

2532

2633
class AggregationExtensionPostRequest(BaseSearchPostRequest):
2734
"""Aggregation Extension POST request model."""
2835

29-
aggregations: Optional[List[str]] = Field(default=None)
36+
aggregations: Optional[List[str]] = Field(
37+
default=None,
38+
description="A list of aggregations to compute and return.",
39+
)

stac_fastapi/extensions/stac_fastapi/extensions/core/fields/request.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Request models for the fields extension."""
22

33
import warnings
4-
from typing import Dict, Optional, Set
4+
from typing import Dict, List, Optional, Set
55

66
import attr
77
from fastapi import Query
@@ -70,14 +70,31 @@ def filter_fields(self) -> Dict:
7070
}
7171

7272

73+
def _fields_converter(
74+
val: Annotated[
75+
Optional[str],
76+
Query(
77+
description="Include or exclude fields from items body.",
78+
json_schema_extra={
79+
"example": "properties.datetime",
80+
},
81+
),
82+
] = None,
83+
) -> Optional[List[str]]:
84+
return str2list(val)
85+
86+
7387
@attr.s
7488
class FieldsExtensionGetRequest(APIRequest):
7589
"""Additional fields for the GET request."""
7690

77-
fields: Annotated[Optional[str], Query()] = attr.ib(default=None, converter=str2list)
91+
fields: Optional[List[str]] = attr.ib(default=None, converter=_fields_converter)
7892

7993

8094
class FieldsExtensionPostRequest(BaseModel):
8195
"""Additional fields and schema for the POST request."""
8296

83-
fields: Optional[PostFieldsExtension] = Field(PostFieldsExtension())
97+
fields: Optional[PostFieldsExtension] = Field(
98+
PostFieldsExtension(),
99+
description="Include or exclude fields from items body.",
100+
)

stac_fastapi/extensions/stac_fastapi/extensions/core/filter/request.py

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,62 @@
1616
class FilterExtensionGetRequest(APIRequest):
1717
"""Filter extension GET request model."""
1818

19-
filter: Annotated[Optional[str], Query()] = attr.ib(default=None)
20-
filter_crs: Annotated[Optional[str], Query(alias="filter-crs")] = attr.ib(
21-
default=None
22-
)
23-
filter_lang: Annotated[Optional[FilterLang], Query(alias="filter-lang")] = attr.ib(
24-
default="cql2-text"
25-
)
19+
filter: Annotated[
20+
Optional[str],
21+
Query(
22+
description="""A CQL filter expression for filtering items.\n
23+
Supports `CQL-JSON` as defined in https://portal.ogc.org/files/96288\n
24+
Remember to URL encode the CQL-JSON if using GET""",
25+
json_schema_extra={
26+
"example": "id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp'", # noqa: E501
27+
},
28+
),
29+
] = attr.ib(default=None)
30+
filter_crs: Annotated[
31+
Optional[str],
32+
Query(
33+
alias="filter-crs",
34+
description="The coordinate reference system (CRS) used by spatial literals in the 'filter' value. Default is `http://www.opengis.net/def/crs/OGC/1.3/CRS84`", # noqa: E501
35+
),
36+
] = attr.ib(default=None)
37+
filter_lang: Annotated[
38+
Optional[FilterLang],
39+
Query(
40+
alias="filter-lang",
41+
description="The CQL filter encoding that the 'filter' value uses.",
42+
),
43+
] = attr.ib(default="cql2-text")
2644

2745

2846
class FilterExtensionPostRequest(BaseModel):
2947
"""Filter extension POST request model."""
3048

31-
filter: Optional[Dict[str, Any]] = None
32-
filter_crs: Optional[str] = Field(alias="filter-crs", default=None)
33-
filter_lang: Optional[FilterLang] = Field(alias="filter-lang", default="cql2-json")
49+
filter: Optional[Dict[str, Any]] = Field(
50+
default=None,
51+
description="A CQL filter expression for filtering items.",
52+
json_schema_extra={
53+
"example": {
54+
"op": "and",
55+
"args": [
56+
{
57+
"op": "=",
58+
"args": [
59+
{"property": "id"},
60+
"LC08_L1TP_060247_20180905_20180912_01_T1_L1TP",
61+
],
62+
},
63+
{"op": "=", "args": [{"property": "collection"}, "landsat8_l1tp"]},
64+
],
65+
},
66+
},
67+
)
68+
filter_crs: Optional[str] = Field(
69+
alias="filter-crs",
70+
default=None,
71+
description="The coordinate reference system (CRS) used by spatial literals in the 'filter' value. Default is `http://www.opengis.net/def/crs/OGC/1.3/CRS84`", # noqa: E501
72+
)
73+
filter_lang: Optional[FilterLang] = Field(
74+
alias="filter-lang",
75+
default="cql2-json",
76+
description="The CQL filter encoding that the 'filter' value uses.",
77+
)

stac_fastapi/extensions/stac_fastapi/extensions/core/query/query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class QueryExtension(ApiExtension):
1717
The Query extension adds an additional `query` parameter to `/search` requests which
1818
allows the caller to perform queries against item metadata (ex. find all images with
1919
cloud cover less than 15%).
20-
https://github.com/radiantearth/stac-api-spec/blob/master/item-search/README.md#query
20+
https://github.com/stac-api-extensions/query
2121
"""
2222

2323
GET = QueryExtensionGetRequest

stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import attr
66
from fastapi import Query
7-
from pydantic import BaseModel
7+
from pydantic import BaseModel, Field
88
from typing_extensions import Annotated
99

1010
from stac_fastapi.types.search import APIRequest
@@ -14,10 +14,24 @@
1414
class QueryExtensionGetRequest(APIRequest):
1515
"""Query Extension GET request model."""
1616

17-
query: Annotated[Optional[str], Query()] = attr.ib(default=None)
17+
query: Annotated[
18+
Optional[str],
19+
Query(
20+
description="Allows additional filtering based on the properties of Item objects", # noqa: E501
21+
json_schema_extra={
22+
"example": '{"eo:cloud_cover": {"gte": 95}}',
23+
},
24+
),
25+
] = attr.ib(default=None)
1826

1927

2028
class QueryExtensionPostRequest(BaseModel):
2129
"""Query Extension POST request model."""
2230

23-
query: Optional[Dict[str, Dict[str, Any]]] = None
31+
query: Optional[Dict[str, Dict[str, Any]]] = Field(
32+
None,
33+
description="Allows additional filtering based on the properties of Item objects", # noqa: E501
34+
json_schema_extra={
35+
"example": {"eo:cloud_cover": {"gte": 95}},
36+
},
37+
)

stac_fastapi/extensions/stac_fastapi/extensions/core/sort/request.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,46 @@
44

55
import attr
66
from fastapi import Query
7-
from pydantic import BaseModel
7+
from pydantic import BaseModel, Field
88
from stac_pydantic.api.extensions.sort import SortExtension as PostSortModel
99
from typing_extensions import Annotated
1010

1111
from stac_fastapi.types.search import APIRequest, str2list
1212

1313

14+
def _sort_converter(
15+
val: Annotated[
16+
Optional[str],
17+
Query(
18+
description="An array of property names, prefixed by either '+' for ascending or '-' for descending. If no prefix is provided, '+' is assumed.", # noqa: E501
19+
json_schema_extra={
20+
"example": "-gsd,-datetime",
21+
},
22+
),
23+
],
24+
) -> Optional[List[str]]:
25+
return str2list(val)
26+
27+
1428
@attr.s
1529
class SortExtensionGetRequest(APIRequest):
1630
"""Sortby Parameter for GET requests."""
1731

18-
sortby: Annotated[Optional[str], Query()] = attr.ib(default=None, converter=str2list)
32+
sortby: Optional[List[str]] = attr.ib(default=None, converter=_sort_converter)
1933

2034

2135
class SortExtensionPostRequest(BaseModel):
2236
"""Sortby parameter for POST requests."""
2337

24-
sortby: Optional[List[PostSortModel]] = None
38+
sortby: Optional[List[PostSortModel]] = Field(
39+
None,
40+
description="An array of property (field) names, and direction in form of '{'field': '<property_name>', 'direction':'<direction>'}'", # noqa: E501
41+
json_schema_extra={
42+
"example": [
43+
{
44+
"field": "properties.created",
45+
"direction": "asc",
46+
}
47+
],
48+
},
49+
)

0 commit comments

Comments
 (0)