stac-fastapi-core 6.8.0__tar.gz → 6.8.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/PKG-INFO +1 -1
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/catalogs.py +57 -72
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/version.py +1 -1
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/.gitignore +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/README.md +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/pyproject.toml +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/pytest.ini +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/__init__.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/base_database_logic.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/base_settings.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/basic_auth.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/core.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/datetime_utils.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/__init__.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/aggregation.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/collections_search.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/fields.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/filter.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/query.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/models/__init__.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/models/links.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/models/search.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/queryables.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/rate_limit.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/redis_utils.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/route_dependencies.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/serializers.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/session.py +0 -0
- {stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/utilities.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stac_fastapi_core
|
|
3
|
-
Version: 6.8.
|
|
3
|
+
Version: 6.8.1
|
|
4
4
|
Summary: Core library for the Elasticsearch and Opensearch stac-fastapi backends.
|
|
5
5
|
Project-URL: Homepage, https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
{stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/catalogs.py
RENAMED
|
@@ -126,7 +126,7 @@ class CatalogsExtension(ApiExtension):
|
|
|
126
126
|
response_class=self.response_class,
|
|
127
127
|
status_code=204,
|
|
128
128
|
summary="Delete Catalog",
|
|
129
|
-
description="Delete a catalog.
|
|
129
|
+
description="Delete a catalog. All linked collections are unlinked and adopted by root if orphaned.",
|
|
130
130
|
tags=["Catalogs"],
|
|
131
131
|
)
|
|
132
132
|
|
|
@@ -337,22 +337,21 @@ class CatalogsExtension(ApiExtension):
|
|
|
337
337
|
status_code=404, detail=f"Catalog {catalog_id} not found"
|
|
338
338
|
)
|
|
339
339
|
|
|
340
|
-
async def delete_catalog(
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
340
|
+
async def delete_catalog(self, catalog_id: str, request: Request) -> None:
|
|
341
|
+
"""Delete a catalog (The Container).
|
|
342
|
+
|
|
343
|
+
Deletes the Catalog document itself. All linked Collections are unlinked
|
|
344
|
+
and adopted by Root if they become orphans. Collection data is NEVER deleted.
|
|
345
|
+
|
|
346
|
+
Logic:
|
|
347
|
+
1. Finds all Collections linked to this Catalog.
|
|
348
|
+
2. Unlinks them (removes catalog_id from their parent_ids).
|
|
349
|
+
3. If a Collection becomes an orphan, it is adopted by Root.
|
|
350
|
+
4. PERMANENTLY DELETES the Catalog document itself.
|
|
350
351
|
|
|
351
352
|
Args:
|
|
352
353
|
catalog_id: The ID of the catalog to delete.
|
|
353
354
|
request: Request object.
|
|
354
|
-
cascade: If true, delete all collections linked to this catalog.
|
|
355
|
-
If false, only delete the catalog.
|
|
356
355
|
|
|
357
356
|
Returns:
|
|
358
357
|
None (204 No Content)
|
|
@@ -361,58 +360,42 @@ class CatalogsExtension(ApiExtension):
|
|
|
361
360
|
HTTPException: If the catalog is not found.
|
|
362
361
|
"""
|
|
363
362
|
try:
|
|
364
|
-
#
|
|
363
|
+
# Verify the catalog exists
|
|
365
364
|
await self.client.database.find_catalog(catalog_id)
|
|
366
365
|
|
|
367
|
-
#
|
|
368
|
-
# This is more reliable than parsing links, as it captures all collections
|
|
369
|
-
# regardless of pagination or link truncation.
|
|
366
|
+
# Find all collections with this catalog in parent_ids
|
|
370
367
|
query_body = {"query": {"term": {"parent_ids": catalog_id}}}
|
|
371
368
|
search_result = await self.client.database.client.search(
|
|
372
369
|
index=COLLECTIONS_INDEX, body=query_body, size=10000
|
|
373
370
|
)
|
|
374
371
|
children = [hit["_source"] for hit in search_result["hits"]["hits"]]
|
|
375
372
|
|
|
376
|
-
#
|
|
373
|
+
# Safe Unlink: Remove catalog from all children's parent_ids
|
|
374
|
+
# If a child becomes an orphan, adopt it to root
|
|
375
|
+
root_id = self.settings.get("STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi")
|
|
376
|
+
|
|
377
377
|
for child in children:
|
|
378
378
|
child_id = child.get("id")
|
|
379
379
|
try:
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
# The collection survives and becomes a root-level collection if it has no other parents.
|
|
390
|
-
parent_ids = child.get("parent_ids", [])
|
|
391
|
-
if catalog_id in parent_ids:
|
|
392
|
-
parent_ids.remove(catalog_id)
|
|
393
|
-
child["parent_ids"] = parent_ids
|
|
394
|
-
|
|
395
|
-
# Update the collection in the database
|
|
396
|
-
# Note: Catalog links are now dynamically generated, so no need to remove them
|
|
397
|
-
await self.client.database.update_collection(
|
|
398
|
-
collection_id=child_id,
|
|
399
|
-
collection=child,
|
|
400
|
-
refresh=False,
|
|
380
|
+
parent_ids = child.get("parent_ids", [])
|
|
381
|
+
if catalog_id in parent_ids:
|
|
382
|
+
parent_ids.remove(catalog_id)
|
|
383
|
+
|
|
384
|
+
# If orphan, move to root
|
|
385
|
+
if len(parent_ids) == 0:
|
|
386
|
+
parent_ids.append(root_id)
|
|
387
|
+
logger.info(
|
|
388
|
+
f"Collection {child_id} adopted by root after catalog deletion."
|
|
401
389
|
)
|
|
402
|
-
|
|
403
|
-
# Log the result
|
|
404
|
-
if len(parent_ids) == 0:
|
|
405
|
-
logger.info(
|
|
406
|
-
f"Collection {child_id} is now a root-level orphan (no parent catalogs)"
|
|
407
|
-
)
|
|
408
|
-
else:
|
|
409
|
-
logger.info(
|
|
410
|
-
f"Removed catalog {catalog_id} from collection {child_id}; still belongs to {len(parent_ids)} other catalog(s)"
|
|
411
|
-
)
|
|
412
390
|
else:
|
|
413
|
-
logger.
|
|
414
|
-
f"
|
|
391
|
+
logger.info(
|
|
392
|
+
f"Removed catalog {catalog_id} from collection {child_id}; still belongs to {len(parent_ids)} other catalog(s)"
|
|
415
393
|
)
|
|
394
|
+
|
|
395
|
+
child["parent_ids"] = parent_ids
|
|
396
|
+
await self.client.database.update_collection(
|
|
397
|
+
collection_id=child_id, collection=child, refresh=False
|
|
398
|
+
)
|
|
416
399
|
except Exception as e:
|
|
417
400
|
error_msg = str(e)
|
|
418
401
|
if "not found" in error_msg.lower():
|
|
@@ -929,11 +912,11 @@ class CatalogsExtension(ApiExtension):
|
|
|
929
912
|
async def delete_catalog_collection(
|
|
930
913
|
self, catalog_id: str, collection_id: str, request: Request
|
|
931
914
|
) -> None:
|
|
932
|
-
"""Delete a collection from a catalog.
|
|
915
|
+
"""Delete a collection from a catalog (Unlink only).
|
|
933
916
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
collection
|
|
917
|
+
Removes the catalog from the collection's parent_ids.
|
|
918
|
+
If the collection becomes an orphan (no parents), it is adopted by the Root.
|
|
919
|
+
It NEVER deletes the collection data.
|
|
937
920
|
|
|
938
921
|
Args:
|
|
939
922
|
catalog_id: The ID of the catalog.
|
|
@@ -959,37 +942,39 @@ class CatalogsExtension(ApiExtension):
|
|
|
959
942
|
detail=f"Collection {collection_id} does not belong to catalog {catalog_id}",
|
|
960
943
|
)
|
|
961
944
|
|
|
962
|
-
#
|
|
963
|
-
|
|
964
|
-
parent_ids.remove(catalog_id)
|
|
965
|
-
collection_db["parent_ids"] = parent_ids
|
|
945
|
+
# SAFE UNLINK LOGIC
|
|
946
|
+
parent_ids.remove(catalog_id)
|
|
966
947
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
948
|
+
# Check if it is now an orphan (empty list)
|
|
949
|
+
if len(parent_ids) == 0:
|
|
950
|
+
# Fallback to Root / Landing Page
|
|
951
|
+
# You can hardcode 'root' or fetch the ID from settings
|
|
952
|
+
root_id = self.settings.get(
|
|
953
|
+
"STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi"
|
|
971
954
|
)
|
|
972
|
-
|
|
955
|
+
parent_ids.append(root_id)
|
|
973
956
|
logger.info(
|
|
974
|
-
f"
|
|
957
|
+
f"Collection {collection_id} unlinked from {catalog_id}. Orphaned, so adopted by root ({root_id})."
|
|
975
958
|
)
|
|
976
959
|
else:
|
|
977
|
-
# If this is the only parent, delete the collection entirely
|
|
978
|
-
await self.client.database.delete_collection(
|
|
979
|
-
collection_id, refresh=True
|
|
980
|
-
)
|
|
981
960
|
logger.info(
|
|
982
|
-
f"
|
|
961
|
+
f"Removed catalog {catalog_id} from collection {collection_id}; still belongs to {len(parent_ids)} other catalog(s)"
|
|
983
962
|
)
|
|
984
963
|
|
|
964
|
+
# Update the collection in the database
|
|
965
|
+
collection_db["parent_ids"] = parent_ids
|
|
966
|
+
await self.client.database.update_collection(
|
|
967
|
+
collection_id=collection_id, collection=collection_db, refresh=True
|
|
968
|
+
)
|
|
969
|
+
|
|
985
970
|
except HTTPException:
|
|
986
971
|
raise
|
|
987
972
|
except Exception as e:
|
|
988
973
|
logger.error(
|
|
989
|
-
f"Error
|
|
974
|
+
f"Error removing collection {collection_id} from catalog {catalog_id}: {e}",
|
|
990
975
|
exc_info=True,
|
|
991
976
|
)
|
|
992
977
|
raise HTTPException(
|
|
993
978
|
status_code=500,
|
|
994
|
-
detail=f"Failed to
|
|
979
|
+
detail=f"Failed to remove collection from catalog: {str(e)}",
|
|
995
980
|
)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""library version."""
|
|
2
|
-
__version__ = "6.8.
|
|
2
|
+
__version__ = "6.8.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/base_database_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/__init__.py
RENAMED
|
File without changes
|
{stac_fastapi_core-6.8.0 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/aggregation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|