stac-fastapi-core 6.7.6__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.7.6 → stac_fastapi_core-6.8.1}/PKG-INFO +2 -2
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/README.md +1 -1
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/base_database_logic.py +40 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/core.py +43 -2
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/__init__.py +2 -0
- stac_fastapi_core-6.8.1/stac_fastapi/core/extensions/catalogs.py +980 -0
- stac_fastapi_core-6.8.1/stac_fastapi/core/models/__init__.py +27 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/models/links.py +9 -2
- stac_fastapi_core-6.8.1/stac_fastapi/core/queryables.py +105 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/serializers.py +147 -1
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/version.py +1 -1
- stac_fastapi_core-6.7.6/stac_fastapi/core/models/__init__.py +0 -1
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/.gitignore +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/pyproject.toml +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/pytest.ini +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/__init__.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/base_settings.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/basic_auth.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/datetime_utils.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/aggregation.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/collections_search.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/fields.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/filter.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/query.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/models/search.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/rate_limit.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/redis_utils.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/route_dependencies.py +0 -0
- {stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/session.py +0 -0
- {stac_fastapi_core-6.7.6 → 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.
|
|
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
|
|
@@ -44,7 +44,7 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
[](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/network/members)
|
|
45
45
|
[](https://pypi.org/project/stac-fastapi-elasticsearch/)
|
|
46
46
|
[](https://github.com/radiantearth/stac-spec/tree/v1.1.0)
|
|
47
|
-
[](https://github.com/stac-utils/stac-fastapi)
|
|
48
48
|
|
|
49
49
|
Core functionality for stac-fastapi. For full documentation, please see the [main README](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/blob/main/README.md).
|
|
50
50
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/network/members)
|
|
11
11
|
[](https://pypi.org/project/stac-fastapi-elasticsearch/)
|
|
12
12
|
[](https://github.com/radiantearth/stac-spec/tree/v1.1.0)
|
|
13
|
-
[](https://github.com/stac-utils/stac-fastapi)
|
|
14
14
|
|
|
15
15
|
Core functionality for stac-fastapi. For full documentation, please see the [main README](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/blob/main/README.md).
|
|
16
16
|
|
{stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/base_database_logic.py
RENAMED
|
@@ -138,3 +138,43 @@ class BaseDatabaseLogic(abc.ABC):
|
|
|
138
138
|
) -> None:
|
|
139
139
|
"""Delete a collection from the database."""
|
|
140
140
|
pass
|
|
141
|
+
|
|
142
|
+
@abc.abstractmethod
|
|
143
|
+
async def get_queryables_mapping(self, collection_id: str = "*") -> Dict[str, Any]:
|
|
144
|
+
"""Retrieve mapping of Queryables for search."""
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
async def get_all_catalogs(
|
|
148
|
+
self,
|
|
149
|
+
token: Optional[str],
|
|
150
|
+
limit: int,
|
|
151
|
+
request: Any = None,
|
|
152
|
+
sort: Optional[List[Dict[str, Any]]] = None,
|
|
153
|
+
) -> Tuple[List[Dict[str, Any]], Optional[str], Optional[int]]:
|
|
154
|
+
"""Retrieve a list of catalogs from the database, supporting pagination.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
token (Optional[str]): The pagination token.
|
|
158
|
+
limit (int): The number of results to return.
|
|
159
|
+
request (Any, optional): The FastAPI request object. Defaults to None.
|
|
160
|
+
sort (Optional[List[Dict[str, Any]]], optional): Optional sort parameter. Defaults to None.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
A tuple of (catalogs, next pagination token if any, optional count).
|
|
164
|
+
"""
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
@abc.abstractmethod
|
|
168
|
+
async def create_catalog(self, catalog: Dict, refresh: bool = False) -> None:
|
|
169
|
+
"""Create a catalog in the database."""
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
@abc.abstractmethod
|
|
173
|
+
async def find_catalog(self, catalog_id: str) -> Dict:
|
|
174
|
+
"""Find a catalog in the database."""
|
|
175
|
+
pass
|
|
176
|
+
|
|
177
|
+
@abc.abstractmethod
|
|
178
|
+
async def delete_catalog(self, catalog_id: str, refresh: bool = False) -> None:
|
|
179
|
+
"""Delete a catalog from the database."""
|
|
180
|
+
pass
|
|
@@ -24,7 +24,15 @@ from stac_fastapi.core.base_database_logic import BaseDatabaseLogic
|
|
|
24
24
|
from stac_fastapi.core.base_settings import ApiBaseSettings
|
|
25
25
|
from stac_fastapi.core.datetime_utils import format_datetime_range
|
|
26
26
|
from stac_fastapi.core.models.links import PagingLinks
|
|
27
|
-
from stac_fastapi.core.
|
|
27
|
+
from stac_fastapi.core.queryables import (
|
|
28
|
+
QueryablesCache,
|
|
29
|
+
get_properties_from_cql2_filter,
|
|
30
|
+
)
|
|
31
|
+
from stac_fastapi.core.serializers import (
|
|
32
|
+
CatalogSerializer,
|
|
33
|
+
CollectionSerializer,
|
|
34
|
+
ItemSerializer,
|
|
35
|
+
)
|
|
28
36
|
from stac_fastapi.core.session import Session
|
|
29
37
|
from stac_fastapi.core.utilities import filter_fields, get_bool_env
|
|
30
38
|
from stac_fastapi.extensions.core.transaction import AsyncBaseTransactionsClient
|
|
@@ -81,12 +89,28 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
81
89
|
collection_serializer: Type[CollectionSerializer] = attr.ib(
|
|
82
90
|
default=CollectionSerializer
|
|
83
91
|
)
|
|
92
|
+
catalog_serializer: Type[CatalogSerializer] = attr.ib(default=CatalogSerializer)
|
|
84
93
|
post_request_model = attr.ib(default=BaseSearchPostRequest)
|
|
85
94
|
stac_version: str = attr.ib(default=STAC_VERSION)
|
|
86
95
|
landing_page_id: str = attr.ib(default="stac-fastapi")
|
|
87
96
|
title: str = attr.ib(default="stac-fastapi")
|
|
88
97
|
description: str = attr.ib(default="stac-fastapi")
|
|
89
98
|
|
|
99
|
+
def __attrs_post_init__(self):
|
|
100
|
+
"""Initialize the queryables cache."""
|
|
101
|
+
self.queryables_cache = QueryablesCache(self.database)
|
|
102
|
+
|
|
103
|
+
def extension_is_enabled(self, extension_name: str) -> bool:
|
|
104
|
+
"""Check if an extension is enabled by checking self.extensions.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
extension_name: Name of the extension class to check for.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
True if the extension is in self.extensions, False otherwise.
|
|
111
|
+
"""
|
|
112
|
+
return any(ext.__class__.__name__ == extension_name for ext in self.extensions)
|
|
113
|
+
|
|
90
114
|
def _landing_page(
|
|
91
115
|
self,
|
|
92
116
|
base_url: str,
|
|
@@ -150,6 +174,7 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
150
174
|
API landing page, serving as an entry point to the API.
|
|
151
175
|
"""
|
|
152
176
|
request: Request = kwargs["request"]
|
|
177
|
+
|
|
153
178
|
base_url = get_base_url(request)
|
|
154
179
|
landing_page = self._landing_page(
|
|
155
180
|
base_url=base_url,
|
|
@@ -207,6 +232,16 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
207
232
|
]
|
|
208
233
|
)
|
|
209
234
|
|
|
235
|
+
if self.extension_is_enabled("CatalogsExtension"):
|
|
236
|
+
landing_page["links"].append(
|
|
237
|
+
{
|
|
238
|
+
"rel": "catalogs",
|
|
239
|
+
"type": "application/json",
|
|
240
|
+
"title": "Catalogs",
|
|
241
|
+
"href": urljoin(base_url, "catalogs"),
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
|
|
210
245
|
# Add OpenAPI URL
|
|
211
246
|
landing_page["links"].append(
|
|
212
247
|
{
|
|
@@ -759,7 +794,7 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
759
794
|
|
|
760
795
|
body_limit = None
|
|
761
796
|
try:
|
|
762
|
-
if request.method == "POST" and request.body():
|
|
797
|
+
if request.method == "POST" and await request.body():
|
|
763
798
|
body_data = await request.json()
|
|
764
799
|
body_limit = body_data.get("limit")
|
|
765
800
|
except Exception:
|
|
@@ -817,6 +852,8 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
817
852
|
)
|
|
818
853
|
|
|
819
854
|
if hasattr(search_request, "query") and getattr(search_request, "query"):
|
|
855
|
+
query_fields = set(getattr(search_request, "query").keys())
|
|
856
|
+
await self.queryables_cache.validate(query_fields)
|
|
820
857
|
for field_name, expr in getattr(search_request, "query").items():
|
|
821
858
|
field = "properties__" + field_name
|
|
822
859
|
for op, value in expr.items():
|
|
@@ -835,7 +872,11 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
835
872
|
|
|
836
873
|
if cql2_filter is not None:
|
|
837
874
|
try:
|
|
875
|
+
query_fields = get_properties_from_cql2_filter(cql2_filter)
|
|
876
|
+
await self.queryables_cache.validate(query_fields)
|
|
838
877
|
search = await self.database.apply_cql2_filter(search, cql2_filter)
|
|
878
|
+
except HTTPException:
|
|
879
|
+
raise
|
|
839
880
|
except Exception as e:
|
|
840
881
|
raise HTTPException(
|
|
841
882
|
status_code=400, detail=f"Error with cql2 filter: {e}"
|
{stac_fastapi_core-6.7.6 → stac_fastapi_core-6.8.1}/stac_fastapi/core/extensions/__init__.py
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""elasticsearch extensions modifications."""
|
|
2
2
|
|
|
3
|
+
from .catalogs import CatalogsExtension
|
|
3
4
|
from .collections_search import CollectionsSearchEndpointExtension
|
|
4
5
|
from .query import Operator, QueryableTypes, QueryExtension
|
|
5
6
|
|
|
@@ -8,4 +9,5 @@ __all__ = [
|
|
|
8
9
|
"QueryableTypes",
|
|
9
10
|
"QueryExtension",
|
|
10
11
|
"CollectionsSearchEndpointExtension",
|
|
12
|
+
"CatalogsExtension",
|
|
11
13
|
]
|