Skip to content

Commit

Permalink
add description and examples (#734)
Browse files Browse the repository at this point in the history
* add description and examples

* update docs

* update changelog

* Update stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py
  • Loading branch information
vincentsarago authored Jul 17, 2024
1 parent 599742c commit c55c253
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 47 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased] - TBD

* add more openapi metadata in input models [#734](https://github.com/stac-utils/stac-fastapi/pull/734)

## [3.0.0b2] - 2024-07-09

### Changed
Expand Down
32 changes: 25 additions & 7 deletions docs/src/migrations/v3.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,12 @@ e.g the BaseSearchGetRequest, default for the `GET - /search` endpoint:
class BaseSearchGetRequest(APIRequest):
"""Base arguments for GET Request."""

collections: Annotated[Optional[str], Query()] = attr.ib(
default=None, converter=str2list
)
ids: Annotated[Optional[str], Query()] = attr.ib(default=None, converter=str2list)
bbox: Annotated[Optional[BBox], Query()] = attr.ib(default=None, converter=str2bbox)
collections: Optional[List[str]] = attr.ib(default=None, converter=_collection_converter)
ids: Optional[List[str]] = attr.ib(default=None, converter=_ids_converter)
bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter)
intersects: Annotated[Optional[str], Query()] = attr.ib(default=None)
datetime: Annotated[Optional[DateTimeType], Query()] = attr.ib(
default=None, converter=str_to_interval
datetime: Optional[DateTimeType] = attr.ib(
default=None, converter=_datetime_converter
)
limit: Annotated[Optional[int], Query()] = attr.ib(default=10)
```
Expand All @@ -115,6 +113,26 @@ class SomeRequest(APIRequest):
user_number: Annotated[Optional[int], Query(alias="user-number")] = attr.ib(default=None)
```

Note: when an attribute has a `converter` (e.g `_ids_converter`), the **Type Hint** should be defined directly in the converter:

```python
def _ids_converter(
val: Annotated[
Optional[str],
Query(
description="Array of Item ids to return.",
),
] = None,
) -> Optional[List[str]]:
return str2list(val)

@attr.s
class BaseSearchGetRequest(APIRequest):
"""Base arguments for GET Request."""

ids: Optional[List[str]] = attr.ib(default=None, converter=_ids_converter)
```

## Filter extension

`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).
Expand Down
10 changes: 5 additions & 5 deletions stac_fastapi/api/stac_fastapi/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
APIRequest,
BaseSearchGetRequest,
BaseSearchPostRequest,
str2bbox,
str_to_interval,
_bbox_converter,
_datetime_converter,
)

try:
Expand Down Expand Up @@ -114,9 +114,9 @@ class ItemCollectionUri(APIRequest):

collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
limit: Annotated[int, Query()] = attr.ib(default=10)
bbox: Annotated[Optional[BBox], Query()] = attr.ib(default=None, converter=str2bbox)
datetime: Annotated[Optional[DateTimeType], Query()] = attr.ib(
default=None, converter=str_to_interval
bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter)
datetime: Optional[DateTimeType] = attr.ib(
default=None, converter=_datetime_converter
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,26 @@
)


def _agg_converter(
val: Annotated[
Optional[str],
Query(description="A list of aggregations to compute and return."),
] = None,
) -> Optional[List[str]]:
return str2list(val)


@attr.s
class AggregationExtensionGetRequest(BaseSearchGetRequest):
"""Aggregation Extension GET request model."""

aggregations: Annotated[Optional[str], Query()] = attr.ib(
default=None, converter=str2list
)
aggregations: Optional[List[str]] = attr.ib(default=None, converter=_agg_converter)


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

aggregations: Optional[List[str]] = Field(default=None)
aggregations: Optional[List[str]] = Field(
default=None,
description="A list of aggregations to compute and return.",
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Request models for the fields extension."""

import warnings
from typing import Dict, Optional, Set
from typing import Dict, List, Optional, Set

import attr
from fastapi import Query
Expand Down Expand Up @@ -70,14 +70,31 @@ def filter_fields(self) -> Dict:
}


def _fields_converter(
val: Annotated[
Optional[str],
Query(
description="Include or exclude fields from items body.",
json_schema_extra={
"example": "properties.datetime",
},
),
] = None,
) -> Optional[List[str]]:
return str2list(val)


@attr.s
class FieldsExtensionGetRequest(APIRequest):
"""Additional fields for the GET request."""

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


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

fields: Optional[PostFieldsExtension] = Field(PostFieldsExtension())
fields: Optional[PostFieldsExtension] = Field(
PostFieldsExtension(),
description="Include or exclude fields from items body.",
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,62 @@
class FilterExtensionGetRequest(APIRequest):
"""Filter extension GET request model."""

filter: Annotated[Optional[str], Query()] = attr.ib(default=None)
filter_crs: Annotated[Optional[str], Query(alias="filter-crs")] = attr.ib(
default=None
)
filter_lang: Annotated[Optional[FilterLang], Query(alias="filter-lang")] = attr.ib(
default="cql2-text"
)
filter: Annotated[
Optional[str],
Query(
description="""A CQL filter expression for filtering items.\n
Supports `CQL-JSON` as defined in https://portal.ogc.org/files/96288\n
Remember to URL encode the CQL-JSON if using GET""",
json_schema_extra={
"example": "id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp'", # noqa: E501
},
),
] = attr.ib(default=None)
filter_crs: Annotated[
Optional[str],
Query(
alias="filter-crs",
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
),
] = attr.ib(default=None)
filter_lang: Annotated[
Optional[FilterLang],
Query(
alias="filter-lang",
description="The CQL filter encoding that the 'filter' value uses.",
),
] = attr.ib(default="cql2-text")


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

filter: Optional[Dict[str, Any]] = None
filter_crs: Optional[str] = Field(alias="filter-crs", default=None)
filter_lang: Optional[FilterLang] = Field(alias="filter-lang", default="cql2-json")
filter: Optional[Dict[str, Any]] = Field(
default=None,
description="A CQL filter expression for filtering items.",
json_schema_extra={
"example": {
"op": "and",
"args": [
{
"op": "=",
"args": [
{"property": "id"},
"LC08_L1TP_060247_20180905_20180912_01_T1_L1TP",
],
},
{"op": "=", "args": [{"property": "collection"}, "landsat8_l1tp"]},
],
},
},
)
filter_crs: Optional[str] = Field(
alias="filter-crs",
default=None,
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
)
filter_lang: Optional[FilterLang] = Field(
alias="filter-lang",
default="cql2-json",
description="The CQL filter encoding that the 'filter' value uses.",
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class QueryExtension(ApiExtension):
The Query extension adds an additional `query` parameter to `/search` requests which
allows the caller to perform queries against item metadata (ex. find all images with
cloud cover less than 15%).
https://github.com/radiantearth/stac-api-spec/blob/master/item-search/README.md#query
https://github.com/stac-api-extensions/query
"""

GET = QueryExtensionGetRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import attr
from fastapi import Query
from pydantic import BaseModel
from pydantic import BaseModel, Field
from typing_extensions import Annotated

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

query: Annotated[Optional[str], Query()] = attr.ib(default=None)
query: Annotated[
Optional[str],
Query(
description="Allows additional filtering based on the properties of Item objects", # noqa: E501
json_schema_extra={
"example": '{"eo:cloud_cover": {"gte": 95}}',
},
),
] = attr.ib(default=None)


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

query: Optional[Dict[str, Dict[str, Any]]] = None
query: Optional[Dict[str, Dict[str, Any]]] = Field(
None,
description="Allows additional filtering based on the properties of Item objects", # noqa: E501
json_schema_extra={
"example": {"eo:cloud_cover": {"gte": 95}},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,46 @@

import attr
from fastapi import Query
from pydantic import BaseModel
from pydantic import BaseModel, Field
from stac_pydantic.api.extensions.sort import SortExtension as PostSortModel
from typing_extensions import Annotated

from stac_fastapi.types.search import APIRequest, str2list


def _sort_converter(
val: Annotated[
Optional[str],
Query(
description="An array of property names, prefixed by either '+' for ascending or '-' for descending. If no prefix is provided, '+' is assumed.", # noqa: E501
json_schema_extra={
"example": "-gsd,-datetime",
},
),
],
) -> Optional[List[str]]:
return str2list(val)


@attr.s
class SortExtensionGetRequest(APIRequest):
"""Sortby Parameter for GET requests."""

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


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

sortby: Optional[List[PostSortModel]] = None
sortby: Optional[List[PostSortModel]] = Field(
None,
description="An array of property (field) names, and direction in form of '{'field': '<property_name>', 'direction':'<direction>'}'", # noqa: E501
json_schema_extra={
"example": [
{
"field": "properties.created",
"direction": "asc",
}
],
},
)
Loading

0 comments on commit c55c253

Please sign in to comment.