Skip to content

Commit

Permalink
handle collection paging differently (#156)
Browse files Browse the repository at this point in the history
* handle collection paging differently

* test next link
  • Loading branch information
hrodmn authored Oct 8, 2024
1 parent 456c515 commit a9dce7e
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 8 deletions.
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ services:
build:
context: .
dockerfile: Dockerfile.tests
volumes:
- .:/app
environment:
- ENVIRONMENT=local
- DB_MIN_CONN_SIZE=1
Expand Down
17 changes: 11 additions & 6 deletions stac_fastapi/pgstac/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from stac_fastapi.pgstac.config import Settings
from stac_fastapi.pgstac.models.links import (
CollectionLinks,
CollectionSearchPagingLinks,
ItemCollectionLinks,
ItemLinks,
PagingLinks,
Expand Down Expand Up @@ -90,12 +91,16 @@ async def all_collections( # noqa: C901
)
collections_result: Collections = await conn.fetchval(q, *p)

next: Optional[str] = None
prev: Optional[str] = None

next: Optional[Dict[str, Any]] = None
prev: Optional[Dict[str, Any]] = None
if links := collections_result.get("links"):
next = collections_result["links"].pop("next")
prev = collections_result["links"].pop("prev")
next = None
prev = None
for link in links:
if link["rel"] == "next":
next = link
elif link["rel"] == "prev":
prev = link

linked_collections: List[Collection] = []
collections = collections_result["collections"]
Expand All @@ -120,7 +125,7 @@ async def all_collections( # noqa: C901

linked_collections.append(coll)

links = await PagingLinks(
links = await CollectionSearchPagingLinks(
request=request,
next=next,
prev=prev,
Expand Down
54 changes: 54 additions & 0 deletions stac_fastapi/pgstac/models/links.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,60 @@ def link_prev(self) -> Optional[Dict[str, Any]]:
return None


@attr.s
class CollectionSearchPagingLinks(BaseLinks):
next: Optional[Dict[str, Any]] = attr.ib(kw_only=True, default=None)
prev: Optional[Dict[str, Any]] = attr.ib(kw_only=True, default=None)

def link_next(self) -> Optional[Dict[str, Any]]:
"""Create link for next page."""
if self.next is not None:
method = self.request.method
if method == "GET":
# if offset is equal to default value (0), drop it
if self.next["body"].get("offset", -1) == 0:
_ = self.next["body"].pop("offset")

href = merge_params(self.url, self.next["body"])

# if next link is equal to this link, skip it
if href == self.url:
print(self.request.body())
return None

link = {
"rel": Relations.next.value,
"type": MimeTypes.geojson.value,
"method": method,
"href": href,
}
return link

return None

def link_prev(self):
if self.prev is not None:
method = self.request.method
if method == "GET":
# if offset is equal to default value (0), drop it
if self.prev["body"].get("offset", -1) == 0:
_ = self.prev["body"].pop("offset")

href = merge_params(self.url, self.prev["body"])

# if prev link is equal to this link, skip it
if href == self.url:
return None
return {
"rel": Relations.previous.value,
"type": MimeTypes.geojson.value,
"method": method,
"href": href,
}

return None


@attr.s
class CollectionLinksBase(BaseLinks):
"""Create inferred links specific to collections."""
Expand Down
14 changes: 12 additions & 2 deletions tests/resources/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,5 +313,15 @@ async def test_get_collections_search_limit_offset(
"/collections",
params={"limit": 1},
)
assert len(resp.json()["collections"]) == 1
assert resp.json()["collections"][0]["id"] == load_test_collection.id
response = resp.json()
assert len(response["collections"]) == 1
assert response["collections"][0]["id"] == load_test_collection["id"]

# check next link
next_link = [link["href"] for link in response["links"] if link["rel"] == "next"][0]
next_url = next_link.replace(str(app_client.base_url), "")
next_resp = await app_client.get(next_url)
next_response = next_resp.json()

assert len(next_response["collections"]) == 1
assert next_response["collections"][0]["id"] == load_test2_collection.id

0 comments on commit a9dce7e

Please sign in to comment.