Skip to content

Commit

Permalink
Make equivalent changes to sqlalchemy backend
Browse files Browse the repository at this point in the history
  • Loading branch information
duckontheweb committed Jul 21, 2022
1 parent 9b723c4 commit 160f831
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 52 deletions.
3 changes: 2 additions & 1 deletion scripts/ingest_joplin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ def post_or_put(url: str, data: dict):
"""Post or put data to url."""
r = requests.post(url, json=data)
if r.status_code == 409:
new_url = url if data["type"] == "Collection" else url + f"/{data['id']}"
# Exists, so update
r = requests.put(url, json=data)
r = requests.put(new_url, json=data)
# Unchanged may throw a 404
if not r.status_code == 404:
r.raise_for_status()
Expand Down
6 changes: 3 additions & 3 deletions stac_fastapi/pgstac/stac_fastapi/pgstac/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ async def create_item(
self, collection_id: str, item: stac_types.Item, **kwargs
) -> Optional[Union[stac_types.Item, Response]]:
"""Create item."""
item_collection_id = item.get("collection")
if item_collection_id is not None and collection_id != item_collection_id:
body_collection_id = item.get("collection")
if body_collection_id is not None and collection_id != body_collection_id:
raise HTTPException(
status_code=409,
detail=f"Collection ID from path parameter ({collection_id}) does not match Collection ID from Item ({item_collection_id})",
detail=f"Collection ID from path parameter ({collection_id}) does not match Collection ID from Item ({body_collection_id})",
)
item["collection"] = collection_id
request = kwargs["request"]
Expand Down
34 changes: 29 additions & 5 deletions stac_fastapi/sqlalchemy/stac_fastapi/sqlalchemy/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Optional, Type, Union

import attr
from fastapi import HTTPException
from starlette.responses import Response

from stac_fastapi.extensions.third_party.bulk_transactions import (
Expand Down Expand Up @@ -35,19 +36,29 @@ class TransactionsClient(BaseTransactionsClient):
)

def create_item(
self, model: Union[stac_types.Item, stac_types.ItemCollection], **kwargs
self,
collection_id: str,
item: Union[stac_types.Item, stac_types.ItemCollection],
**kwargs,
) -> Optional[stac_types.Item]:
"""Create item."""
base_url = str(kwargs["request"].base_url)

# If a feature collection is posted
if model["type"] == "FeatureCollection":
if item["type"] == "FeatureCollection":
bulk_client = BulkTransactionsClient(session=self.session)
bulk_client.bulk_item_insert(items=model["features"])
bulk_client.bulk_item_insert(items=item["features"])
return None

# Otherwise a single item has been posted
data = self.item_serializer.stac_to_db(model)
body_collection_id = item.get("collection")
if body_collection_id is not None and collection_id != body_collection_id:
raise HTTPException(
status_code=409,
detail=f"Collection ID from path parameter ({collection_id}) does not match Collection ID from Item ({body_collection_id})",
)
item["collection"] = collection_id
data = self.item_serializer.stac_to_db(item)
with self.session.writer.context_session() as session:
session.add(data)
return self.item_serializer.db_to_stac(data, base_url)
Expand All @@ -63,9 +74,22 @@ def create_collection(
return self.collection_serializer.db_to_stac(data, base_url=base_url)

def update_item(
self, item: stac_types.Item, **kwargs
self, collection_id: str, item_id: str, item: stac_types.Item, **kwargs
) -> Optional[Union[stac_types.Item, Response]]:
"""Update item."""
body_collection_id = item.get("collection")
if body_collection_id is not None and collection_id != body_collection_id:
raise HTTPException(
status_code=409,
detail=f"Collection ID from path parameter ({collection_id}) does not match Collection ID from Item ({body_collection_id})",
)
item["collection"] = collection_id
body_item_id = item["id"]
if body_item_id != item_id:
raise HTTPException(
status_code=409,
detail=f"Item ID from path parameter ({item_id}) does not match Item ID from Item ({body_item_id})",
)
base_url = str(kwargs["request"].base_url)
with self.session.reader.context_session() as session:
query = session.query(self.item_table).filter(
Expand Down
74 changes: 55 additions & 19 deletions stac_fastapi/sqlalchemy/tests/api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"POST /collections",
"POST /collections/{collection_id}/items",
"PUT /collections",
"PUT /collections/{collection_id}/items",
"PUT /collections/{collection_id}/items/{item_id}",
]


Expand Down Expand Up @@ -66,7 +66,9 @@ def test_app_transaction_extension(app_client, load_test_data):

def test_app_search_response(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

resp = app_client.get("/search", params={"collections": ["test-collection"]})
assert resp.status_code == 200
Expand All @@ -82,7 +84,9 @@ def test_app_search_response_multipolygon(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item_multipolygon.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

resp = app_client.get("/search", params={"collections": ["test-collection"]})
assert resp.status_code == 200
Expand All @@ -96,7 +100,9 @@ def test_app_search_response_geometry_null(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item_geometry_null.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

resp = app_client.get("/search", params={"collections": ["test-collection"]})
assert resp.status_code == 200
Expand All @@ -109,7 +115,9 @@ def test_app_search_response_geometry_null(

def test_app_context_extension(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

resp = app_client.get("/search", params={"collections": ["test-collection"]})
assert resp.status_code == 200
Expand All @@ -120,7 +128,9 @@ def test_app_context_extension(load_test_data, app_client, postgres_transactions

def test_app_fields_extension(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

resp = app_client.get("/search", params={"collections": ["test-collection"]})
assert resp.status_code == 200
Expand All @@ -130,7 +140,9 @@ def test_app_fields_extension(load_test_data, app_client, postgres_transactions)

def test_app_query_extension_gt(load_test_data, app_client, postgres_transactions):
test_item = load_test_data("test_item.json")
postgres_transactions.create_item(test_item, request=MockStarletteRequest)
postgres_transactions.create_item(
test_item["collection"], test_item, request=MockStarletteRequest
)

params = {"query": {"proj:epsg": {"gt": test_item["properties"]["proj:epsg"]}}}
resp = app_client.post("/search", json=params)
Expand All @@ -141,7 +153,9 @@ def test_app_query_extension_gt(load_test_data, app_client, postgres_transaction

def test_app_query_extension_gte(load_test_data, app_client, postgres_transactions):
test_item = load_test_data("test_item.json")
postgres_transactions.create_item(test_item, request=MockStarletteRequest)
postgres_transactions.create_item(
test_item["collection"], test_item, request=MockStarletteRequest
)

params = {"query": {"proj:epsg": {"gte": test_item["properties"]["proj:epsg"]}}}
resp = app_client.post("/search", json=params)
Expand All @@ -160,7 +174,9 @@ def test_app_query_extension_limit_lt0(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

params = {"limit": -1}
resp = app_client.post("/search", json=params)
Expand All @@ -171,7 +187,9 @@ def test_app_query_extension_limit_gt10000(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

params = {"limit": 10001}
resp = app_client.post("/search", json=params)
Expand All @@ -182,7 +200,9 @@ def test_app_query_extension_limit_10000(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

params = {"limit": 10000}
resp = app_client.post("/search", json=params)
Expand All @@ -194,15 +214,19 @@ def test_app_sort_extension(load_test_data, app_client, postgres_transactions):
item_date = datetime.strptime(
first_item["properties"]["datetime"], "%Y-%m-%dT%H:%M:%SZ"
)
postgres_transactions.create_item(first_item, request=MockStarletteRequest)
postgres_transactions.create_item(
first_item["collection"], first_item, request=MockStarletteRequest
)

second_item = load_test_data("test_item.json")
second_item["id"] = "another-item"
another_item_date = item_date - timedelta(days=1)
second_item["properties"]["datetime"] = another_item_date.strftime(
"%Y-%m-%dT%H:%M:%SZ"
)
postgres_transactions.create_item(second_item, request=MockStarletteRequest)
postgres_transactions.create_item(
second_item["collection"], second_item, request=MockStarletteRequest
)

params = {
"collections": [first_item["collection"]],
Expand All @@ -217,7 +241,9 @@ def test_app_sort_extension(load_test_data, app_client, postgres_transactions):

def test_search_invalid_date(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

params = {
"datetime": "2020-XX-01/2020-10-30",
Expand All @@ -230,7 +256,9 @@ def test_search_invalid_date(load_test_data, app_client, postgres_transactions):

def test_search_point_intersects(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

point = [150.04, -33.14]
intersects = {"type": "Point", "coordinates": point}
Expand All @@ -247,7 +275,9 @@ def test_search_point_intersects(load_test_data, app_client, postgres_transactio

def test_datetime_non_interval(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)
alternate_formats = [
"2020-02-12T12:30:22+00:00",
"2020-02-12T12:30:22.00Z",
Expand All @@ -269,7 +299,9 @@ def test_datetime_non_interval(load_test_data, app_client, postgres_transactions

def test_bbox_3d(load_test_data, app_client, postgres_transactions):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

australia_bbox = [106.343365, -47.199523, 0.1, 168.218365, -19.437288, 0.1]
params = {
Expand All @@ -286,7 +318,9 @@ def test_search_line_string_intersects(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

line = [[150.04, -33.14], [150.22, -33.89]]
intersects = {"type": "LineString", "coordinates": line}
Expand All @@ -305,7 +339,9 @@ def test_app_fields_extension_return_all_properties(
load_test_data, app_client, postgres_transactions
):
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)
postgres_transactions.create_item(
item["collection"], item, request=MockStarletteRequest
)

resp = app_client.get(
"/search", params={"collections": ["test-collection"], "fields": "properties"}
Expand Down
Loading

0 comments on commit 160f831

Please # to comment.