stac-fastapi.extensions 3.0.1__tar.gz → 3.0.2__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 (51) hide show
  1. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/PKG-INFO +1 -1
  2. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/collection_search/collection_search.py +101 -1
  3. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/version.py +1 -1
  4. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi.extensions.egg-info/PKG-INFO +1 -1
  5. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/tests/test_collection_search.py +118 -1
  6. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/README.md +0 -0
  7. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/setup.cfg +0 -0
  8. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/setup.py +0 -0
  9. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/__init__.py +0 -0
  10. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/__init__.py +0 -0
  11. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/aggregation/__init__.py +0 -0
  12. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/aggregation/aggregation.py +0 -0
  13. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/aggregation/client.py +0 -0
  14. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/aggregation/request.py +0 -0
  15. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/aggregation/types.py +0 -0
  16. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/collection_search/__init__.py +0 -0
  17. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/collection_search/client.py +0 -0
  18. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/collection_search/request.py +0 -0
  19. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/fields/__init__.py +0 -0
  20. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/fields/fields.py +0 -0
  21. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/fields/request.py +0 -0
  22. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/filter/__init__.py +0 -0
  23. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/filter/client.py +0 -0
  24. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/filter/filter.py +0 -0
  25. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/filter/request.py +0 -0
  26. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/free_text/__init__.py +0 -0
  27. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/free_text/free_text.py +0 -0
  28. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/free_text/request.py +0 -0
  29. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/pagination/__init__.py +0 -0
  30. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/pagination/pagination.py +0 -0
  31. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/pagination/request.py +0 -0
  32. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/pagination/token_pagination.py +0 -0
  33. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/query/__init__.py +0 -0
  34. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/query/query.py +0 -0
  35. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/query/request.py +0 -0
  36. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/sort/__init__.py +0 -0
  37. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/sort/request.py +0 -0
  38. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/sort/sort.py +0 -0
  39. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/core/transaction.py +0 -0
  40. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/third_party/__init__.py +0 -0
  41. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi/extensions/third_party/bulk_transactions.py +0 -0
  42. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi.extensions.egg-info/SOURCES.txt +0 -0
  43. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi.extensions.egg-info/dependency_links.txt +0 -0
  44. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi.extensions.egg-info/not-zip-safe +0 -0
  45. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi.extensions.egg-info/requires.txt +0 -0
  46. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/stac_fastapi.extensions.egg-info/top_level.txt +0 -0
  47. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/tests/test_aggregation.py +0 -0
  48. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/tests/test_filter.py +0 -0
  49. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/tests/test_free_text.py +0 -0
  50. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/tests/test_query.py +0 -0
  51. {stac_fastapi_extensions-3.0.1 → stac_fastapi_extensions-3.0.2}/tests/test_transaction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.extensions
3
- Version: 3.0.1
3
+ Version: 3.0.2
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
@@ -1,5 +1,6 @@
1
1
  """Collection-Search extension."""
2
2
 
3
+ import warnings
3
4
  from enum import Enum
4
5
  from typing import List, Optional, Union
5
6
 
@@ -8,7 +9,7 @@ from fastapi import APIRouter, FastAPI
8
9
  from stac_pydantic.api.collections import Collections
9
10
  from stac_pydantic.shared import MimeTypes
10
11
 
11
- from stac_fastapi.api.models import GeoJSONResponse
12
+ from stac_fastapi.api.models import GeoJSONResponse, create_request_model
12
13
  from stac_fastapi.api.routes import create_async_endpoint
13
14
  from stac_fastapi.types.config import ApiSettings
14
15
  from stac_fastapi.types.extension import ApiExtension
@@ -71,6 +72,48 @@ class CollectionSearchExtension(ApiExtension):
71
72
  """
72
73
  pass
73
74
 
75
+ @classmethod
76
+ def from_extensions(
77
+ cls,
78
+ extensions: List[ApiExtension],
79
+ schema_href: Optional[str] = None,
80
+ ) -> "CollectionSearchExtension":
81
+ """Create CollectionSearchExtension object from extensions."""
82
+ supported_extensions = {
83
+ "FreeTextExtension": ConformanceClasses.FREETEXT,
84
+ "FreeTextAdvancedExtension": ConformanceClasses.FREETEXT,
85
+ "QueryExtension": ConformanceClasses.QUERY,
86
+ "SortExtension": ConformanceClasses.SORT,
87
+ "FieldsExtension": ConformanceClasses.FIELDS,
88
+ "FilterExtension": ConformanceClasses.FILTER,
89
+ }
90
+ conformance_classes = [
91
+ ConformanceClasses.COLLECTIONSEARCH,
92
+ ConformanceClasses.BASIS,
93
+ ]
94
+ for ext in extensions:
95
+ conf = supported_extensions.get(ext.__class__.__name__, None)
96
+ if not conf:
97
+ warnings.warn(
98
+ f"Conformance class for `{ext.__class__.__name__}` extension not found.", # noqa: E501
99
+ UserWarning,
100
+ )
101
+ else:
102
+ conformance_classes.append(conf)
103
+
104
+ get_request_model = create_request_model(
105
+ model_name="CollectionsGetRequest",
106
+ base_model=BaseCollectionSearchGetRequest,
107
+ extensions=extensions,
108
+ request_type="GET",
109
+ )
110
+
111
+ return cls(
112
+ GET=get_request_model,
113
+ conformance_classes=conformance_classes,
114
+ schema_href=schema_href,
115
+ )
116
+
74
117
 
75
118
  @attr.s
76
119
  class CollectionSearchPostExtension(CollectionSearchExtension):
@@ -132,3 +175,60 @@ class CollectionSearchPostExtension(CollectionSearchExtension):
132
175
  endpoint=create_async_endpoint(self.client.post_all_collections, self.POST),
133
176
  )
134
177
  app.include_router(self.router)
178
+
179
+ @classmethod
180
+ def from_extensions(
181
+ cls,
182
+ extensions: List[ApiExtension],
183
+ *,
184
+ client: Union[AsyncBaseCollectionSearchClient, BaseCollectionSearchClient],
185
+ settings: ApiSettings,
186
+ schema_href: Optional[str] = None,
187
+ router: Optional[APIRouter] = None,
188
+ ) -> "CollectionSearchPostExtension":
189
+ """Create CollectionSearchPostExtension object from extensions."""
190
+ supported_extensions = {
191
+ "FreeTextExtension": ConformanceClasses.FREETEXT,
192
+ "FreeTextAdvancedExtension": ConformanceClasses.FREETEXT,
193
+ "QueryExtension": ConformanceClasses.QUERY,
194
+ "SortExtension": ConformanceClasses.SORT,
195
+ "FieldsExtension": ConformanceClasses.FIELDS,
196
+ "FilterExtension": ConformanceClasses.FILTER,
197
+ }
198
+ conformance_classes = [
199
+ ConformanceClasses.COLLECTIONSEARCH,
200
+ ConformanceClasses.BASIS,
201
+ ]
202
+ for ext in extensions:
203
+ conf = supported_extensions.get(ext.__class__.__name__, None)
204
+ if not conf:
205
+ warnings.warn(
206
+ f"Conformance class for `{ext.__class__.__name__}` extension not found.", # noqa: E501
207
+ UserWarning,
208
+ )
209
+ else:
210
+ conformance_classes.append(conf)
211
+
212
+ get_request_model = create_request_model(
213
+ model_name="CollectionsGetRequest",
214
+ base_model=BaseCollectionSearchGetRequest,
215
+ extensions=extensions,
216
+ request_type="GET",
217
+ )
218
+
219
+ post_request_model = create_request_model(
220
+ model_name="CollectionsPostRequest",
221
+ base_model=BaseCollectionSearchPostRequest,
222
+ extensions=extensions,
223
+ request_type="POST",
224
+ )
225
+
226
+ return cls(
227
+ client=client,
228
+ settings=settings,
229
+ GET=get_request_model,
230
+ POST=post_request_model,
231
+ conformance_classes=conformance_classes,
232
+ router=router or APIRouter(),
233
+ schema_href=schema_href,
234
+ )
@@ -1,3 +1,3 @@
1
1
  """Library version."""
2
2
 
3
- __version__ = "3.0.1"
3
+ __version__ = "3.0.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.extensions
3
- Version: 3.0.1
3
+ Version: 3.0.2
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
@@ -2,13 +2,21 @@ import json
2
2
  from urllib.parse import quote_plus
3
3
 
4
4
  import attr
5
+ import pytest
5
6
  from starlette.testclient import TestClient
6
7
 
7
8
  from stac_fastapi.api.app import StacApi
8
9
  from stac_fastapi.api.models import create_request_model
9
10
  from stac_fastapi.extensions.core import (
11
+ AggregationExtension,
10
12
  CollectionSearchExtension,
11
13
  CollectionSearchPostExtension,
14
+ FieldsExtension,
15
+ FilterExtension,
16
+ FreeTextAdvancedExtension,
17
+ FreeTextExtension,
18
+ QueryExtension,
19
+ SortExtension,
12
20
  )
13
21
  from stac_fastapi.extensions.core.collection_search import ConformanceClasses
14
22
  from stac_fastapi.extensions.core.collection_search.client import (
@@ -302,8 +310,8 @@ def test_collection_search_extension_post_models():
302
310
  client=DummyCoreClient(),
303
311
  extensions=[
304
312
  CollectionSearchPostExtension(
305
- settings=settings,
306
313
  client=DummyPostClient(),
314
+ settings=settings,
307
315
  GET=get_request_model,
308
316
  POST=post_request_model,
309
317
  conformance_classes=[
@@ -392,3 +400,112 @@ def test_collection_search_extension_post_models():
392
400
  assert response_dict["query"]
393
401
  assert response_dict["sortby"]
394
402
  assert response_dict["fields"]
403
+
404
+
405
+ @pytest.mark.parametrize(
406
+ "extensions",
407
+ [
408
+ # with FreeTextExtension
409
+ [
410
+ FieldsExtension(),
411
+ FilterExtension(),
412
+ FreeTextExtension(),
413
+ QueryExtension(),
414
+ SortExtension(),
415
+ ],
416
+ # with FreeTextAdvancedExtension
417
+ [
418
+ FieldsExtension(),
419
+ FilterExtension(),
420
+ FreeTextAdvancedExtension(),
421
+ QueryExtension(),
422
+ SortExtension(),
423
+ ],
424
+ ],
425
+ )
426
+ def test_from_extensions_methods(extensions):
427
+ """
428
+ Make sure `from_extensions` create the correct
429
+ models and adds desired conformances classes.
430
+ """
431
+ ext = CollectionSearchExtension.from_extensions(
432
+ extensions,
433
+ )
434
+ collection_search = ext.GET()
435
+ assert collection_search.__class__.__name__ == "CollectionsGetRequest"
436
+ assert hasattr(collection_search, "bbox")
437
+ assert hasattr(collection_search, "datetime")
438
+ assert hasattr(collection_search, "limit")
439
+ assert hasattr(collection_search, "fields")
440
+ assert hasattr(collection_search, "q")
441
+ assert hasattr(collection_search, "sortby")
442
+ assert hasattr(collection_search, "filter")
443
+ assert ext.conformance_classes == [
444
+ ConformanceClasses.COLLECTIONSEARCH,
445
+ ConformanceClasses.BASIS,
446
+ ConformanceClasses.FIELDS,
447
+ ConformanceClasses.FILTER,
448
+ ConformanceClasses.FREETEXT,
449
+ ConformanceClasses.QUERY,
450
+ ConformanceClasses.SORT,
451
+ ]
452
+
453
+ ext = CollectionSearchPostExtension.from_extensions(
454
+ extensions,
455
+ client=DummyPostClient(),
456
+ settings=ApiSettings(),
457
+ )
458
+ collection_search = ext.POST()
459
+ assert collection_search.__class__.__name__ == "CollectionsPostRequest"
460
+ assert hasattr(collection_search, "bbox")
461
+ assert hasattr(collection_search, "datetime")
462
+ assert hasattr(collection_search, "limit")
463
+ assert hasattr(collection_search, "fields")
464
+ assert hasattr(collection_search, "q")
465
+ assert hasattr(collection_search, "sortby")
466
+ assert hasattr(collection_search, "filter")
467
+ assert ext.conformance_classes == [
468
+ ConformanceClasses.COLLECTIONSEARCH,
469
+ ConformanceClasses.BASIS,
470
+ ConformanceClasses.FIELDS,
471
+ ConformanceClasses.FILTER,
472
+ ConformanceClasses.FREETEXT,
473
+ ConformanceClasses.QUERY,
474
+ ConformanceClasses.SORT,
475
+ ]
476
+
477
+
478
+ def test_from_extensions_methods_invalid():
479
+ """Should raise warnings for invalid extensions."""
480
+ extensions = [
481
+ AggregationExtension(),
482
+ ]
483
+ with pytest.warns((UserWarning)):
484
+ ext = CollectionSearchExtension.from_extensions(
485
+ extensions,
486
+ )
487
+ collection_search = ext.GET()
488
+ assert collection_search.__class__.__name__ == "CollectionsGetRequest"
489
+ assert hasattr(collection_search, "bbox")
490
+ assert hasattr(collection_search, "datetime")
491
+ assert hasattr(collection_search, "limit")
492
+ assert ext.conformance_classes == [
493
+ ConformanceClasses.COLLECTIONSEARCH,
494
+ ConformanceClasses.BASIS,
495
+ ]
496
+
497
+ with pytest.warns((UserWarning)):
498
+ ext = CollectionSearchPostExtension.from_extensions(
499
+ extensions,
500
+ client=DummyPostClient(),
501
+ settings=ApiSettings(),
502
+ )
503
+ collection_search = ext.POST()
504
+ assert collection_search.__class__.__name__ == "CollectionsPostRequest"
505
+ assert hasattr(collection_search, "bbox")
506
+ assert hasattr(collection_search, "datetime")
507
+ assert hasattr(collection_search, "limit")
508
+ assert ext.conformance_classes == [
509
+ ConformanceClasses.COLLECTIONSEARCH,
510
+ ConformanceClasses.BASIS,
511
+ ]