sfeos-helpers 6.10.0__py3-none-any.whl → 6.10.1__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sfeos_helpers
3
- Version: 6.10.0
3
+ Version: 6.10.1
4
4
  Summary: Helper 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
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Classifier: Programming Language :: Python :: 3.14
16
16
  Requires-Python: >=3.11
17
- Requires-Dist: stac-fastapi-core==6.10.0
17
+ Requires-Dist: stac-fastapi-core==6.10.1
18
18
  Description-Content-Type: text/markdown
19
19
 
20
20
  # sfeos-helpers
@@ -1,18 +1,18 @@
1
1
  stac_fastapi/sfeos_helpers/mappings.py,sha256=U0zrBZ-foLtPy25PwSJSJW5EFBMin03aTrw53natt3g,12964
2
- stac_fastapi/sfeos_helpers/version.py,sha256=bQiD_D-FuZl4YJZxrz9LK-THtzxnF7e-QdjJAiGBoSY,46
2
+ stac_fastapi/sfeos_helpers/version.py,sha256=AD8oiYJE5bGoF51nIlCATcNL2aBRMbKASqetnSyzqGA,46
3
3
  stac_fastapi/sfeos_helpers/aggregation/README.md,sha256=SDlvCOpKyaJrlJvx84T2RzCnGALe_PK51zNeo3RP9ac,2122
4
4
  stac_fastapi/sfeos_helpers/aggregation/__init__.py,sha256=Mym17lFh90by1GnoQgMyIKAqRNJnvCgVSXDYzjBiPQk,1210
5
5
  stac_fastapi/sfeos_helpers/aggregation/client.py,sha256=eaH1kTBRuBbt1Ikqk0rR8hcY3LEFr9_06UgMGP44ZcQ,17861
6
6
  stac_fastapi/sfeos_helpers/aggregation/format.py,sha256=qUW1jjh2EEjy-V7riliFR77grpi-AgsTmP76z60K5Lo,2011
7
7
  stac_fastapi/sfeos_helpers/database/README.md,sha256=TVYFDD4PqDD57ZsWBv4i4LawaL_DAEIOjM6OQuqwLAU,4049
8
- stac_fastapi/sfeos_helpers/database/__init__.py,sha256=M3EBI5X4QD_x0oG976ZNLvUSYSMJ2UJPMj4nkDMSXYg,3425
8
+ stac_fastapi/sfeos_helpers/database/__init__.py,sha256=DATeB7mvDzu26O09QJG_DOmFcKRClMZ9x47224-2W68,3655
9
9
  stac_fastapi/sfeos_helpers/database/catalogs.py,sha256=Sux7VAeCLWTk6845pt2YHFEJaecPxZ5vP2RT0G-M45k,6425
10
10
  stac_fastapi/sfeos_helpers/database/datetime.py,sha256=yVD-FQCmjjJGM0CxAKqzOWfdotHvVup1r8Pvd68WjTU,8578
11
11
  stac_fastapi/sfeos_helpers/database/document.py,sha256=LtjX15gvaOuZC_k2t_oQhys_c-zRTLN5rwX0hNJkHnM,1725
12
- stac_fastapi/sfeos_helpers/database/index.py,sha256=GS7xwkhG3ccUG4EY4KCzW_YQO3CxXbJ1QaGnv_E7pEg,8536
12
+ stac_fastapi/sfeos_helpers/database/index.py,sha256=Eqa94G_lYBGYmscNTC0NPuH9n9EkqGyxV1zidf_xB8I,8587
13
13
  stac_fastapi/sfeos_helpers/database/mapping.py,sha256=4vGUuBLGoBOkQ984pYOciiz9UUWb4sbZyt-iViIsmdM,3809
14
14
  stac_fastapi/sfeos_helpers/database/query.py,sha256=Qe78ZmFTyWMKBmz8PpJ3CUiWuoTojbTo9seSxNteC9E,9477
15
- stac_fastapi/sfeos_helpers/database/utils.py,sha256=FfQsO-01kn1Znw9qSrXDr-SBnJOXridMO1MpRphDEms,12732
15
+ stac_fastapi/sfeos_helpers/database/utils.py,sha256=p3kmY9fC08l_OKYGfKQWqQpjX4K27R_2iBv8xM8N58o,14751
16
16
  stac_fastapi/sfeos_helpers/filter/README.md,sha256=Rb5qHmDkI-7-o3I82Lb_zfmrviqUj958wef021xI6pQ,1955
17
17
  stac_fastapi/sfeos_helpers/filter/__init__.py,sha256=n3zL_MhEGOoxMz1KeijyK_UKiZ0MKPl90zHtYI5RAy8,1557
18
18
  stac_fastapi/sfeos_helpers/filter/client.py,sha256=_LX3mlW9MYhoMGxvyi7Eg-LJICElQXYGbzzhSPXYRtw,6517
@@ -23,13 +23,13 @@ stac_fastapi/sfeos_helpers/search_engine/__init__.py,sha256=Bi0cAtul3FuLjFceTPtE
23
23
  stac_fastapi/sfeos_helpers/search_engine/base.py,sha256=ww1yCDVuXCK7nIYwmmyxywIvDeB-l5ITVoxkSkdOoT0,2337
24
24
  stac_fastapi/sfeos_helpers/search_engine/factory.py,sha256=nPty3L8esypSVIzl5IKfmqQ1hVUIjMQ183Ksistr1bM,1066
25
25
  stac_fastapi/sfeos_helpers/search_engine/index_operations.py,sha256=AYc8lJ7TAK9tADw4kHDKvzF3nF8uUaCPPXRhWQzNHFo,7809
26
- stac_fastapi/sfeos_helpers/search_engine/inserters.py,sha256=HO0jm4zx9sRI_ioWVNQbkSCNeejQHM-8zOZJNHzn_50,13709
26
+ stac_fastapi/sfeos_helpers/search_engine/inserters.py,sha256=spyGwbKLT7u9qOMdOCyPS5zoLh8p4KTEPOOy04Uvrho,13780
27
27
  stac_fastapi/sfeos_helpers/search_engine/managers.py,sha256=fODO2aAiRhiuEEJic6JgIIR-RnI-EjUCWse0YkEdvM4,18000
28
28
  stac_fastapi/sfeos_helpers/search_engine/selection/__init__.py,sha256=qKd4KzZkERwF_yhIeFcjAUnq5vQarr3CuXxE3SWmt6c,441
29
29
  stac_fastapi/sfeos_helpers/search_engine/selection/base.py,sha256=YANRYcosHsZQ1jnkjBUFoNF5V_Xh2efg9BGh411MGxI,1067
30
30
  stac_fastapi/sfeos_helpers/search_engine/selection/cache_manager.py,sha256=dLIZRWSQ-t4YWXHDw4pyr1My3G26ewIg53zkKUvWGbo,6086
31
31
  stac_fastapi/sfeos_helpers/search_engine/selection/factory.py,sha256=vbgNVCUW2lviePqzpgsPLxp6IEqcX3GHiahqN2oVObA,1305
32
- stac_fastapi/sfeos_helpers/search_engine/selection/selectors.py,sha256=LH_JZUs_gJSvACLL8BHOg0594ePCQ_XFtG_OSZx5Oj0,7117
33
- sfeos_helpers-6.10.0.dist-info/METADATA,sha256=0ftfZvtVk3oxJiDcetPSVOqwDy_mi4AsXlv37kzoPH0,3116
34
- sfeos_helpers-6.10.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
35
- sfeos_helpers-6.10.0.dist-info/RECORD,,
32
+ stac_fastapi/sfeos_helpers/search_engine/selection/selectors.py,sha256=L_NKw1BNNBgu6o6HNupUFinYDFUex2GItr2jABx_0UE,7116
33
+ sfeos_helpers-6.10.1.dist-info/METADATA,sha256=z6T2mi71Kb-r3QHwekALGZSDVf7of943gssfB9---Rs,3116
34
+ sfeos_helpers-6.10.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
35
+ sfeos_helpers-6.10.1.dist-info/RECORD,,
@@ -60,7 +60,14 @@ from .query import (
60
60
  apply_intersects_filter_shared,
61
61
  populate_sort_shared,
62
62
  )
63
- from .utils import add_bbox_shape_to_collection, get_bool_env, validate_refresh
63
+ from .utils import (
64
+ ItemAlreadyExistsError,
65
+ add_bbox_shape_to_collection,
66
+ check_item_exists_in_alias,
67
+ check_item_exists_in_alias_sync,
68
+ get_bool_env,
69
+ validate_refresh,
70
+ )
64
71
 
65
72
  __all__ = [
66
73
  # Catalog operations
@@ -90,6 +97,10 @@ __all__ = [
90
97
  "validate_refresh",
91
98
  "get_bool_env",
92
99
  "add_bbox_shape_to_collection",
100
+ "check_item_exists_in_alias",
101
+ "check_item_exists_in_alias_sync",
102
+ # Errors
103
+ "ItemAlreadyExistsError",
93
104
  # Datetime utilities
94
105
  "return_date",
95
106
  "extract_date",
@@ -165,7 +165,8 @@ def filter_indexes_by_datetime(
165
165
  datetime_alias if use_datetime else start_datetime_alias
166
166
  )
167
167
 
168
- filtered_indexes.append(primary_datetime_alias)
168
+ if primary_datetime_alias is not None:
169
+ filtered_indexes.append(primary_datetime_alias)
169
170
 
170
171
  return filtered_indexes
171
172
 
@@ -14,10 +14,73 @@ from stac_fastapi.extensions.core.transaction.request import (
14
14
  PatchRemove,
15
15
  )
16
16
  from stac_fastapi.sfeos_helpers.models.patch import ElasticPath, ESCommandSet
17
+ from stac_fastapi.types.errors import ConflictError
17
18
 
18
19
  logger = logging.getLogger(__name__)
19
20
 
20
21
 
22
+ class ItemAlreadyExistsError(ConflictError):
23
+ """Error raised when attempting to create an item that already exists.
24
+
25
+ Attributes:
26
+ item_id: The ID of the item that already exists.
27
+ collection_id: The ID of the collection containing the item.
28
+ """
29
+
30
+ def __init__(self, item_id: str, collection_id: str):
31
+ """Initialize the error with item and collection IDs."""
32
+ self.item_id = item_id
33
+ self.collection_id = collection_id
34
+ message = f"Item {item_id} in collection {collection_id} already exists"
35
+ super().__init__(message)
36
+
37
+
38
+ async def check_item_exists_in_alias(client: Any, alias: str, doc_id: str) -> bool:
39
+ """Check if an item exists across all indexes for an alias.
40
+
41
+ Args:
42
+ client: The async Elasticsearch/OpenSearch client.
43
+ alias: The index alias to search against.
44
+ doc_id: The document ID to check for existence.
45
+
46
+ Returns:
47
+ bool: True if the item exists in any index under the alias, False otherwise.
48
+ """
49
+ resp = await client.search(
50
+ index=alias,
51
+ body={
52
+ "query": {"ids": {"values": [doc_id]}},
53
+ "_source": False,
54
+ },
55
+ size=0,
56
+ terminate_after=1,
57
+ )
58
+ return bool(resp["hits"]["total"]["value"])
59
+
60
+
61
+ def check_item_exists_in_alias_sync(client: Any, alias: str, doc_id: str) -> bool:
62
+ """Check if an item exists across all indexes for an alias (sync).
63
+
64
+ Args:
65
+ client: The sync Elasticsearch/OpenSearch client.
66
+ alias: The index alias to search against.
67
+ doc_id: The document ID to check for existence.
68
+
69
+ Returns:
70
+ bool: True if the item exists in any index under the alias, False otherwise.
71
+ """
72
+ resp = client.search(
73
+ index=alias,
74
+ body={
75
+ "query": {"ids": {"values": [doc_id]}},
76
+ "_source": False,
77
+ },
78
+ size=0,
79
+ terminate_after=1,
80
+ )
81
+ return bool(resp["hits"]["total"]["value"])
82
+
83
+
21
84
  def add_bbox_shape_to_collection(collection: Dict[str, Any]) -> bool:
22
85
  """Add bbox_shape field to a collection document for spatial queries.
23
86
 
@@ -257,8 +257,10 @@ class DatetimeIndexInserter(BaseIndexInserter):
257
257
  extract_date(latest_item["_source"]["properties"]["datetime"])
258
258
  ),
259
259
  end_datetime=str(
260
- extract_date(latest_item["_source"]["properties"]["end_datetime"])
261
- ),
260
+ extract_first_date_from_index(aliases_dict["end_datetime"])
261
+ )
262
+ if aliases_dict.get("end_datetime")
263
+ else None,
262
264
  )
263
265
 
264
266
  await self.datetime_manager.handle_oversized_index(
@@ -1,5 +1,4 @@
1
1
  """Async index selectors with datetime-based filtering."""
2
-
3
2
  from typing import Any, Dict, List, Optional, Tuple
4
3
 
5
4
  from stac_fastapi.core.utilities import get_bool_env
@@ -1,2 +1,2 @@
1
1
  """library version."""
2
- __version__ = "6.10.0"
2
+ __version__ = "6.10.1"