Skip to content

Commit

Permalink
Pgstac queryables (#474)
Browse files Browse the repository at this point in the history
* add queryables

* bump pgstac version

* add tests for queryables

* make id refer to current url

* update content type, add changelog
  • Loading branch information
bitner authored Oct 5, 2022
1 parent 25879af commit fbdd993
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

### Added

* Add support in pgstac backend for /queryables and /collections/{collection_id}/queryables endpoints with functions exposed in pgstac 0.6.8
* Update pgstac requirement to 0.6.8

### Changed

### Removed
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ services:

database:
container_name: stac-db
image: ghcr.io/stac-utils/pgstac:v0.6.6
image: ghcr.io/stac-utils/pgstac:v0.6.8
environment:
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
class PostItem(CollectionUri):
"""Create Item."""

item: stac_types.Item = attr.ib(default=Body())
item: stac_types.Item = attr.ib(default=Body(None))


@attr.s
class PutItem(ItemUri):
"""Update Item."""

item: stac_types.Item = attr.ib(default=Body())
item: stac_types.Item = attr.ib(default=Body(None))


@attr.s
Expand Down
3 changes: 3 additions & 0 deletions stac_fastapi/pgstac/stac_fastapi/pgstac/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from stac_fastapi.extensions.core import (
ContextExtension,
FieldsExtension,
FilterExtension,
SortExtension,
TokenPaginationExtension,
TransactionExtension,
Expand All @@ -15,6 +16,7 @@
from stac_fastapi.pgstac.core import CoreCrudClient
from stac_fastapi.pgstac.db import close_db_connection, connect_to_db
from stac_fastapi.pgstac.extensions import QueryExtension
from stac_fastapi.pgstac.extensions.filter import FiltersClient
from stac_fastapi.pgstac.transactions import BulkTransactionsClient, TransactionsClient
from stac_fastapi.pgstac.types.search import PgstacSearch

Expand All @@ -30,6 +32,7 @@
FieldsExtension(),
TokenPaginationExtension(),
ContextExtension(),
FilterExtension(client=FiltersClient()),
BulkTransactionExtension(client=BulkTransactionsClient()),
]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""pgstac extension customisations."""

from .filter import FiltersClient
from .query import QueryExtension

__all__ = ["QueryExtension"]
__all__ = ["QueryExtension", "FiltersClient"]
37 changes: 37 additions & 0 deletions stac_fastapi/pgstac/stac_fastapi/pgstac/extensions/filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Get Queryables."""
from typing import Any, Optional

from buildpg import render
from fastapi import Request
from fastapi.responses import JSONResponse

from stac_fastapi.types.core import AsyncBaseFiltersClient


class FiltersClient(AsyncBaseFiltersClient):
"""Defines a pattern for implementing the STAC filter extension."""

async def get_queryables(
self, request: Request, collection_id: Optional[str] = None, **kwargs: Any
) -> JSONResponse:
"""Get the queryables available for the given collection_id.
If collection_id is None, returns the intersection of all
queryables over all collections.
This base implementation returns a blank queryable schema. This is not allowed
under OGC CQL but it is allowed by the STAC API Filter Extension
https://github.com/radiantearth/stac-api-spec/tree/master/fragments/filter#queryables
"""
pool = request.app.state.readpool

async with pool.acquire() as conn:
q, p = render(
"""
SELECT * FROM get_queryables(:collection::text);
""",
collection=collection_id,
)
queryables = await conn.fetchval(q, *p)
queryables["$id"] = str(request.url)
headers = {"Content-Type": "application/schema+json"}
return JSONResponse(queryables, headers=headers)
24 changes: 24 additions & 0 deletions stac_fastapi/pgstac/tests/api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,27 @@ async def test_search_duplicate_forward_headers(
for feature in features:
for link in feature["links"]:
assert link["href"].startswith("https://test:1234/")


@pytest.mark.asyncio
async def test_base_queryables(load_test_data, app_client, load_test_collection):
resp = await app_client.get("/queryables")
assert resp.headers["Content-Type"] == "application/schema+json"
q = resp.json()
assert q["$id"].endswith("/queryables")
assert q["type"] == "object"
assert "properties" in q
assert "id" in q["properties"]
assert "eo:cloud_cover" in q["properties"]


@pytest.mark.asyncio
async def test_collection_queryables(load_test_data, app_client, load_test_collection):
resp = await app_client.get("/collections/test-collection/queryables")
assert resp.headers["Content-Type"] == "application/schema+json"
q = resp.json()
assert q["$id"].endswith("/collections/test-collection/queryables")
assert q["type"] == "object"
assert "properties" in q
assert "id" in q["properties"]
assert "eo:cloud_cover" in q["properties"]
6 changes: 5 additions & 1 deletion stac_fastapi/pgstac/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from stac_fastapi.api.app import StacApi
from stac_fastapi.api.models import create_get_request_model, create_post_request_model
from stac_fastapi.extensions.core import (
ContextExtension,
FieldsExtension,
FilterExtension,
SortExtension,
Expand All @@ -28,6 +29,7 @@
from stac_fastapi.pgstac.core import CoreCrudClient
from stac_fastapi.pgstac.db import close_db_connection, connect_to_db
from stac_fastapi.pgstac.extensions import QueryExtension
from stac_fastapi.pgstac.extensions.filter import FiltersClient
from stac_fastapi.pgstac.transactions import BulkTransactionsClient, TransactionsClient
from stac_fastapi.pgstac.types.search import PgstacSearch

Expand Down Expand Up @@ -133,12 +135,14 @@ def api_client(request, pg):
extensions = [
TransactionExtension(client=TransactionsClient(), settings=settings),
QueryExtension(),
FilterExtension(),
SortExtension(),
FieldsExtension(),
TokenPaginationExtension(),
ContextExtension(),
FilterExtension(client=FiltersClient()),
BulkTransactionExtension(client=BulkTransactionsClient()),
]

post_request_model = create_post_request_model(extensions, base_model=PgstacSearch)
api = StacApi(
settings=api_settings,
Expand Down

0 comments on commit fbdd993

Please # to comment.