sfeos-helpers 6.2.0__tar.gz → 6.2.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.
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/PKG-INFO +12 -2
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/README.md +1 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/setup.py +1 -1
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/sfeos_helpers.egg-info/PKG-INFO +13 -3
- sfeos_helpers-6.2.1/sfeos_helpers.egg-info/requires.txt +1 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/sfeos_helpers.egg-info/top_level.txt +1 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/query.py +5 -2
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/utils.py +75 -38
- sfeos_helpers-6.2.1/stac_fastapi/sfeos_helpers/models/patch.py +124 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/version.py +1 -1
- sfeos_helpers-6.2.0/sfeos_helpers.egg-info/requires.txt +0 -1
- sfeos_helpers-6.2.0/stac_fastapi/sfeos_helpers/models/patch.py +0 -166
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/setup.cfg +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/sfeos_helpers.egg-info/SOURCES.txt +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/sfeos_helpers.egg-info/dependency_links.txt +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/sfeos_helpers.egg-info/not-zip-safe +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/aggregation/__init__.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/aggregation/client.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/aggregation/format.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/__init__.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/datetime.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/document.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/index.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/database/mapping.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/filter/__init__.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/filter/client.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/filter/cql2.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/filter/transform.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/mappings.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/__init__.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/base.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/factory.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/index_operations.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/inserters.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/managers.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/selection/__init__.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/selection/base.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/selection/cache_manager.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/selection/factory.py +0 -0
- {sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/selection/selectors.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: sfeos_helpers
|
|
3
|
-
Version: 6.2.
|
|
3
|
+
Version: 6.2.1
|
|
4
4
|
Summary: Helper library for the Elasticsearch and Opensearch stac-fastapi backends.
|
|
5
5
|
Home-page: https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
|
@@ -15,6 +15,15 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Requires-Python: >=3.9
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: stac-fastapi.core==6.2.1
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
18
27
|
|
|
19
28
|
# stac-fastapi-elasticsearch-opensearch
|
|
20
29
|
|
|
@@ -245,6 +254,7 @@ You can customize additional settings in your `.env` file:
|
|
|
245
254
|
| `RAISE_ON_BULK_ERROR` | Controls whether bulk insert operations raise exceptions on errors. If set to `true`, the operation will stop and raise an exception when an error occurs. If set to `false`, errors will be logged, and the operation will continue. **Note:** STAC Item and ItemCollection validation errors will always raise, regardless of this flag. | `false` | Optional |
|
|
246
255
|
| `DATABASE_REFRESH` | Controls whether database operations refresh the index immediately after changes. If set to `true`, changes will be immediately searchable. If set to `false`, changes may not be immediately visible but can improve performance for bulk operations. If set to `wait_for`, changes will wait for the next refresh cycle to become visible. | `false` | Optional |
|
|
247
256
|
| `ENABLE_TRANSACTIONS_EXTENSIONS` | Enables or disables the Transactions and Bulk Transactions API extensions. If set to `false`, the POST `/collections` route and related transaction endpoints (including bulk transaction operations) will be unavailable in the API. This is useful for deployments where mutating the catalog via the API should be prevented. | `true` | Optional |
|
|
257
|
+
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
248
258
|
|
|
249
259
|
> [!NOTE]
|
|
250
260
|
> The variables `ES_HOST`, `ES_PORT`, `ES_USE_SSL`, `ES_VERIFY_CERTS` and `ES_TIMEOUT` apply to both Elasticsearch and OpenSearch backends, so there is no need to rename the key names to `OS_` even if you're using OpenSearch.
|
|
@@ -227,6 +227,7 @@ You can customize additional settings in your `.env` file:
|
|
|
227
227
|
| `RAISE_ON_BULK_ERROR` | Controls whether bulk insert operations raise exceptions on errors. If set to `true`, the operation will stop and raise an exception when an error occurs. If set to `false`, errors will be logged, and the operation will continue. **Note:** STAC Item and ItemCollection validation errors will always raise, regardless of this flag. | `false` | Optional |
|
|
228
228
|
| `DATABASE_REFRESH` | Controls whether database operations refresh the index immediately after changes. If set to `true`, changes will be immediately searchable. If set to `false`, changes may not be immediately visible but can improve performance for bulk operations. If set to `wait_for`, changes will wait for the next refresh cycle to become visible. | `false` | Optional |
|
|
229
229
|
| `ENABLE_TRANSACTIONS_EXTENSIONS` | Enables or disables the Transactions and Bulk Transactions API extensions. If set to `false`, the POST `/collections` route and related transaction endpoints (including bulk transaction operations) will be unavailable in the API. This is useful for deployments where mutating the catalog via the API should be prevented. | `true` | Optional |
|
|
230
|
+
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
230
231
|
|
|
231
232
|
> [!NOTE]
|
|
232
233
|
> The variables `ES_HOST`, `ES_PORT`, `ES_USE_SSL`, `ES_VERIFY_CERTS` and `ES_TIMEOUT` apply to both Elasticsearch and OpenSearch backends, so there is no need to rename the key names to `OS_` even if you're using OpenSearch.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
2
|
-
Name:
|
|
3
|
-
Version: 6.2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sfeos_helpers
|
|
3
|
+
Version: 6.2.1
|
|
4
4
|
Summary: Helper library for the Elasticsearch and Opensearch stac-fastapi backends.
|
|
5
5
|
Home-page: https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
|
@@ -15,6 +15,15 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Requires-Python: >=3.9
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: stac-fastapi.core==6.2.1
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
18
27
|
|
|
19
28
|
# stac-fastapi-elasticsearch-opensearch
|
|
20
29
|
|
|
@@ -245,6 +254,7 @@ You can customize additional settings in your `.env` file:
|
|
|
245
254
|
| `RAISE_ON_BULK_ERROR` | Controls whether bulk insert operations raise exceptions on errors. If set to `true`, the operation will stop and raise an exception when an error occurs. If set to `false`, errors will be logged, and the operation will continue. **Note:** STAC Item and ItemCollection validation errors will always raise, regardless of this flag. | `false` | Optional |
|
|
246
255
|
| `DATABASE_REFRESH` | Controls whether database operations refresh the index immediately after changes. If set to `true`, changes will be immediately searchable. If set to `false`, changes may not be immediately visible but can improve performance for bulk operations. If set to `wait_for`, changes will wait for the next refresh cycle to become visible. | `false` | Optional |
|
|
247
256
|
| `ENABLE_TRANSACTIONS_EXTENSIONS` | Enables or disables the Transactions and Bulk Transactions API extensions. If set to `false`, the POST `/collections` route and related transaction endpoints (including bulk transaction operations) will be unavailable in the API. This is useful for deployments where mutating the catalog via the API should be prevented. | `true` | Optional |
|
|
257
|
+
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
248
258
|
|
|
249
259
|
> [!NOTE]
|
|
250
260
|
> The variables `ES_HOST`, `ES_PORT`, `ES_USE_SSL`, `ES_VERIFY_CERTS` and `ES_TIMEOUT` apply to both Elasticsearch and OpenSearch backends, so there is no need to rename the key names to `OS_` even if you're using OpenSearch.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
stac-fastapi.core==6.2.1
|
|
@@ -80,11 +80,14 @@ def populate_sort_shared(sortby: List) -> Optional[Dict[str, Dict[str, str]]]:
|
|
|
80
80
|
This function transforms a list of sort specifications into the format required by
|
|
81
81
|
Elasticsearch/OpenSearch for sorting query results. The returned dictionary can be
|
|
82
82
|
directly used in search requests.
|
|
83
|
+
Always includes 'id' as secondary sort to ensure unique pagination tokens.
|
|
83
84
|
"""
|
|
84
85
|
if sortby:
|
|
85
|
-
|
|
86
|
+
sort_config = {s.field: {"order": s.direction} for s in sortby}
|
|
87
|
+
sort_config.setdefault("id", {"order": "asc"})
|
|
88
|
+
return sort_config
|
|
86
89
|
else:
|
|
87
|
-
return
|
|
90
|
+
return {"id": {"order": "asc"}}
|
|
88
91
|
|
|
89
92
|
|
|
90
93
|
def add_collections_to_body(
|
|
@@ -76,7 +76,7 @@ def merge_to_operations(data: Dict) -> List:
|
|
|
76
76
|
nested_operations = merge_to_operations(value)
|
|
77
77
|
|
|
78
78
|
for nested_operation in nested_operations:
|
|
79
|
-
nested_operation.path = f"{key}
|
|
79
|
+
nested_operation.path = f"{key}/{nested_operation.path}"
|
|
80
80
|
operations.append(nested_operation)
|
|
81
81
|
|
|
82
82
|
else:
|
|
@@ -90,6 +90,7 @@ def check_commands(
|
|
|
90
90
|
op: str,
|
|
91
91
|
path: ElasticPath,
|
|
92
92
|
from_path: bool = False,
|
|
93
|
+
create_nest: bool = False,
|
|
93
94
|
) -> None:
|
|
94
95
|
"""Add Elasticsearch checks to operation.
|
|
95
96
|
|
|
@@ -101,25 +102,44 @@ def check_commands(
|
|
|
101
102
|
|
|
102
103
|
"""
|
|
103
104
|
if path.nest:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
105
|
+
part_nest = ""
|
|
106
|
+
for index, path_part in enumerate(path.parts):
|
|
107
|
+
|
|
108
|
+
# Create nested dictionaries if not present for merge operations
|
|
109
|
+
if create_nest and not from_path:
|
|
110
|
+
value = "[:]"
|
|
111
|
+
for sub_part in reversed(path.parts[index + 1 :]):
|
|
112
|
+
value = f"['{sub_part}': {value}]"
|
|
113
|
+
|
|
114
|
+
commands.add(
|
|
115
|
+
f"if (!ctx._source{part_nest}.containsKey('{path_part}'))"
|
|
116
|
+
f"{{ctx._source{part_nest}['{path_part}'] = {value};}}"
|
|
117
|
+
f"{'' if index == len(path.parts) - 1 else' else '}"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
else:
|
|
121
|
+
commands.add(
|
|
122
|
+
f"if (!ctx._source{part_nest}.containsKey('{path_part}'))"
|
|
123
|
+
f"{{Debug.explain('{path_part} in {path.path} does not exist');}}"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
part_nest += f"['{path_part}']"
|
|
127
|
+
|
|
128
|
+
if from_path or op in ["remove", "replace", "test"]:
|
|
129
|
+
|
|
130
|
+
if isinstance(path.key, int):
|
|
131
|
+
commands.add(
|
|
132
|
+
f"if ((ctx._source{path.es_nest} instanceof ArrayList"
|
|
133
|
+
f" && ctx._source{path.es_nest}.size() < {abs(path.key)})"
|
|
134
|
+
f" || (!(ctx._source{path.es_nest} instanceof ArrayList)"
|
|
135
|
+
f" && !ctx._source{path.es_nest}.containsKey('{path.key}')))"
|
|
136
|
+
f"{{Debug.explain('{path.key} does not exist in {path.nest}');}}"
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
commands.add(
|
|
140
|
+
f"if (!ctx._source{path.es_nest}.containsKey('{path.key}'))"
|
|
141
|
+
f"{{Debug.explain('{path.key} does not exist in {path.nest}');}}"
|
|
142
|
+
)
|
|
123
143
|
|
|
124
144
|
|
|
125
145
|
def remove_commands(commands: ESCommandSet, path: ElasticPath) -> None:
|
|
@@ -130,15 +150,16 @@ def remove_commands(commands: ESCommandSet, path: ElasticPath) -> None:
|
|
|
130
150
|
path (ElasticPath): Path to value to be removed
|
|
131
151
|
|
|
132
152
|
"""
|
|
133
|
-
|
|
153
|
+
commands.add(f"def {path.variable_name};")
|
|
154
|
+
if isinstance(path.key, int):
|
|
134
155
|
commands.add(
|
|
135
|
-
f"
|
|
156
|
+
f"if (ctx._source{path.es_nest} instanceof ArrayList)"
|
|
157
|
+
f"{{{path.variable_name} = ctx._source{path.es_nest}.remove({path.es_key});}} else "
|
|
136
158
|
)
|
|
137
159
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
160
|
+
commands.add(
|
|
161
|
+
f"{path.variable_name} = ctx._source{path.es_nest}.remove('{path.key}');"
|
|
162
|
+
)
|
|
142
163
|
|
|
143
164
|
|
|
144
165
|
def add_commands(
|
|
@@ -160,21 +181,22 @@ def add_commands(
|
|
|
160
181
|
value = (
|
|
161
182
|
from_path.variable_name
|
|
162
183
|
if operation.op == "move"
|
|
163
|
-
else f"ctx._source
|
|
184
|
+
else f"ctx._source{from_path.es_path}"
|
|
164
185
|
)
|
|
186
|
+
|
|
165
187
|
else:
|
|
166
188
|
value = f"params.{path.param_key}"
|
|
167
189
|
params[path.param_key] = operation.value
|
|
168
190
|
|
|
169
|
-
if path.
|
|
191
|
+
if isinstance(path.key, int):
|
|
170
192
|
commands.add(
|
|
171
|
-
f"if (ctx._source{path.
|
|
172
|
-
f"{{ctx._source{path.
|
|
173
|
-
f"else
|
|
193
|
+
f"if (ctx._source{path.es_nest} instanceof ArrayList)"
|
|
194
|
+
f"{{ctx._source{path.es_nest}.{'add' if operation.op in ['add', 'move'] else 'set'}({path.es_key}, {value});}}"
|
|
195
|
+
f" else ctx._source{path.es_nest}['{path.es_key}'] = {value};"
|
|
174
196
|
)
|
|
175
197
|
|
|
176
198
|
else:
|
|
177
|
-
commands.add(f"ctx._source
|
|
199
|
+
commands.add(f"ctx._source{path.es_path} = {value};")
|
|
178
200
|
|
|
179
201
|
|
|
180
202
|
def test_commands(
|
|
@@ -190,14 +212,23 @@ def test_commands(
|
|
|
190
212
|
value = f"params.{path.param_key}"
|
|
191
213
|
params[path.param_key] = operation.value
|
|
192
214
|
|
|
215
|
+
if isinstance(path.key, int):
|
|
216
|
+
commands.add(
|
|
217
|
+
f"if (ctx._source{path.es_nest} instanceof ArrayList)"
|
|
218
|
+
f"{{if (ctx._source{path.es_nest}[{path.es_key}] != {value})"
|
|
219
|
+
f"{{Debug.explain('Test failed `{path.path}`"
|
|
220
|
+
f" != ' + ctx._source{path.es_path});}}"
|
|
221
|
+
f"}} else "
|
|
222
|
+
)
|
|
223
|
+
|
|
193
224
|
commands.add(
|
|
194
|
-
f"if (ctx._source
|
|
195
|
-
f"{{Debug.explain('Test failed `{path.path}`
|
|
196
|
-
f"
|
|
225
|
+
f"if (ctx._source{path.es_path} != {value})"
|
|
226
|
+
f"{{Debug.explain('Test failed `{path.path}`"
|
|
227
|
+
f" != ' + ctx._source{path.es_path});}}"
|
|
197
228
|
)
|
|
198
229
|
|
|
199
230
|
|
|
200
|
-
def operations_to_script(operations: List) -> Dict:
|
|
231
|
+
def operations_to_script(operations: List, create_nest: bool = False) -> Dict:
|
|
201
232
|
"""Convert list of operation to painless script.
|
|
202
233
|
|
|
203
234
|
Args:
|
|
@@ -215,10 +246,16 @@ def operations_to_script(operations: List) -> Dict:
|
|
|
215
246
|
ElasticPath(path=operation.from_) if hasattr(operation, "from_") else None
|
|
216
247
|
)
|
|
217
248
|
|
|
218
|
-
check_commands(
|
|
249
|
+
check_commands(
|
|
250
|
+
commands=commands, op=operation.op, path=path, create_nest=create_nest
|
|
251
|
+
)
|
|
219
252
|
if from_path is not None:
|
|
220
253
|
check_commands(
|
|
221
|
-
commands=commands,
|
|
254
|
+
commands=commands,
|
|
255
|
+
op=operation.op,
|
|
256
|
+
path=from_path,
|
|
257
|
+
from_path=True,
|
|
258
|
+
create_nest=create_nest,
|
|
222
259
|
)
|
|
223
260
|
|
|
224
261
|
if operation.op in ["remove", "move"]:
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""patch helpers."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any, Dict, Optional, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, model_validator
|
|
7
|
+
|
|
8
|
+
regex = re.compile(r"([^.' ]*:[^.'[ ]*)\.?")
|
|
9
|
+
replacements = str.maketrans({"/": "", ".": "", ":": "", "[": "", "]": ""})
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ESCommandSet:
|
|
13
|
+
"""Uses dictionary keys to behaviour of ordered set.
|
|
14
|
+
|
|
15
|
+
Yields:
|
|
16
|
+
str: Elasticsearch commands
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
dict_: Dict[str, None] = {}
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
"""Initialise ESCommandSet instance."""
|
|
23
|
+
self.dict_ = {}
|
|
24
|
+
|
|
25
|
+
def add(self, value: str):
|
|
26
|
+
"""Add command.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
value (str): value to be added
|
|
30
|
+
"""
|
|
31
|
+
self.dict_[value] = None
|
|
32
|
+
|
|
33
|
+
def remove(self, value: str):
|
|
34
|
+
"""Remove command.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
value (str): value to be removed
|
|
38
|
+
"""
|
|
39
|
+
del self.dict_[value]
|
|
40
|
+
|
|
41
|
+
def __iter__(self):
|
|
42
|
+
"""Iterate Elasticsearch commands.
|
|
43
|
+
|
|
44
|
+
Yields:
|
|
45
|
+
str: Elasticsearch command
|
|
46
|
+
"""
|
|
47
|
+
yield from self.dict_.keys()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def to_es(string: str):
|
|
51
|
+
"""Convert patch operation key to Elasticsearch key.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
string (str): string to be converted
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
_type_: converted string
|
|
58
|
+
"""
|
|
59
|
+
if matches := regex.findall(string):
|
|
60
|
+
for match in set(matches):
|
|
61
|
+
string = re.sub(rf"\.?{match}", f"['{match}']", string)
|
|
62
|
+
|
|
63
|
+
return string
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ElasticPath(BaseModel):
|
|
67
|
+
"""Converts a JSON path to an Elasticsearch path.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
path (str): JSON path to be converted.
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
parts: list[str] = []
|
|
75
|
+
|
|
76
|
+
path: Optional[str] = None
|
|
77
|
+
key: Optional[Union[str, int]] = None
|
|
78
|
+
nest: Optional[str] = None
|
|
79
|
+
|
|
80
|
+
es_path: Optional[str] = None
|
|
81
|
+
es_key: Optional[str] = None
|
|
82
|
+
es_nest: Optional[str] = None
|
|
83
|
+
|
|
84
|
+
variable_name: Optional[str] = None
|
|
85
|
+
param_key: Optional[str] = None
|
|
86
|
+
|
|
87
|
+
class Config:
|
|
88
|
+
"""Class config."""
|
|
89
|
+
|
|
90
|
+
frozen = True
|
|
91
|
+
|
|
92
|
+
@model_validator(mode="before")
|
|
93
|
+
@classmethod
|
|
94
|
+
def validate_model(cls, data: Any):
|
|
95
|
+
"""Set optional fields from JSON path.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
data (Any): input data
|
|
99
|
+
"""
|
|
100
|
+
data["parts"] = data["path"].lstrip("/").split("/")
|
|
101
|
+
|
|
102
|
+
data["key"] = data["parts"].pop(-1)
|
|
103
|
+
data["nest"] = "/".join(data["parts"])
|
|
104
|
+
data["path"] = data["nest"] + "/" + data["key"]
|
|
105
|
+
|
|
106
|
+
data["es_key"] = data["key"]
|
|
107
|
+
data["es_nest"] = "".join([f"['{part}']" for part in data["parts"]])
|
|
108
|
+
data["es_path"] = data["es_nest"] + f"['{data['es_key']}']"
|
|
109
|
+
|
|
110
|
+
if data["key"].lstrip("-").isdigit() or data["key"] == "-":
|
|
111
|
+
data["key"] = -1 if data["key"] == "-" else int(data["key"])
|
|
112
|
+
data["es_key"] = (
|
|
113
|
+
f"ctx._source{data['es_nest']}.size() - {-data['key']}"
|
|
114
|
+
if data["key"] < 0
|
|
115
|
+
else str(data["key"])
|
|
116
|
+
)
|
|
117
|
+
data["es_path"] = data["es_nest"] + f"[{data['es_key']}]"
|
|
118
|
+
|
|
119
|
+
data[
|
|
120
|
+
"variable_name"
|
|
121
|
+
] = f"{data['nest'].replace('/','_').replace(':','_')}_{str(data['key']).replace(':','_')}"
|
|
122
|
+
data["param_key"] = data["path"].translate(replacements)
|
|
123
|
+
|
|
124
|
+
return data
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""library version."""
|
|
2
|
-
__version__ = "6.2.
|
|
2
|
+
__version__ = "6.2.1"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
stac-fastapi.core==6.2.0
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
"""patch helpers."""
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
from typing import Any, Dict, Optional, Union
|
|
5
|
-
|
|
6
|
-
from pydantic import BaseModel, computed_field, model_validator
|
|
7
|
-
|
|
8
|
-
regex = re.compile(r"([^.' ]*:[^.'[ ]*)\.?")
|
|
9
|
-
replacements = str.maketrans({"/": "", ".": "", ":": "", "[": "", "]": ""})
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ESCommandSet:
|
|
13
|
-
"""Uses dictionary keys to behaviour of ordered set.
|
|
14
|
-
|
|
15
|
-
Yields:
|
|
16
|
-
str: Elasticsearch commands
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
dict_: Dict[str, None] = {}
|
|
20
|
-
|
|
21
|
-
def __init__(self):
|
|
22
|
-
"""Initialise ESCommandSet instance."""
|
|
23
|
-
self.dict_ = {}
|
|
24
|
-
|
|
25
|
-
def add(self, value: str):
|
|
26
|
-
"""Add command.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
value (str): value to be added
|
|
30
|
-
"""
|
|
31
|
-
self.dict_[value] = None
|
|
32
|
-
|
|
33
|
-
def remove(self, value: str):
|
|
34
|
-
"""Remove command.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
value (str): value to be removed
|
|
38
|
-
"""
|
|
39
|
-
del self.dict_[value]
|
|
40
|
-
|
|
41
|
-
def __iter__(self):
|
|
42
|
-
"""Iterate Elasticsearch commands.
|
|
43
|
-
|
|
44
|
-
Yields:
|
|
45
|
-
str: Elasticsearch command
|
|
46
|
-
"""
|
|
47
|
-
yield from self.dict_.keys()
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def to_es(string: str):
|
|
51
|
-
"""Convert patch operation key to Elasticsearch key.
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
string (str): string to be converted
|
|
55
|
-
|
|
56
|
-
Returns:
|
|
57
|
-
_type_: converted string
|
|
58
|
-
"""
|
|
59
|
-
if matches := regex.findall(string):
|
|
60
|
-
for match in set(matches):
|
|
61
|
-
string = re.sub(rf"\.?{match}", f"['{match}']", string)
|
|
62
|
-
|
|
63
|
-
return string
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class ElasticPath(BaseModel):
|
|
67
|
-
"""Converts a JSON path to an Elasticsearch path.
|
|
68
|
-
|
|
69
|
-
Args:
|
|
70
|
-
path (str): JSON path to be converted.
|
|
71
|
-
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
path: str
|
|
75
|
-
nest: Optional[str] = None
|
|
76
|
-
partition: Optional[str] = None
|
|
77
|
-
key: Optional[str] = None
|
|
78
|
-
|
|
79
|
-
es_path: Optional[str] = None
|
|
80
|
-
es_nest: Optional[str] = None
|
|
81
|
-
es_key: Optional[str] = None
|
|
82
|
-
|
|
83
|
-
index_: Optional[int] = None
|
|
84
|
-
|
|
85
|
-
@model_validator(mode="before")
|
|
86
|
-
@classmethod
|
|
87
|
-
def validate_model(cls, data: Any):
|
|
88
|
-
"""Set optional fields from JSON path.
|
|
89
|
-
|
|
90
|
-
Args:
|
|
91
|
-
data (Any): input data
|
|
92
|
-
"""
|
|
93
|
-
data["path"] = data["path"].lstrip("/").replace("/", ".")
|
|
94
|
-
data["nest"], data["partition"], data["key"] = data["path"].rpartition(".")
|
|
95
|
-
|
|
96
|
-
if data["key"].lstrip("-").isdigit() or data["key"] == "-":
|
|
97
|
-
data["index_"] = -1 if data["key"] == "-" else int(data["key"])
|
|
98
|
-
data["path"] = f"{data['nest']}[{data['index_']}]"
|
|
99
|
-
data["nest"], data["partition"], data["key"] = data["nest"].rpartition(".")
|
|
100
|
-
|
|
101
|
-
data["es_path"] = to_es(data["path"])
|
|
102
|
-
data["es_nest"] = f".{to_es(data['nest'])}" if data["nest"] else ""
|
|
103
|
-
data["es_key"] = to_es(data["key"])
|
|
104
|
-
|
|
105
|
-
return data
|
|
106
|
-
|
|
107
|
-
@computed_field # type: ignore[misc]
|
|
108
|
-
@property
|
|
109
|
-
def index(self) -> Union[int, str, None]:
|
|
110
|
-
"""Compute location of path.
|
|
111
|
-
|
|
112
|
-
Returns:
|
|
113
|
-
str: path index
|
|
114
|
-
"""
|
|
115
|
-
if self.index_ and self.index_ < 0:
|
|
116
|
-
|
|
117
|
-
return f"ctx._source.{self.location}.size() - {-self.index_}"
|
|
118
|
-
|
|
119
|
-
return self.index_
|
|
120
|
-
|
|
121
|
-
@computed_field # type: ignore[misc]
|
|
122
|
-
@property
|
|
123
|
-
def location(self) -> str:
|
|
124
|
-
"""Compute location of path.
|
|
125
|
-
|
|
126
|
-
Returns:
|
|
127
|
-
str: path location
|
|
128
|
-
"""
|
|
129
|
-
return self.nest + self.partition + self.key
|
|
130
|
-
|
|
131
|
-
@computed_field # type: ignore[misc]
|
|
132
|
-
@property
|
|
133
|
-
def es_location(self) -> str:
|
|
134
|
-
"""Compute location of path.
|
|
135
|
-
|
|
136
|
-
Returns:
|
|
137
|
-
str: path location
|
|
138
|
-
"""
|
|
139
|
-
if self.es_key and ":" in self.es_key:
|
|
140
|
-
return self.es_nest + self.es_key
|
|
141
|
-
return self.es_nest + self.partition + self.es_key
|
|
142
|
-
|
|
143
|
-
@computed_field # type: ignore[misc]
|
|
144
|
-
@property
|
|
145
|
-
def variable_name(self) -> str:
|
|
146
|
-
"""Variable name for scripting.
|
|
147
|
-
|
|
148
|
-
Returns:
|
|
149
|
-
str: variable name
|
|
150
|
-
"""
|
|
151
|
-
if self.index is not None:
|
|
152
|
-
return f"{self.location.replace('.','_').replace(':','_')}_{self.index}"
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
f"{self.nest.replace('.','_').replace(':','_')}_{self.key.replace(':','_')}"
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
@computed_field # type: ignore[misc]
|
|
159
|
-
@property
|
|
160
|
-
def param_key(self) -> str:
|
|
161
|
-
"""Param key for scripting.
|
|
162
|
-
|
|
163
|
-
Returns:
|
|
164
|
-
str: param key
|
|
165
|
-
"""
|
|
166
|
-
return self.path.translate(replacements)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/aggregation/__init__.py
RENAMED
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/aggregation/client.py
RENAMED
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/aggregation/format.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
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/__init__.py
RENAMED
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/base.py
RENAMED
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/factory.py
RENAMED
|
File without changes
|
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/inserters.py
RENAMED
|
File without changes
|
{sfeos_helpers-6.2.0 → sfeos_helpers-6.2.1}/stac_fastapi/sfeos_helpers/search_engine/managers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|