Skip to content

Commit 2117b52

Browse files
authored
fix: use model_dump(mode="json") for serializing STAC objects (#131)
1 parent c671ed6 commit 2117b52

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

lib/ingestor-api/runtime/src/collection.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22

3+
from fastapi import HTTPException
34
from pypgstac.db import PgstacDB
45
from pypgstac.load import Methods
56

@@ -18,12 +19,14 @@ def ingest(collection: StacCollection):
1819
creds = get_db_credentials(os.environ["DB_SECRET_ARN"])
1920
with PgstacDB(dsn=creds.dsn_string, debug=True) as db:
2021
loader = Loader(db=db)
21-
collection = [
22-
collection.to_dict()
23-
] # pypgstac wants either a string or an Iterable of dicts.
24-
loader.load_collections(file=collection, insert_mode=Methods.upsert)
22+
loader.load_collections(
23+
file=[collection.model_dump(mode="json")], insert_mode=Methods.upsert
24+
)
2525
except Exception as e:
26-
print(f"Encountered failure loading collection into pgSTAC: {e}")
26+
raise HTTPException(
27+
status_code=500,
28+
detail=f"Encountered failure loading collection into pgSTAC: {e}",
29+
) from e
2730

2831

2932
def delete(collection_id: str):

lib/ingestor-api/runtime/src/utils.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import boto3
44
import pydantic
5-
from fastapi.encoders import jsonable_encoder
65
from pypgstac.db import PgstacDB
76
from pypgstac.load import Methods
87

@@ -41,8 +40,7 @@ def load_items(creds: DbCreds, ingestions: Sequence[Ingestion]):
4140
with PgstacDB(dsn=creds.dsn_string, debug=True) as db:
4241
loader = Loader(db=db)
4342

44-
# serialize to JSON-friendly dicts (won't be necessary in Pydantic v2, https://github.com/pydantic/pydantic/issues/1409#issuecomment-1423995424)
45-
items = jsonable_encoder(i.item for i in ingestions)
43+
items = [i.item.model_dump(mode="json") for i in ingestions]
4644
loading_result = loader.load_items(
4745
file=items,
4846
# use insert_ignore to avoid overwritting existing items or upsert to replace

lib/ingestor-api/runtime/tests/test_collection.py

+52-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import pytest
55
import src.collection as collection
6+
from fastapi import HTTPException
67
from pypgstac.load import Methods
78
from src.utils import DbCreds
89

@@ -31,6 +32,56 @@ def test_load_collections(stac_collection, loader, pgstacdb):
3132
collection.ingest(stac_collection)
3233

3334
loader.return_value.load_collections.assert_called_once_with(
34-
file=[stac_collection.to_dict()],
35+
file=[stac_collection.model_dump(mode="json")],
3536
insert_mode=Methods.upsert,
3637
)
38+
39+
40+
def test_ingest_loader_error(stac_collection, pgstacdb):
41+
"""Test handling of errors during the loading process."""
42+
with patch(
43+
"src.collection.get_db_credentials",
44+
return_value=DbCreds(
45+
username="", password="", host="", port=1, dbname="", engine=""
46+
),
47+
):
48+
os.environ["DB_SECRET_ARN"] = ""
49+
50+
with patch("src.collection.Loader") as mock_loader:
51+
mock_loader_instance = Mock()
52+
mock_loader.return_value = mock_loader_instance
53+
mock_loader_instance.load_collections.side_effect = Exception(
54+
"Invalid collection data"
55+
)
56+
57+
with pytest.raises(HTTPException) as excinfo:
58+
collection.ingest(stac_collection)
59+
60+
assert excinfo.value.status_code == 500
61+
assert "Invalid collection data" in str(excinfo.value.detail)
62+
63+
64+
def test_ingest_missing_environment_variable(stac_collection):
65+
"""Test handling when the required environment variable is missing."""
66+
if "DB_SECRET_ARN" in os.environ:
67+
del os.environ["DB_SECRET_ARN"]
68+
69+
with pytest.raises(HTTPException) as excinfo:
70+
collection.ingest(stac_collection)
71+
72+
assert "DB_SECRET_ARN" in str(excinfo.value)
73+
74+
75+
def test_ingest_credentials_error(stac_collection):
76+
"""Test handling of errors during credential retrieval."""
77+
with patch(
78+
"src.collection.get_db_credentials",
79+
side_effect=Exception("Failed to retrieve credentials"),
80+
):
81+
os.environ["DB_SECRET_ARN"] = ""
82+
83+
with pytest.raises(HTTPException) as excinfo:
84+
collection.ingest(stac_collection)
85+
86+
assert excinfo.value.status_code == 500
87+
assert "Failed to retrieve credentials" in str(excinfo.value.detail)

lib/ingestor-api/runtime/tests/test_utils.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from unittest.mock import Mock, patch
22

33
import pytest
4-
from fastapi.encoders import jsonable_encoder
54
from pypgstac.load import Methods
65
from src.utils import DbCreds
76

@@ -28,8 +27,9 @@ def dbcreds():
2827
def test_load_items(loader, pgstacdb, example_ingestion, dbcreds):
2928
import src.utils as utils
3029

31-
utils.load_items(dbcreds, [example_ingestion])
30+
ingestions = [example_ingestion]
31+
utils.load_items(dbcreds, ingestions)
3232
loader.return_value.load_items.assert_called_once_with(
33-
file=jsonable_encoder([example_ingestion.item]),
33+
file=[i.item.model_dump(mode="json") for i in ingestions],
3434
insert_mode=Methods.upsert,
3535
)

0 commit comments

Comments
 (0)