stac-fastapi.core 7.2.0__tar.gz → 8.0.0__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-7.2.0 → stac_fastapi_core-8.0.0}/PKG-INFO +9 -9
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/pyproject.toml +8 -8
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/base_database_logic.py +200 -34
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/catalogs_client.py +255 -171
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/core.py +671 -172
- stac_fastapi_core-8.0.0/stac_fastapi/core/etag.py +265 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/extensions/collections_search.py +13 -3
- stac_fastapi_core-8.0.0/stac_fastapi/core/extensions/filter.py +295 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/models/links.py +17 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/serializers.py +50 -3
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/utilities.py +29 -2
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/validate.py +45 -26
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/version.py +1 -1
- stac_fastapi_core-7.2.0/stac_fastapi/core/extensions/filter.py +0 -135
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/.gitignore +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/README.md +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/pytest.ini +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/__init__.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/base_settings.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/basic_auth.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/datetime_utils.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/exceptions.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/extensions/__init__.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/extensions/aggregation.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/extensions/fields.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/extensions/query.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/models/__init__.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/models/search.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/queryables.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/rate_limit.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/redis_utils.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/route_dependencies.py +0 -0
- {stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/session.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: stac_fastapi_core
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.0
|
|
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
|
|
@@ -15,29 +15,29 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.14
|
|
16
16
|
Requires-Python: >=3.11
|
|
17
17
|
Requires-Dist: attrs>=23.2.0
|
|
18
|
-
Requires-Dist:
|
|
18
|
+
Requires-Dist: cql2<0.7.0,>=0.6.0
|
|
19
|
+
Requires-Dist: fastapi<0.144,>=0.109
|
|
19
20
|
Requires-Dist: jsonschema~=4.26.0
|
|
20
|
-
Requires-Dist: orjson<3.
|
|
21
|
+
Requires-Dist: orjson<3.14,>=3.11
|
|
21
22
|
Requires-Dist: overrides<7.8,>=7.4
|
|
22
23
|
Requires-Dist: pydantic<3.0.0,>=2.4.1
|
|
23
|
-
Requires-Dist: pygeofilter<0.5.0,>=0.3.1
|
|
24
24
|
Requires-Dist: slowapi~=0.1.9
|
|
25
25
|
Requires-Dist: stac-fastapi-api==7.0.0
|
|
26
26
|
Requires-Dist: stac-fastapi-extensions==7.0.0
|
|
27
27
|
Requires-Dist: stac-fastapi-types==7.0.0
|
|
28
|
-
Requires-Dist: stac-pydantic<3.
|
|
29
|
-
Requires-Dist: starlette<1.
|
|
30
|
-
Requires-Dist: uvicorn<0.
|
|
28
|
+
Requires-Dist: stac-pydantic<3.8,>=3.7
|
|
29
|
+
Requires-Dist: starlette<1.9.0,>=0.35.0
|
|
30
|
+
Requires-Dist: uvicorn<0.55,>=0.23
|
|
31
31
|
Provides-Extra: catalogs
|
|
32
32
|
Requires-Dist: stac-fastapi-catalogs-extension==1.0.0; extra == 'catalogs'
|
|
33
33
|
Provides-Extra: redis
|
|
34
34
|
Requires-Dist: redis<8.2,>=6.4; extra == 'redis'
|
|
35
35
|
Requires-Dist: retry~=0.9.2; extra == 'redis'
|
|
36
36
|
Provides-Extra: sentry
|
|
37
|
-
Requires-Dist: sentry-sdk<2.
|
|
37
|
+
Requires-Dist: sentry-sdk<2.73,>=2.49; extra == 'sentry'
|
|
38
38
|
Provides-Extra: validator
|
|
39
39
|
Requires-Dist: jsonpatch; extra == 'validator'
|
|
40
|
-
Requires-Dist: stac-valid<4.
|
|
40
|
+
Requires-Dist: stac-valid<4.7,>=4.6.1; extra == 'validator'
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
|
|
43
43
|
# stac-fastapi-core
|
|
@@ -29,20 +29,20 @@ keywords = [
|
|
|
29
29
|
]
|
|
30
30
|
dynamic = ["version"]
|
|
31
31
|
dependencies = [
|
|
32
|
-
"fastapi>=0.109,<0.
|
|
32
|
+
"fastapi>=0.109,<0.144",
|
|
33
33
|
"attrs>=23.2.0",
|
|
34
34
|
"pydantic>=2.4.1,<3.0.0",
|
|
35
|
-
"stac_pydantic>=3.
|
|
35
|
+
"stac_pydantic>=3.7,<3.8",
|
|
36
36
|
"stac-fastapi.types==7.0.0",
|
|
37
37
|
"stac-fastapi.api==7.0.0",
|
|
38
38
|
"stac-fastapi.extensions==7.0.0",
|
|
39
|
-
"orjson>=3.11,<3.
|
|
39
|
+
"orjson>=3.11,<3.14",
|
|
40
40
|
"overrides>=7.4,<7.8",
|
|
41
|
-
"
|
|
41
|
+
"cql2>=0.6.0,<0.7.0",
|
|
42
42
|
"jsonschema~=4.26.0",
|
|
43
43
|
"slowapi~=0.1.9",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
44
|
+
"starlette>=0.35.0,<1.9.0",
|
|
45
|
+
"uvicorn>=0.23,<0.55",
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
[project.optional-dependencies]
|
|
@@ -51,13 +51,13 @@ redis = [
|
|
|
51
51
|
"retry~=0.9.2",
|
|
52
52
|
]
|
|
53
53
|
sentry = [
|
|
54
|
-
"sentry-sdk>=2.49,<2.
|
|
54
|
+
"sentry-sdk>=2.49,<2.73",
|
|
55
55
|
]
|
|
56
56
|
catalogs = [
|
|
57
57
|
"stac-fastapi-catalogs-extension==1.0.0",
|
|
58
58
|
]
|
|
59
59
|
validator = [
|
|
60
|
-
"stac-valid>=4.
|
|
60
|
+
"stac-valid>=4.6.1,<4.7",
|
|
61
61
|
"jsonpatch"
|
|
62
62
|
]
|
|
63
63
|
|
{stac_fastapi_core-7.2.0 → stac_fastapi_core-8.0.0}/stac_fastapi/core/base_database_logic.py
RENAMED
|
@@ -5,6 +5,17 @@ from typing import Any, Iterable
|
|
|
5
5
|
|
|
6
6
|
from stac_pydantic.shared import BBox
|
|
7
7
|
|
|
8
|
+
from stac_fastapi.core.etag import DocumentVersion
|
|
9
|
+
from stac_fastapi.sfeos_helpers.database import (
|
|
10
|
+
find_item_in_alias,
|
|
11
|
+
index_alias_by_collection_id,
|
|
12
|
+
mk_item_id,
|
|
13
|
+
)
|
|
14
|
+
from stac_fastapi.sfeos_helpers.search_engine import (
|
|
15
|
+
BaseIndexInserter,
|
|
16
|
+
DatetimeIndexInserter,
|
|
17
|
+
)
|
|
18
|
+
from stac_fastapi.types.errors import NotFoundError
|
|
8
19
|
from stac_fastapi.types.stac import Collection, Item
|
|
9
20
|
|
|
10
21
|
|
|
@@ -16,6 +27,12 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
16
27
|
Subclasses must provide implementations for these methods.
|
|
17
28
|
"""
|
|
18
29
|
|
|
30
|
+
client: Any
|
|
31
|
+
async_index_inserter: BaseIndexInserter
|
|
32
|
+
#: Search-engine exception raised when a document lookup misses. Concrete
|
|
33
|
+
#: backends set this to their engine-specific not-found error class.
|
|
34
|
+
not_found_error_class: type[Exception]
|
|
35
|
+
|
|
19
36
|
@abc.abstractmethod
|
|
20
37
|
async def get_all_collections(
|
|
21
38
|
self,
|
|
@@ -48,13 +65,85 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
48
65
|
pass
|
|
49
66
|
|
|
50
67
|
@abc.abstractmethod
|
|
51
|
-
async def get_one_item(
|
|
68
|
+
async def get_one_item(
|
|
69
|
+
self, collection_id: str, item_id: str, *, include_hidden: bool = False
|
|
70
|
+
) -> dict:
|
|
52
71
|
"""Retrieve a single item from the database."""
|
|
53
72
|
pass
|
|
54
73
|
|
|
74
|
+
async def get_item_for_write(self, collection_id: str, item_id: str) -> dict:
|
|
75
|
+
"""Retrieve an item for a write without applying read visibility filters.
|
|
76
|
+
|
|
77
|
+
Under datetime index filtering the real-time ``mget`` lookup is used
|
|
78
|
+
for the same reason as in :meth:`get_item_hit_for_write`.
|
|
79
|
+
"""
|
|
80
|
+
if isinstance(self.async_index_inserter, DatetimeIndexInserter):
|
|
81
|
+
hit = await self.get_item_hit_for_write(collection_id, item_id)
|
|
82
|
+
return hit["_source"]
|
|
83
|
+
return await self.get_one_item(collection_id, item_id, include_hidden=True)
|
|
84
|
+
|
|
85
|
+
async def get_item_hit_for_write(self, collection_id: str, item_id: str) -> dict:
|
|
86
|
+
"""Retrieve the write-lookup hit for an item, including its version.
|
|
87
|
+
|
|
88
|
+
Returns a hit dict carrying ``_source``, ``_index``, ``_seq_no`` and
|
|
89
|
+
``_primary_term``, so callers that then write via ``create_item`` can
|
|
90
|
+
pass the result back as ``existing_hit`` (the existence check is not
|
|
91
|
+
repeated) or read the stored version from it.
|
|
92
|
+
|
|
93
|
+
Under datetime index filtering, ``_id`` uniqueness is enforced per
|
|
94
|
+
physical index and a just-written document may not be visible to
|
|
95
|
+
``_search`` yet, so the lookup is a real-time ``mget`` over the
|
|
96
|
+
collection alias's concrete indexes instead.
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
NotFoundError: If the item does not exist in the collection.
|
|
100
|
+
"""
|
|
101
|
+
if isinstance(self.async_index_inserter, DatetimeIndexInserter):
|
|
102
|
+
try:
|
|
103
|
+
hit = await find_item_in_alias(
|
|
104
|
+
self.client,
|
|
105
|
+
index_alias_by_collection_id(collection_id),
|
|
106
|
+
mk_item_id(item_id, collection_id),
|
|
107
|
+
)
|
|
108
|
+
except self.not_found_error_class:
|
|
109
|
+
hit = None
|
|
110
|
+
if hit is None:
|
|
111
|
+
raise NotFoundError(
|
|
112
|
+
f"Item {item_id} does not exist inside Collection {collection_id}"
|
|
113
|
+
)
|
|
114
|
+
return hit
|
|
115
|
+
item, version = await self.get_one_item_with_version(
|
|
116
|
+
collection_id, item_id, include_hidden=True
|
|
117
|
+
)
|
|
118
|
+
return {
|
|
119
|
+
"_source": item,
|
|
120
|
+
"_index": version.index,
|
|
121
|
+
"_seq_no": version.seq_no,
|
|
122
|
+
"_primary_term": version.primary_term,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@abc.abstractmethod
|
|
126
|
+
async def get_one_item_with_version(
|
|
127
|
+
self, collection_id: str, item_id: str, *, include_hidden: bool = False
|
|
128
|
+
) -> tuple[dict, DocumentVersion]:
|
|
129
|
+
"""Retrieve a single item and the version of its stored document.
|
|
130
|
+
|
|
131
|
+
With `include_hidden`, HIDE_ITEM_PATH does not apply, as for a write.
|
|
132
|
+
"""
|
|
133
|
+
pass
|
|
134
|
+
|
|
55
135
|
@abc.abstractmethod
|
|
56
|
-
async def create_item(
|
|
57
|
-
|
|
136
|
+
async def create_item(
|
|
137
|
+
self,
|
|
138
|
+
item: dict,
|
|
139
|
+
refresh: bool = False,
|
|
140
|
+
version: DocumentVersion | None = None,
|
|
141
|
+
**kwargs: Any,
|
|
142
|
+
) -> DocumentVersion | None:
|
|
143
|
+
"""Create an item in the database; return the version it stored.
|
|
144
|
+
|
|
145
|
+
With `version` (If-Match), only that stored version is replaced; 412 otherwise.
|
|
146
|
+
"""
|
|
58
147
|
pass
|
|
59
148
|
|
|
60
149
|
@abc.abstractmethod
|
|
@@ -72,6 +161,7 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
72
161
|
item: dict,
|
|
73
162
|
base_url: str,
|
|
74
163
|
refresh: bool = True,
|
|
164
|
+
version: DocumentVersion | None = None,
|
|
75
165
|
) -> dict:
|
|
76
166
|
"""Patch a item in the database follows RF7396."""
|
|
77
167
|
pass
|
|
@@ -85,13 +175,18 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
85
175
|
base_url: str,
|
|
86
176
|
create_nest: bool = False,
|
|
87
177
|
refresh: bool = True,
|
|
178
|
+
version: DocumentVersion | None = None,
|
|
88
179
|
) -> dict:
|
|
89
180
|
"""Patch a item in the database follows RF6902."""
|
|
90
181
|
pass
|
|
91
182
|
|
|
92
183
|
@abc.abstractmethod
|
|
93
184
|
async def delete_item(
|
|
94
|
-
self,
|
|
185
|
+
self,
|
|
186
|
+
item_id: str,
|
|
187
|
+
collection_id: str,
|
|
188
|
+
refresh: bool = False,
|
|
189
|
+
version: DocumentVersion | None = None,
|
|
95
190
|
) -> None:
|
|
96
191
|
"""Delete an item from the database."""
|
|
97
192
|
pass
|
|
@@ -109,8 +204,10 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
109
204
|
pass
|
|
110
205
|
|
|
111
206
|
@abc.abstractmethod
|
|
112
|
-
async def create_collection(
|
|
113
|
-
|
|
207
|
+
async def create_collection(
|
|
208
|
+
self, collection: dict, refresh: bool = False
|
|
209
|
+
) -> DocumentVersion | None:
|
|
210
|
+
"""Create a collection in the database; return the version it stored."""
|
|
114
211
|
pass
|
|
115
212
|
|
|
116
213
|
@abc.abstractmethod
|
|
@@ -120,6 +217,7 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
120
217
|
collection: dict,
|
|
121
218
|
base_url: str,
|
|
122
219
|
refresh: bool = True,
|
|
220
|
+
version: DocumentVersion | None = None,
|
|
123
221
|
) -> dict:
|
|
124
222
|
"""Patch a collection in the database follows RF7396."""
|
|
125
223
|
pass
|
|
@@ -132,6 +230,7 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
132
230
|
base_url: str,
|
|
133
231
|
create_nest: bool = False,
|
|
134
232
|
refresh: bool = True,
|
|
233
|
+
version: DocumentVersion | None = None,
|
|
135
234
|
) -> dict:
|
|
136
235
|
"""Patch a collection in the database follows RF6902."""
|
|
137
236
|
pass
|
|
@@ -141,16 +240,47 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
141
240
|
"""Find a collection in the database."""
|
|
142
241
|
pass
|
|
143
242
|
|
|
243
|
+
@abc.abstractmethod
|
|
244
|
+
async def find_collection_with_version(
|
|
245
|
+
self, collection_id: str
|
|
246
|
+
) -> tuple[dict, DocumentVersion]:
|
|
247
|
+
"""Find a collection and the version of its stored document."""
|
|
248
|
+
pass
|
|
249
|
+
|
|
144
250
|
@abc.abstractmethod
|
|
145
251
|
async def update_collection(
|
|
146
|
-
self,
|
|
147
|
-
|
|
252
|
+
self,
|
|
253
|
+
collection_id: str,
|
|
254
|
+
collection: Collection,
|
|
255
|
+
preserve_parent_ids: bool = False,
|
|
256
|
+
version: DocumentVersion | None = None,
|
|
257
|
+
**kwargs: Any,
|
|
258
|
+
) -> DocumentVersion | None:
|
|
148
259
|
"""Update a collection in the database."""
|
|
149
260
|
pass
|
|
150
261
|
|
|
262
|
+
@abc.abstractmethod
|
|
263
|
+
async def update_parent_ids(
|
|
264
|
+
self,
|
|
265
|
+
doc_id: str,
|
|
266
|
+
doc_type: str,
|
|
267
|
+
parent_id: str,
|
|
268
|
+
add: bool,
|
|
269
|
+
refresh: bool | str = False,
|
|
270
|
+
) -> dict:
|
|
271
|
+
"""Atomically add or remove one parent id in a Collection's or Catalog's parent_ids.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
The stored document after the update.
|
|
275
|
+
"""
|
|
276
|
+
pass
|
|
277
|
+
|
|
151
278
|
@abc.abstractmethod
|
|
152
279
|
async def delete_collection(
|
|
153
|
-
self,
|
|
280
|
+
self,
|
|
281
|
+
collection_id: str,
|
|
282
|
+
refresh: bool = False,
|
|
283
|
+
version: DocumentVersion | None = None,
|
|
154
284
|
) -> None:
|
|
155
285
|
"""Delete a collection from the database."""
|
|
156
286
|
pass
|
|
@@ -175,6 +305,7 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
175
305
|
limit: int,
|
|
176
306
|
request: Any = None,
|
|
177
307
|
sort: list[dict[str, Any]] | None = None,
|
|
308
|
+
filter: dict[str, Any] | None = None,
|
|
178
309
|
) -> tuple[list[dict[str, Any]], str | None, int | None]:
|
|
179
310
|
"""Retrieve a list of catalogs from the database, supporting pagination.
|
|
180
311
|
|
|
@@ -183,6 +314,7 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
183
314
|
limit (int): The number of results to return.
|
|
184
315
|
request (Any, optional): The FastAPI request object. Defaults to None.
|
|
185
316
|
sort (Optional[List[Dict[str, Any]]], optional): Optional sort parameter. Defaults to None.
|
|
317
|
+
filter (Optional[Dict[str, Any]], optional): A CQL2 JSON filter the catalogs must match. Defaults to None.
|
|
186
318
|
|
|
187
319
|
Returns:
|
|
188
320
|
A tuple of (catalogs, next pagination token if any, optional count).
|
|
@@ -190,8 +322,13 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
190
322
|
pass
|
|
191
323
|
|
|
192
324
|
@abc.abstractmethod
|
|
193
|
-
async def create_catalog(
|
|
194
|
-
|
|
325
|
+
async def create_catalog(
|
|
326
|
+
self, catalog: dict, refresh: bool = False
|
|
327
|
+
) -> DocumentVersion | None:
|
|
328
|
+
"""Create a catalog; reject an id already used by any document.
|
|
329
|
+
|
|
330
|
+
Returns the version of the stored document.
|
|
331
|
+
"""
|
|
195
332
|
pass
|
|
196
333
|
|
|
197
334
|
@abc.abstractmethod
|
|
@@ -200,12 +337,34 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
200
337
|
pass
|
|
201
338
|
|
|
202
339
|
@abc.abstractmethod
|
|
203
|
-
async def
|
|
340
|
+
async def find_catalog_with_version(
|
|
341
|
+
self, catalog_id: str
|
|
342
|
+
) -> tuple[dict, DocumentVersion]:
|
|
343
|
+
"""Find a catalog and the version of its stored document."""
|
|
344
|
+
pass
|
|
345
|
+
|
|
346
|
+
@abc.abstractmethod
|
|
347
|
+
async def delete_catalog(
|
|
348
|
+
self,
|
|
349
|
+
catalog_id: str,
|
|
350
|
+
refresh: bool = False,
|
|
351
|
+
version: DocumentVersion | None = None,
|
|
352
|
+
) -> None:
|
|
204
353
|
"""Delete a catalog from the database.
|
|
205
354
|
|
|
206
355
|
Implementations MUST verify the document exists and is a Catalog
|
|
207
356
|
before deleting, raising NotFoundError otherwise; deleting a catalog
|
|
208
|
-
must never remove Collection or Item data.
|
|
357
|
+
must never remove Collection or Item data. With `version` (If-Match),
|
|
358
|
+
only that stored version is deleted, and nothing changes otherwise.
|
|
359
|
+
"""
|
|
360
|
+
pass
|
|
361
|
+
|
|
362
|
+
@abc.abstractmethod
|
|
363
|
+
async def unlink_catalog_orphans(self, catalog_id: str) -> None:
|
|
364
|
+
"""Unlink children that still reference a catalog that no longer exists.
|
|
365
|
+
|
|
366
|
+
Nothing is deleted. A retry of a catalog delete whose cleanup failed
|
|
367
|
+
calls this, with or without If-Match.
|
|
209
368
|
"""
|
|
210
369
|
pass
|
|
211
370
|
|
|
@@ -217,8 +376,9 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
217
376
|
token: str | None,
|
|
218
377
|
request: Any = None,
|
|
219
378
|
resource_type: str | None = None,
|
|
379
|
+
filter: dict[str, Any] | None = None,
|
|
220
380
|
) -> tuple[list[dict[str, Any]], int, str | None]:
|
|
221
|
-
"""Get children of a catalog.
|
|
381
|
+
"""Get children of a catalog, optionally matching a CQL2 JSON filter.
|
|
222
382
|
|
|
223
383
|
Returns:
|
|
224
384
|
Tuple of (children_list, total_count, next_token).
|
|
@@ -232,9 +392,15 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
232
392
|
limit: int,
|
|
233
393
|
token: str | None,
|
|
234
394
|
request: Any = None,
|
|
395
|
+
filter: dict[str, Any] | None = None,
|
|
396
|
+
sort: list[dict[str, Any]] | None = None,
|
|
397
|
+
q: list[str] | None = None,
|
|
235
398
|
) -> tuple[list[dict[str, Any]], int, str | None]:
|
|
236
399
|
"""Get collections of a catalog.
|
|
237
400
|
|
|
401
|
+
Optionally matching a CQL2 JSON `filter`, ordered by `sort`
|
|
402
|
+
({field, direction} pairs), and matching `q` free-text terms.
|
|
403
|
+
|
|
238
404
|
Returns:
|
|
239
405
|
Tuple of (collections_list, total_count, next_token).
|
|
240
406
|
"""
|
|
@@ -247,8 +413,9 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
247
413
|
limit: int,
|
|
248
414
|
token: str | None,
|
|
249
415
|
request: Any = None,
|
|
416
|
+
filter: dict[str, Any] | None = None,
|
|
250
417
|
) -> tuple[list[dict[str, Any]], int, str | None]:
|
|
251
|
-
"""Get sub-catalogs of a catalog.
|
|
418
|
+
"""Get sub-catalogs of a catalog, optionally matching a CQL2 JSON filter.
|
|
252
419
|
|
|
253
420
|
Returns:
|
|
254
421
|
Tuple of (catalogs_list, total_count, next_token).
|
|
@@ -295,34 +462,26 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
295
462
|
datetime: str | None = None,
|
|
296
463
|
limit: int = 10,
|
|
297
464
|
sortby: str | None = None,
|
|
298
|
-
|
|
299
|
-
filter_lang: str | None = None,
|
|
465
|
+
filter: dict[str, Any] | None = None,
|
|
300
466
|
token: str | None = None,
|
|
301
467
|
query: str | None = None,
|
|
302
468
|
fields: list[str] | None = None,
|
|
303
469
|
) -> Any:
|
|
304
|
-
"""Get items from a collection in a catalog."""
|
|
305
|
-
pass
|
|
306
|
-
|
|
307
|
-
@abc.abstractmethod
|
|
308
|
-
async def get_catalog_collection_item(
|
|
309
|
-
self,
|
|
310
|
-
catalog_id: str,
|
|
311
|
-
collection_id: str,
|
|
312
|
-
item_id: str,
|
|
313
|
-
request: Any,
|
|
314
|
-
) -> Any:
|
|
315
|
-
"""Get an item from a collection in a catalog."""
|
|
470
|
+
"""Get items from a collection in a catalog, optionally matching a CQL2 JSON filter."""
|
|
316
471
|
pass
|
|
317
472
|
|
|
318
473
|
@abc.abstractmethod
|
|
319
474
|
async def update_catalog(
|
|
320
475
|
self,
|
|
321
476
|
catalog_id: str,
|
|
322
|
-
catalog:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
477
|
+
catalog: dict,
|
|
478
|
+
refresh: bool | str = False,
|
|
479
|
+
version: DocumentVersion | None = None,
|
|
480
|
+
) -> DocumentVersion | None:
|
|
481
|
+
"""Replace a catalog, keeping its stored parent_ids; return the version stored.
|
|
482
|
+
|
|
483
|
+
With `version` (If-Match), only that stored version is replaced; 412 otherwise.
|
|
484
|
+
"""
|
|
326
485
|
pass
|
|
327
486
|
|
|
328
487
|
@abc.abstractmethod
|
|
@@ -388,7 +547,9 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
388
547
|
pass
|
|
389
548
|
|
|
390
549
|
@abc.abstractmethod
|
|
391
|
-
def populate_sort(
|
|
550
|
+
def populate_sort(
|
|
551
|
+
self, sortby: list, field_types: dict[str, str] | None = None
|
|
552
|
+
) -> Any:
|
|
392
553
|
"""Populate sort for the search."""
|
|
393
554
|
pass
|
|
394
555
|
|
|
@@ -464,6 +625,11 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
464
625
|
"""Check if a collection exists."""
|
|
465
626
|
pass
|
|
466
627
|
|
|
628
|
+
@abc.abstractmethod
|
|
629
|
+
def check_collection_exists_sync(self, collection_id: str) -> None:
|
|
630
|
+
"""Check if a collection exists, using the synchronous client."""
|
|
631
|
+
pass
|
|
632
|
+
|
|
467
633
|
@abc.abstractmethod
|
|
468
634
|
async def delete_items(self) -> None:
|
|
469
635
|
"""Delete all items."""
|