Skip to content

Commit

Permalink
update from main
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentsarago committed Jul 19, 2024
2 parents b5c8ff3 + fe4d0df commit 1e260d1
Show file tree
Hide file tree
Showing 11 changed files with 537 additions and 41 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

## [Unreleased] - TBD

### Changed

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

### Added
* Add Free-text Extension ([#655](https://github.com/stac-utils/stac-fastapi/pull/655))
* Add Collection-Search Extension

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

### Changed
Expand Down
4 changes: 4 additions & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ nav:
- core:
- module: api/stac_fastapi/extensions/core/index.md
- context: api/stac_fastapi/extensions/core/context.md
- free_text:
- module: api/stac_fastapi/extensions/core/free_text/index.md
- free_text: api/stac_fastapi/extensions/core/free_text/free_text.md
- request: api/stac_fastapi/extensions/core/free_text/request.md
- filter:
- module: api/stac_fastapi/extensions/core/filter/index.md
- filter: api/stac_fastapi/extensions/core/filter/filter.md
Expand Down
1 change: 1 addition & 0 deletions stac_fastapi/api/stac_fastapi/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class ApiExtensions(enum.Enum):
transaction = "transaction"
aggregation = "aggregation"
collection_search = "collection-search"
free_text = "free-text"


class AddOns(enum.Enum):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .context import ContextExtension
from .fields import FieldsExtension
from .filter import FilterExtension
from .free_text import FreeTextAdvancedExtension, FreeTextExtension
from .pagination import PaginationExtension, TokenPaginationExtension
from .query import QueryExtension
from .sort import SortExtension
Expand All @@ -15,6 +16,8 @@
"ContextExtension",
"FieldsExtension",
"FilterExtension",
"FreeTextExtension",
"FreeTextAdvancedExtension",
"PaginationExtension",
"QueryExtension",
"SortExtension",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Collection-Search extension module."""

from .collection_search import CollectionSearchExtension
from .collection_search import CollectionSearchExtension, ConformanceClasses

__all__ = ["CollectionSearchExtension"]
__all__ = ["CollectionSearchExtension", "ConformanceClasses"]
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,3 @@ class CollectionSearchExtensionGetRequest(APIRequest):
description="Limits the number of results that are included in each page of the response." # noqa: E501
),
] = attr.ib(default=None)


@attr.s
class FreeTextGetRequest(APIRequest):
"""FreeText additional Collection-Search parameters for the GET request."""

q: Annotated[
Optional[str],
Query(description="A basic free-text search parameter."),
] = attr.ib(default=None)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Query extension module."""

from .free_text import (
FreeTextAdvancedExtension,
FreeTextConformanceClasses,
FreeTextExtension,
)

__all__ = [
"FreeTextExtension",
"FreeTextAdvancedExtension",
"FreeTextConformanceClasses",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""Free-text extension."""

from enum import Enum
from typing import List, Optional

import attr
from fastapi import FastAPI

from stac_fastapi.types.extension import ApiExtension

from .request import (
FreeTextAdvancedExtensionGetRequest,
FreeTextAdvancedExtensionPostRequest,
FreeTextExtensionGetRequest,
FreeTextExtensionPostRequest,
)


class FreeTextConformanceClasses(str, Enum):
"""Conformance classes for the Free-Text extension.
See https://github.com/stac-api-extensions/freetext-search
"""

# https://github.com/stac-api-extensions/freetext-search?tab=readme-ov-file#basic
SEARCH = "https://api.stacspec.org/v1.0.0-rc.1/item-search#free-text"
COLLECTIONS = "https://api.stacspec.org/v1.0.0-rc.1/collection-search#free-text"
ITEMS = "https://api.stacspec.org/v1.0.0-rc.1/ogcapi-features#free-text"

# https://github.com/stac-api-extensions/freetext-search?tab=readme-ov-file#advanced
SEARCH_ADVANCED = (
"https://api.stacspec.org/v1.0.0-rc.1/item-search#advanced-free-text"
)
COLLECTIONS_ADVANCED = (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#advanced-free-text"
)
ITEMS_ADVANCED = (
"https://api.stacspec.org/v1.0.0-rc.1/ogcapi-features#advanced-free-text"
)


@attr.s
class FreeTextExtension(ApiExtension):
"""Free-text Extension.
The Free-text extension adds an additional `q` parameter to `/search` requests which
allows the caller to perform free-text queries against STAC metadata.
https://github.com/stac-api-extensions/freetext-search?tab=readme-ov-file#basic
"""

GET = FreeTextExtensionGetRequest
POST = FreeTextExtensionPostRequest

conformance_classes: List[str] = attr.ib(
default=[
FreeTextConformanceClasses.SEARCH,
FreeTextConformanceClasses.COLLECTIONS,
FreeTextConformanceClasses.ITEMS,
]
)
schema_href: Optional[str] = attr.ib(default=None)

def register(self, app: FastAPI) -> None:
"""Register the extension with a FastAPI application.
Args:
app: target FastAPI application.
Returns:
None
"""
pass


@attr.s
class FreeTextAdvancedExtension(ApiExtension):
"""Free-text Extension.
The Free-text extension adds an additional `q` parameter to `/search` requests which
allows the caller to perform free-text queries against STAC metadata.
https://github.com/stac-api-extensions/freetext-search?tab=readme-ov-file#advanced
"""

GET = FreeTextAdvancedExtensionGetRequest
POST = FreeTextAdvancedExtensionPostRequest

conformance_classes: List[str] = attr.ib(
default=[
FreeTextConformanceClasses.SEARCH_ADVANCED,
FreeTextConformanceClasses.COLLECTIONS_ADVANCED,
FreeTextConformanceClasses.ITEMS_ADVANCED,
]
)
schema_href: Optional[str] = attr.ib(default=None)

def register(self, app: FastAPI) -> None:
"""Register the extension with a FastAPI application.
Args:
app: target FastAPI application.
Returns:
None
"""
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Request model for the Free-text extension."""

from typing import List, Optional

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

from stac_fastapi.types.search import APIRequest, str2list


def _ft_converter(
val: Annotated[
Optional[str],
Query(
description="Parameter to perform free-text queries against STAC metadata",
json_schema_extra={
"example": "ocean,coast",
},
),
] = None,
) -> Optional[List[str]]:
return str2list(val)


@attr.s
class FreeTextExtensionGetRequest(APIRequest):
"""Free-text Extension GET request model."""

q: Optional[List[str]] = attr.ib(default=None, converter=_ft_converter)


class FreeTextExtensionPostRequest(BaseModel):
"""Free-text Extension POST request model."""

q: Optional[List[str]] = Field(
None,
description="Parameter to perform free-text queries against STAC metadata",
)


@attr.s
class FreeTextAdvancedExtensionGetRequest(APIRequest):
"""Free-text Extension GET request model."""

q: Annotated[
Optional[str],
Query(
description="Parameter to perform free-text queries against STAC metadata",
json_schema_extra={
"example": "ocean,coast",
},
),
] = attr.ib(default=None)


class FreeTextAdvancedExtensionPostRequest(BaseModel):
"""Free-text Extension POST request model."""

q: Optional[str] = Field(
None,
description="Parameter to perform free-text queries against STAC metadata",
)
41 changes: 12 additions & 29 deletions stac_fastapi/extensions/tests/test_collection_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
from stac_fastapi.api.app import StacApi
from stac_fastapi.api.models import create_request_model
from stac_fastapi.extensions.core import CollectionSearchExtension
from stac_fastapi.extensions.core.collection_search.collection_search import (
ConformanceClasses,
)
from stac_fastapi.extensions.core.collection_search import ConformanceClasses
from stac_fastapi.extensions.core.collection_search.request import (
CollectionSearchExtensionGetRequest,
FreeTextGetRequest,
)
from stac_fastapi.extensions.core.fields.request import FieldsExtensionGetRequest
from stac_fastapi.extensions.core.filter.request import FilterExtensionGetRequest
from stac_fastapi.extensions.core.free_text.request import FreeTextExtensionGetRequest
from stac_fastapi.extensions.core.query.request import QueryExtensionGetRequest
from stac_fastapi.extensions.core.sort.request import SortExtensionGetRequest
from stac_fastapi.types.config import ApiSettings
Expand Down Expand Up @@ -94,7 +92,7 @@ def test_collection_search_extension_models():
model_name="SearchGetRequest",
base_model=CollectionSearchExtensionGetRequest,
mixins=[
FreeTextGetRequest,
FreeTextExtensionGetRequest,
FilterExtensionGetRequest,
QueryExtensionGetRequest,
SortExtensionGetRequest,
Expand Down Expand Up @@ -125,34 +123,19 @@ def test_collection_search_extension_models():
response = client.get("/conformance")
assert response.is_success, response.json()
response_dict = response.json()
assert (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search"
in response_dict["conformsTo"]
)
conforms = response_dict["conformsTo"]
assert "https://api.stacspec.org/v1.0.0-rc.1/collection-search" in conforms
assert (
"http://www.opengis.net/spec/ogcapi-common-2/1.0/conf/simple-query"
in response_dict["conformsTo"]
in conforms
)
assert (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#free-text"
in response_dict["conformsTo"]
)
assert (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#filter"
in response_dict["conformsTo"]
)
assert (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#query"
in response_dict["conformsTo"]
)
assert (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#sort"
in response_dict["conformsTo"]
)
assert (
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#fields"
in response_dict["conformsTo"]
"https://api.stacspec.org/v1.0.0-rc.1/collection-search#free-text" in conforms
)
assert "https://api.stacspec.org/v1.0.0-rc.1/collection-search#filter" in conforms
assert "https://api.stacspec.org/v1.0.0-rc.1/collection-search#query" in conforms
assert "https://api.stacspec.org/v1.0.0-rc.1/collection-search#sort" in conforms
assert "https://api.stacspec.org/v1.0.0-rc.1/collection-search#fields" in conforms

response = client.get("/collections")
assert response.is_success, response.json()
Expand Down Expand Up @@ -189,7 +172,7 @@ def test_collection_search_extension_models():
"2020-06-13T14:00:00+00:00",
] == response_dict["datetime"]
assert 100 == response_dict["limit"]
assert "EO,Earth Observation" == response_dict["q"]
assert ["EO", "Earth Observation"] == response_dict["q"]
assert "id='item_id' AND collection='collection_id'" == response_dict["filter"]
assert "filter_crs" in response_dict
assert "cql2-text" in response_dict["filter_lang"]
Expand Down
Loading

0 comments on commit 1e260d1

Please sign in to comment.