stac-fastapi.extensions 3.0.2__tar.gz → 3.0.4__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 (54) hide show
  1. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/PKG-INFO +2 -1
  2. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/setup.py +1 -0
  3. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/__init__.py +6 -1
  4. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/filter/request.py +1 -1
  5. stac_fastapi_extensions-3.0.4/stac_fastapi/extensions/core/pagination/__init__.py +7 -0
  6. stac_fastapi_extensions-3.0.4/stac_fastapi/extensions/core/pagination/offset_pagination.py +38 -0
  7. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/pagination/request.py +13 -0
  8. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/version.py +1 -1
  9. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi.extensions.egg-info/PKG-INFO +2 -1
  10. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi.extensions.egg-info/SOURCES.txt +2 -0
  11. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/tests/test_filter.py +2 -2
  12. stac_fastapi_extensions-3.0.4/tests/test_pagination.py +132 -0
  13. stac_fastapi_extensions-3.0.2/stac_fastapi/extensions/core/pagination/__init__.py +0 -6
  14. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/README.md +0 -0
  15. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/setup.cfg +0 -0
  16. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/__init__.py +0 -0
  17. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/aggregation/__init__.py +0 -0
  18. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/aggregation/aggregation.py +0 -0
  19. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/aggregation/client.py +0 -0
  20. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/aggregation/request.py +0 -0
  21. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/aggregation/types.py +0 -0
  22. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/collection_search/__init__.py +0 -0
  23. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/collection_search/client.py +0 -0
  24. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/collection_search/collection_search.py +0 -0
  25. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/collection_search/request.py +0 -0
  26. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/fields/__init__.py +0 -0
  27. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/fields/fields.py +0 -0
  28. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/fields/request.py +0 -0
  29. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/filter/__init__.py +0 -0
  30. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/filter/client.py +0 -0
  31. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/filter/filter.py +0 -0
  32. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/free_text/__init__.py +0 -0
  33. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/free_text/free_text.py +0 -0
  34. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/free_text/request.py +0 -0
  35. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/pagination/pagination.py +0 -0
  36. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/pagination/token_pagination.py +0 -0
  37. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/query/__init__.py +0 -0
  38. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/query/query.py +0 -0
  39. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/query/request.py +0 -0
  40. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/sort/__init__.py +0 -0
  41. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/sort/request.py +0 -0
  42. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/sort/sort.py +0 -0
  43. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/core/transaction.py +0 -0
  44. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/third_party/__init__.py +0 -0
  45. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi/extensions/third_party/bulk_transactions.py +0 -0
  46. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi.extensions.egg-info/dependency_links.txt +0 -0
  47. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi.extensions.egg-info/not-zip-safe +0 -0
  48. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi.extensions.egg-info/requires.txt +0 -0
  49. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/stac_fastapi.extensions.egg-info/top_level.txt +0 -0
  50. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/tests/test_aggregation.py +0 -0
  51. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/tests/test_collection_search.py +0 -0
  52. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/tests/test_free_text.py +0 -0
  53. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/tests/test_query.py +0 -0
  54. {stac_fastapi_extensions-3.0.2 → stac_fastapi_extensions-3.0.4}/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.2
3
+ Version: 3.0.4
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
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
18
19
  Classifier: License :: OSI Approved :: MIT License
19
20
  Requires-Python: >=3.8
20
21
  Description-Content-Type: text/markdown
@@ -38,6 +38,7 @@ setup(
38
38
  "Programming Language :: Python :: 3.10",
39
39
  "Programming Language :: Python :: 3.11",
40
40
  "Programming Language :: Python :: 3.12",
41
+ "Programming Language :: Python :: 3.13",
41
42
  "License :: OSI Approved :: MIT License",
42
43
  ],
43
44
  keywords="STAC FastAPI COG",
@@ -5,7 +5,11 @@ from .collection_search import CollectionSearchExtension, CollectionSearchPostEx
5
5
  from .fields import FieldsExtension
6
6
  from .filter import FilterExtension
7
7
  from .free_text import FreeTextAdvancedExtension, FreeTextExtension
8
- from .pagination import PaginationExtension, TokenPaginationExtension
8
+ from .pagination import (
9
+ OffsetPaginationExtension,
10
+ PaginationExtension,
11
+ TokenPaginationExtension,
12
+ )
9
13
  from .query import QueryExtension
10
14
  from .sort import SortExtension
11
15
  from .transaction import TransactionExtension
@@ -16,6 +20,7 @@ __all__ = (
16
20
  "FilterExtension",
17
21
  "FreeTextExtension",
18
22
  "FreeTextAdvancedExtension",
23
+ "OffsetPaginationExtension",
19
24
  "PaginationExtension",
20
25
  "QueryExtension",
21
26
  "SortExtension",
@@ -70,7 +70,7 @@ class FilterExtensionPostRequest(BaseModel):
70
70
  default=None,
71
71
  description="The coordinate reference system (CRS) used by spatial literals in the 'filter' value. Default is `http://www.opengis.net/def/crs/OGC/1.3/CRS84`", # noqa: E501
72
72
  )
73
- filter_lang: Optional[FilterLang] = Field(
73
+ filter_lang: Optional[Literal["cql-json", "cql2-json"]] = Field(
74
74
  alias="filter-lang",
75
75
  default="cql2-json",
76
76
  description="The CQL filter encoding that the 'filter' value uses.",
@@ -0,0 +1,7 @@
1
+ """Pagination classes as extensions."""
2
+
3
+ from .offset_pagination import OffsetPaginationExtension
4
+ from .pagination import PaginationExtension
5
+ from .token_pagination import TokenPaginationExtension
6
+
7
+ __all__ = ["OffsetPaginationExtension", "PaginationExtension", "TokenPaginationExtension"]
@@ -0,0 +1,38 @@
1
+ """Pagination API extension."""
2
+
3
+ from typing import List, Optional
4
+
5
+ import attr
6
+ from fastapi import FastAPI
7
+
8
+ from stac_fastapi.types.extension import ApiExtension
9
+
10
+ from .request import GETOffsetPagination, POSTOffsetPagination
11
+
12
+
13
+ @attr.s
14
+ class OffsetPaginationExtension(ApiExtension):
15
+ """Offset Pagination.
16
+
17
+ Though not strictly an extension, the chosen pagination will modify the form of the
18
+ request object. By making pagination an extension class, we can use
19
+ create_request_model to dynamically add the correct pagination parameter to the
20
+ request model for OpenAPI generation.
21
+ """
22
+
23
+ GET = GETOffsetPagination
24
+ POST = POSTOffsetPagination
25
+
26
+ conformance_classes: List[str] = attr.ib(factory=list)
27
+ schema_href: Optional[str] = attr.ib(default=None)
28
+
29
+ def register(self, app: FastAPI) -> None:
30
+ """Register the extension with a FastAPI application.
31
+
32
+ Args:
33
+ app: target FastAPI application.
34
+
35
+ Returns:
36
+ None
37
+ """
38
+ pass
@@ -34,3 +34,16 @@ class POSTPagination(BaseModel):
34
34
  """Page based pagination for POST requests."""
35
35
 
36
36
  page: Optional[str] = None
37
+
38
+
39
+ @attr.s
40
+ class GETOffsetPagination(APIRequest):
41
+ """Offset pagination for GET requests."""
42
+
43
+ offset: Annotated[Optional[int], Query()] = attr.ib(default=None)
44
+
45
+
46
+ class POSTOffsetPagination(BaseModel):
47
+ """Offset pagination model for POST requests."""
48
+
49
+ offset: Optional[int] = None
@@ -1,3 +1,3 @@
1
1
  """Library version."""
2
2
 
3
- __version__ = "3.0.2"
3
+ __version__ = "3.0.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.extensions
3
- Version: 3.0.2
3
+ Version: 3.0.4
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
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
18
19
  Classifier: License :: OSI Approved :: MIT License
19
20
  Requires-Python: >=3.8
20
21
  Description-Content-Type: text/markdown
@@ -31,6 +31,7 @@ stac_fastapi/extensions/core/free_text/__init__.py
31
31
  stac_fastapi/extensions/core/free_text/free_text.py
32
32
  stac_fastapi/extensions/core/free_text/request.py
33
33
  stac_fastapi/extensions/core/pagination/__init__.py
34
+ stac_fastapi/extensions/core/pagination/offset_pagination.py
34
35
  stac_fastapi/extensions/core/pagination/pagination.py
35
36
  stac_fastapi/extensions/core/pagination/request.py
36
37
  stac_fastapi/extensions/core/pagination/token_pagination.py
@@ -46,5 +47,6 @@ tests/test_aggregation.py
46
47
  tests/test_collection_search.py
47
48
  tests/test_filter.py
48
49
  tests/test_free_text.py
50
+ tests/test_pagination.py
49
51
  tests/test_query.py
50
52
  tests/test_transaction.py
@@ -62,12 +62,12 @@ def test_search_filter_post_filter_lang_default(client: TestClient):
62
62
 
63
63
  def test_search_filter_post_filter_lang_non_default(client: TestClient):
64
64
  """Test search POST endpoint with filter ext."""
65
- filter_lang_value = "cql2-text"
65
+ filter_lang_value = "cql-json"
66
66
  response = client.post(
67
67
  "/search",
68
68
  json={
69
69
  "collections": ["test"],
70
- "filter": {"op": "=", "args": [{"property": "test_property"}, "test-value"]},
70
+ "filter": {"eq": [{"property": "test_property"}, "test-value"]},
71
71
  "filter-lang": filter_lang_value,
72
72
  },
73
73
  )
@@ -0,0 +1,132 @@
1
+ from typing import Iterator
2
+
3
+ import pytest
4
+ from starlette.testclient import TestClient
5
+
6
+ from stac_fastapi.api.app import StacApi
7
+ from stac_fastapi.api.models import (
8
+ EmptyRequest,
9
+ create_post_request_model,
10
+ create_request_model,
11
+ )
12
+ from stac_fastapi.extensions.core import (
13
+ OffsetPaginationExtension,
14
+ PaginationExtension,
15
+ TokenPaginationExtension,
16
+ )
17
+ from stac_fastapi.types.config import ApiSettings
18
+ from stac_fastapi.types.core import BaseCoreClient
19
+ from stac_fastapi.types.search import BaseSearchGetRequest
20
+
21
+
22
+ class DummyCoreClient(BaseCoreClient):
23
+ def all_collections(self, *args, **kwargs):
24
+ _ = kwargs.pop("request", None)
25
+ return args, kwargs
26
+
27
+ def get_collection(self, *args, **kwargs):
28
+ _ = kwargs.pop("request", None)
29
+ return args, kwargs
30
+
31
+ def get_item(self, *args, **kwargs):
32
+ _ = kwargs.pop("request", None)
33
+ return args, kwargs
34
+
35
+ def get_search(self, *args, **kwargs):
36
+ _ = kwargs.pop("request", None)
37
+ return args, kwargs
38
+
39
+ def post_search(self, *args, **kwargs):
40
+ _ = kwargs.pop("request", None)
41
+ return args[0].model_dump(), kwargs
42
+
43
+ def item_collection(self, *args, **kwargs):
44
+ _ = kwargs.pop("request", None)
45
+ return args, kwargs
46
+
47
+
48
+ collections_get_request_model = create_request_model(
49
+ model_name="CollectionsGetRequest",
50
+ base_model=EmptyRequest,
51
+ mixins=[
52
+ OffsetPaginationExtension().GET,
53
+ ],
54
+ request_type="GET",
55
+ )
56
+
57
+ items_get_request_model = create_request_model(
58
+ model_name="ItemsGetRequest",
59
+ base_model=EmptyRequest,
60
+ mixins=[
61
+ PaginationExtension().GET,
62
+ ],
63
+ request_type="GET",
64
+ )
65
+
66
+ search_get_request_model = create_request_model(
67
+ model_name="SearchGetRequest",
68
+ base_model=BaseSearchGetRequest,
69
+ mixins=[
70
+ TokenPaginationExtension().GET,
71
+ ],
72
+ request_type="GET",
73
+ )
74
+
75
+
76
+ @pytest.fixture
77
+ def client() -> Iterator[TestClient]:
78
+ settings = ApiSettings()
79
+
80
+ api = StacApi(
81
+ settings=settings,
82
+ client=DummyCoreClient(),
83
+ extensions=[],
84
+ collections_get_request_model=collections_get_request_model,
85
+ items_get_request_model=items_get_request_model,
86
+ search_get_request_model=search_get_request_model,
87
+ search_post_request_model=create_post_request_model([]),
88
+ )
89
+ with TestClient(api.app) as client:
90
+ yield client
91
+
92
+
93
+ def test_pagination_extension(client: TestClient):
94
+ """Test endpoints with pagination extensions."""
95
+ # OffsetPaginationExtension
96
+ response = client.get("/collections")
97
+ assert response.is_success, response.json()
98
+ arg, kwargs = response.json()
99
+ assert "offset" in kwargs
100
+ assert kwargs["offset"] is None
101
+
102
+ response = client.get("/collections", params={"offset": 1})
103
+ assert response.is_success, response.json()
104
+ arg, kwargs = response.json()
105
+ assert "offset" in kwargs
106
+ assert kwargs["offset"] == 1
107
+
108
+ # PaginationExtension
109
+ response = client.get("/collections/a_collection/items")
110
+ assert response.is_success, response.json()
111
+ arg, kwargs = response.json()
112
+ assert "page" in kwargs
113
+ assert kwargs["page"] is None
114
+
115
+ response = client.get("/collections/a_collection/items", params={"page": "1"})
116
+ assert response.is_success, response.json()
117
+ arg, kwargs = response.json()
118
+ assert "page" in kwargs
119
+ assert kwargs["page"] == "1"
120
+
121
+ # TokenPaginationExtension
122
+ response = client.get("/search")
123
+ assert response.is_success, response.json()
124
+ arg, kwargs = response.json()
125
+ assert "token" in kwargs
126
+ assert kwargs["token"] is None
127
+
128
+ response = client.get("/search", params={"token": "atoken"})
129
+ assert response.is_success, response.json()
130
+ arg, kwargs = response.json()
131
+ assert "token" in kwargs
132
+ assert kwargs["token"] == "atoken"
@@ -1,6 +0,0 @@
1
- """Pagination classes as extensions."""
2
-
3
- from .pagination import PaginationExtension
4
- from .token_pagination import TokenPaginationExtension
5
-
6
- __all__ = ["PaginationExtension", "TokenPaginationExtension"]