stac-fastapi.api 3.0.0a3__tar.gz → 3.0.0a4__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.
Files changed (25) hide show
  1. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/PKG-INFO +1 -1
  2. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/app.py +4 -6
  3. stac_fastapi_api-3.0.0a4/stac_fastapi/api/version.py +2 -0
  4. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi.api.egg-info/PKG-INFO +1 -1
  5. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/tests/test_app.py +106 -2
  6. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/tests/test_middleware.py +30 -0
  7. stac_fastapi_api-3.0.0a3/stac_fastapi/api/version.py +0 -2
  8. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/README.md +0 -0
  9. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/setup.cfg +0 -0
  10. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/setup.py +0 -0
  11. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/__init__.py +0 -0
  12. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/config.py +0 -0
  13. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/errors.py +0 -0
  14. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/middleware.py +0 -0
  15. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/models.py +0 -0
  16. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/openapi.py +0 -0
  17. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi/api/routes.py +0 -0
  18. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi.api.egg-info/SOURCES.txt +0 -0
  19. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi.api.egg-info/dependency_links.txt +0 -0
  20. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi.api.egg-info/not-zip-safe +0 -0
  21. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi.api.egg-info/requires.txt +0 -0
  22. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/stac_fastapi.api.egg-info/top_level.txt +0 -0
  23. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/tests/test_api.py +0 -0
  24. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/tests/test_app_prefix.py +0 -0
  25. {stac_fastapi_api-3.0.0a3 → stac_fastapi_api-3.0.0a4}/tests/test_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.api
3
- Version: 3.0.0a3
3
+ Version: 3.0.0a4
4
4
  Summary: An implementation of STAC API based on the FastAPI framework.
5
5
  Home-page: https://github.com/stac-utils/stac-fastapi
6
6
  Author: Arturo Engineering
@@ -439,11 +439,6 @@ class StacApi:
439
439
  """
440
440
  return add_route_dependencies(self.app.router.routes, scopes, dependencies)
441
441
 
442
- def add_middleware(self, middleware: Middleware):
443
- """Add a middleware class to the application."""
444
- self.app.user_middleware.insert(0, middleware)
445
- self.app.middleware_stack = self.app.build_middleware_stack()
446
-
447
442
  def __attrs_post_init__(self):
448
443
  """Post-init hook.
449
444
 
@@ -483,8 +478,11 @@ class StacApi:
483
478
  self.app.openapi = self.customize_openapi
484
479
 
485
480
  # add middlewares
481
+ if self.middlewares and self.app.middleware_stack is not None:
482
+ raise RuntimeError("Cannot add middleware after an application has started")
483
+
486
484
  for middleware in self.middlewares:
487
- self.add_middleware(middleware)
485
+ self.app.user_middleware.insert(0, middleware)
488
486
 
489
487
  # customize route dependencies
490
488
  for scopes, dependencies in self.route_dependencies:
@@ -0,0 +1,2 @@
1
+ """Library version."""
2
+ __version__ = "3.0.0a4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.api
3
- Version: 3.0.0a3
3
+ Version: 3.0.0a4
4
4
  Summary: An implementation of STAC API based on the FastAPI framework.
5
5
  Home-page: https://github.com/stac-utils/stac-fastapi
6
6
  Author: Arturo Engineering
@@ -8,10 +8,10 @@ from stac_pydantic import api
8
8
 
9
9
  from stac_fastapi.api import app
10
10
  from stac_fastapi.api.models import create_get_request_model, create_post_request_model
11
- from stac_fastapi.extensions.core.filter.filter import FilterExtension
11
+ from stac_fastapi.extensions.core import FieldsExtension, FilterExtension
12
12
  from stac_fastapi.types import stac
13
13
  from stac_fastapi.types.config import ApiSettings
14
- from stac_fastapi.types.core import NumType
14
+ from stac_fastapi.types.core import BaseCoreClient, NumType
15
15
  from stac_fastapi.types.search import BaseSearchPostRequest
16
16
 
17
17
 
@@ -190,3 +190,107 @@ def test_filter_extension(validate, TestCoreClient, item_dict):
190
190
  assert landing.status_code == 200, landing.text
191
191
  assert get_search.status_code == 200, get_search.text
192
192
  assert post_search.status_code == 200, post_search.text
193
+
194
+
195
+ @pytest.mark.parametrize("validate", [True, False])
196
+ def test_fields_extension(validate, TestCoreClient, item_dict):
197
+ """Test if fields Parameters are passed correctly."""
198
+
199
+ class BadCoreClient(BaseCoreClient):
200
+ def post_search(
201
+ self, search_request: BaseSearchPostRequest, **kwargs
202
+ ) -> stac.ItemCollection:
203
+ return {"not": "a proper stac item"}
204
+
205
+ def get_search(
206
+ self,
207
+ collections: Optional[List[str]] = None,
208
+ ids: Optional[List[str]] = None,
209
+ bbox: Optional[List[NumType]] = None,
210
+ intersects: Optional[str] = None,
211
+ datetime: Optional[Union[str, datetime]] = None,
212
+ limit: Optional[int] = 10,
213
+ **kwargs,
214
+ ) -> stac.ItemCollection:
215
+ return {"not": "a proper stac item"}
216
+
217
+ def get_item(self, item_id: str, collection_id: str, **kwargs) -> stac.Item:
218
+ raise NotImplementedError
219
+
220
+ def all_collections(self, **kwargs) -> stac.Collections:
221
+ raise NotImplementedError
222
+
223
+ def get_collection(self, collection_id: str, **kwargs) -> stac.Collection:
224
+ raise NotImplementedError
225
+
226
+ def item_collection(
227
+ self,
228
+ collection_id: str,
229
+ bbox: Optional[List[Union[float, int]]] = None,
230
+ datetime: Optional[Union[str, datetime]] = None,
231
+ limit: int = 10,
232
+ token: str = None,
233
+ **kwargs,
234
+ ) -> stac.ItemCollection:
235
+ raise NotImplementedError
236
+
237
+ test_app = app.StacApi(
238
+ settings=ApiSettings(enable_response_models=validate),
239
+ client=BadCoreClient(),
240
+ search_get_request_model=create_get_request_model([FieldsExtension()]),
241
+ search_post_request_model=create_post_request_model([FieldsExtension()]),
242
+ extensions=[FieldsExtension()],
243
+ )
244
+
245
+ with TestClient(test_app.app) as client:
246
+ get_search = client.get(
247
+ "/search",
248
+ params={"fields": "properties.datetime"},
249
+ )
250
+ post_search = client.post(
251
+ "/search",
252
+ json={
253
+ "collections": ["test"],
254
+ "fields": {
255
+ "include": ["properties.datetime"],
256
+ "exclude": [],
257
+ },
258
+ },
259
+ )
260
+
261
+ assert get_search.status_code == 200, get_search.text
262
+ assert post_search.status_code == 200, post_search.text
263
+
264
+ test_app = app.StacApi(
265
+ settings=ApiSettings(enable_response_models=validate),
266
+ client=BadCoreClient(),
267
+ search_get_request_model=create_get_request_model([FieldsExtension()]),
268
+ search_post_request_model=create_post_request_model([FieldsExtension()]),
269
+ extensions=[],
270
+ )
271
+
272
+ with TestClient(test_app.app) as client:
273
+ get_search = client.get(
274
+ "/search",
275
+ params={"fields": "properties.datetime"},
276
+ )
277
+ post_search = client.post(
278
+ "/search",
279
+ json={
280
+ "collections": ["test"],
281
+ "fields": {
282
+ "include": ["properties.datetime"],
283
+ "exclude": [],
284
+ },
285
+ },
286
+ )
287
+ if validate:
288
+ assert get_search.status_code == 500, (
289
+ get_search.json()["code"] == "ResponseValidationError"
290
+ )
291
+ assert post_search.status_code == 500, (
292
+ post_search.json()["code"] == "ResponseValidationError"
293
+ )
294
+ else:
295
+ assert get_search.status_code == 200, get_search.text
296
+ assert post_search.status_code == 200, post_search.text
@@ -1,6 +1,8 @@
1
1
  from unittest import mock
2
2
 
3
3
  import pytest
4
+ from fastapi import Request
5
+ from fastapi.responses import JSONResponse
4
6
  from starlette.applications import Starlette
5
7
  from starlette.testclient import TestClient
6
8
 
@@ -166,3 +168,31 @@ def test_cors_middleware(test_client):
166
168
  resp = test_client.get("/_mgmt/ping", headers={"Origin": "http://netloc"})
167
169
  assert resp.status_code == 200
168
170
  assert resp.headers["access-control-allow-origin"] == "*"
171
+
172
+
173
+ def test_middleware_stack():
174
+ stac_api = StacApi(
175
+ settings=ApiSettings(), client=mock.create_autospec(BaseCoreClient)
176
+ )
177
+
178
+ def exception_handler(request: Request, exc: Exception) -> JSONResponse:
179
+ return JSONResponse(
180
+ status_code=400,
181
+ content={"customerrordetail": "yoo", "body": "yo"},
182
+ )
183
+
184
+ class CustomException(Exception):
185
+ "Custom Exception"
186
+
187
+ pass
188
+
189
+ stac_api.app.add_exception_handler(CustomException, exception_handler)
190
+
191
+ @stac_api.app.get("/error")
192
+ def error_endpoint():
193
+ raise CustomException("got you!")
194
+
195
+ with TestClient(stac_api.app) as client:
196
+ resp = client.get("/error")
197
+ assert resp.status_code == 400
198
+ assert resp.json()["customerrordetail"] == "yoo"
@@ -1,2 +0,0 @@
1
- """Library version."""
2
- __version__ = "3.0.0a3"