Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Deprecated

- Deprecated `BulkTransactionExtension` (`POST /collections/{collection_id}/bulk_items`). Use `TransactionExtension` instead, which supports `ItemCollection` payloads on `POST /collections/{collection_id}/items`. ([#987](https://github.com/stac-utils/stac-fastapi/pull/987))

### Fixed

- Return a `Location` header with the URI of the newly created resource for `POST /collections/{collection_id}/items` (single `Item`) and `POST /collections` in the Transaction extension, as required by the spec. `ItemCollection` payloads still return 201 without a `Location` header. The header is also added when a client returns a `Response` object directly, unless it already sets `Location` or returns an error status. ([#982](https://github.com/stac-utils/stac-fastapi/pull/982))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Bulk transactions extension."""

import abc
import warnings
from collections.abc import Sequence
from enum import StrEnum
from typing import Any, TypedDict
Expand Down Expand Up @@ -123,6 +124,10 @@ async def bulk_item_insert(
class BulkTransactionExtension(ApiExtension):
"""Bulk Transaction Extension.

Deprecated: this extension is deprecated and will be removed in a future
release. Use `TransactionExtension` instead, which supports `ItemCollection`
payloads on `POST /collections/{collection_id}/items`.

Bulk Transaction extension adds the `POST
/collections/{collection_id}/bulk_items` endpoint to the application for
efficient bulk insertion of items. The input to this is an object with an
Expand Down Expand Up @@ -151,6 +156,17 @@ class BulkTransactionExtension(ApiExtension):
route_dependencies: Sequence[Depends] | None = attr.ib(default=None)
enable_response_models: bool = attr.ib(default=True)

def __attrs_post_init__(self):
"""Warn about the extension's deprecation."""
warnings.warn(
"BulkTransactionExtension is deprecated and will be removed in a "
"future release. Use TransactionExtension instead, which supports "
"ItemCollection payloads on "
"POST /collections/{collection_id}/items.",
DeprecationWarning,
stacklevel=2,
)

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

Expand All @@ -166,6 +182,7 @@ def register(self, app: FastAPI) -> None:
router.add_api_route(
name="Bulk Create Item",
path="/collections/{collection_id}/bulk_items",
deprecated=True,
response_model=BulkTransactionModel,
responses={
200: {
Expand Down
73 changes: 42 additions & 31 deletions stac_fastapi/extensions/tests/test_bulk_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,17 @@ def test_base_client_chunks():
assert chunks_large == [[1, 2, 3, 4, 5, 6, 7]]


def test_bulk_transaction_extension_deprecated():
"""BulkTransactionExtension emits a DeprecationWarning."""
with pytest.warns(DeprecationWarning, match="deprecated"):
BulkTransactionExtension(client=Mock(spec=AsyncBaseBulkTransactionsClient))


def test_bulk_transaction_extension_defaults():
"""Test the default instantiation of the BulkTransactionExtension."""
mock_client = Mock(spec=AsyncBaseBulkTransactionsClient)
ext = BulkTransactionExtension(client=mock_client)
with pytest.warns(DeprecationWarning, match="deprecated"):
ext = BulkTransactionExtension(client=mock_client)

assert ext.client == mock_client
assert ext.schema_href is None
Expand All @@ -67,12 +74,13 @@ def test_bulk_transaction_extension_customization():
custom_schema = "https://example.com/bulk-schema.json"
custom_dependencies = [Depends(must_be_bob)]

ext = BulkTransactionExtension(
client=mock_client,
conformance_classes=custom_conformance,
schema_href=custom_schema,
route_dependencies=custom_dependencies,
)
with pytest.warns(DeprecationWarning, match="deprecated"):
ext = BulkTransactionExtension(
client=mock_client,
conformance_classes=custom_conformance,
schema_href=custom_schema,
route_dependencies=custom_dependencies,
)

assert ext.conformance_classes == custom_conformance
assert ext.schema_href == custom_schema
Expand Down Expand Up @@ -154,13 +162,14 @@ def client(
) -> Iterator[TestClient]:
"""Fixture to set up the TestClient with the BulkTransactionExtension."""
settings = ApiSettings()
api = StacApi(
settings=settings,
client=core_client,
extensions=[
BulkTransactionExtension(client=bulk_transactions_client),
],
)
with pytest.warns(DeprecationWarning, match="deprecated"):
api = StacApi(
settings=settings,
client=core_client,
extensions=[
BulkTransactionExtension(client=bulk_transactions_client),
],
)
with TestClient(api.app) as client:
yield client

Expand All @@ -169,13 +178,14 @@ def client(
def client_with_error(core_client: DummyCoreClient) -> Iterator[TestClient]:
"""Fixture to set up the TestClient with the BulkTransactionExtension."""
settings = ApiSettings()
api = StacApi(
settings=settings,
client=core_client,
extensions=[
BulkTransactionExtension(client=DummyBulkTransactionsClientWithError()),
],
)
with pytest.warns(DeprecationWarning, match="deprecated"):
api = StacApi(
settings=settings,
client=core_client,
extensions=[
BulkTransactionExtension(client=DummyBulkTransactionsClientWithError()),
],
)
with TestClient(api.app) as client:
yield client

Expand Down Expand Up @@ -242,16 +252,17 @@ def test_bulk_item_invalid_method(client: TestClient, item: dict) -> None:
def test_bulk_item_insert_with_route_dependencies(item: dict) -> None:
"""Test route dependencies are applied to the bulk transactions route."""
settings = ApiSettings()
api = StacApi(
settings=settings,
client=DummyCoreClient(),
extensions=[
BulkTransactionExtension(
client=DummyBulkTransactionsClient(),
route_dependencies=[Depends(must_be_bob)],
),
],
)
with pytest.warns(DeprecationWarning, match="deprecated"):
api = StacApi(
settings=settings,
client=DummyCoreClient(),
extensions=[
BulkTransactionExtension(
client=DummyBulkTransactionsClient(),
route_dependencies=[Depends(must_be_bob)],
),
],
)
payload = {
"items": {item["id"]: item},
"method": "insert",
Expand Down
Loading