stac-fastapi.api 3.0.0b1__tar.gz → 3.0.0b3__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.0b1 → stac_fastapi_api-3.0.0b3}/PKG-INFO +1 -1
  2. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/config.py +2 -0
  3. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/models.py +24 -23
  4. stac_fastapi_api-3.0.0b3/stac_fastapi/api/version.py +2 -0
  5. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi.api.egg-info/PKG-INFO +1 -1
  6. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/tests/test_app.py +14 -13
  7. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/tests/test_models.py +17 -9
  8. stac_fastapi_api-3.0.0b1/stac_fastapi/api/version.py +0 -2
  9. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/README.md +0 -0
  10. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/setup.cfg +0 -0
  11. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/setup.py +0 -0
  12. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/__init__.py +0 -0
  13. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/app.py +0 -0
  14. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/errors.py +0 -0
  15. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/middleware.py +0 -0
  16. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/openapi.py +0 -0
  17. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi/api/routes.py +0 -0
  18. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi.api.egg-info/SOURCES.txt +0 -0
  19. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi.api.egg-info/dependency_links.txt +0 -0
  20. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi.api.egg-info/not-zip-safe +0 -0
  21. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi.api.egg-info/requires.txt +0 -0
  22. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/stac_fastapi.api.egg-info/top_level.txt +0 -0
  23. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/tests/test_api.py +0 -0
  24. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/tests/test_app_prefix.py +0 -0
  25. {stac_fastapi_api-3.0.0b1 → stac_fastapi_api-3.0.0b3}/tests/test_middleware.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.api
3
- Version: 3.0.0b1
3
+ Version: 3.0.0b3
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
@@ -19,6 +19,8 @@ class ApiExtensions(enum.Enum):
19
19
  sort = "sort"
20
20
  transaction = "transaction"
21
21
  aggregation = "aggregation"
22
+ collection_search = "collection-search"
23
+ free_text = "free-text"
22
24
 
23
25
 
24
26
  class AddOns(enum.Enum):
@@ -1,8 +1,8 @@
1
1
  """Api request/response models."""
2
2
 
3
- from dataclasses import dataclass, make_dataclass
4
3
  from typing import List, Optional, Type, Union
5
4
 
5
+ import attr
6
6
  from fastapi import Path, Query
7
7
  from pydantic import BaseModel, create_model
8
8
  from stac_pydantic.shared import BBox
@@ -14,8 +14,9 @@ from stac_fastapi.types.search import (
14
14
  APIRequest,
15
15
  BaseSearchGetRequest,
16
16
  BaseSearchPostRequest,
17
- str2bbox,
18
- str_to_interval,
17
+ Limit,
18
+ _bbox_converter,
19
+ _datetime_converter,
19
20
  )
20
21
 
21
22
  try:
@@ -43,11 +44,11 @@ def create_request_model(
43
44
 
44
45
  mixins = mixins or []
45
46
 
46
- models = extension_models + mixins + [base_model]
47
+ models = [base_model] + extension_models + mixins
47
48
 
48
49
  # Handle GET requests
49
50
  if all([issubclass(m, APIRequest) for m in models]):
50
- return make_dataclass(model_name, [], bases=tuple(models))
51
+ return attr.make_class(model_name, attrs={}, bases=tuple(models))
51
52
 
52
53
  # Handle POST requests
53
54
  elif all([issubclass(m, BaseModel) for m in models]):
@@ -86,43 +87,43 @@ def create_post_request_model(
86
87
  )
87
88
 
88
89
 
89
- @dataclass
90
+ @attr.s
90
91
  class CollectionUri(APIRequest):
91
92
  """Get or delete collection."""
92
93
 
93
- collection_id: Annotated[str, Path(description="Collection ID")]
94
+ collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
94
95
 
95
96
 
96
- @dataclass
97
+ @attr.s
97
98
  class ItemUri(APIRequest):
98
99
  """Get or delete item."""
99
100
 
100
- collection_id: Annotated[str, Path(description="Collection ID")]
101
- item_id: Annotated[str, Path(description="Item ID")]
101
+ collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
102
+ item_id: Annotated[str, Path(description="Item ID")] = attr.ib()
102
103
 
103
104
 
104
- @dataclass
105
+ @attr.s
105
106
  class EmptyRequest(APIRequest):
106
107
  """Empty request."""
107
108
 
108
109
  ...
109
110
 
110
111
 
111
- @dataclass
112
+ @attr.s
112
113
  class ItemCollectionUri(APIRequest):
113
114
  """Get item collection."""
114
115
 
115
- collection_id: Annotated[str, Path(description="Collection ID")]
116
- limit: Annotated[int, Query()] = 10
117
- bbox: Annotated[Optional[BBox], Query()] = None
118
- datetime: Annotated[Optional[DateTimeType], Query()] = None
119
-
120
- def __post_init__(self):
121
- """convert attributes."""
122
- if self.bbox:
123
- self.bbox = str2bbox(self.bbox) # type: ignore
124
- if self.datetime:
125
- self.datetime = str_to_interval(self.datetime) # type: ignore
116
+ collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
117
+ limit: Annotated[
118
+ Optional[Limit],
119
+ Query(
120
+ description="Limits the number of results that are included in each page of the response (capped to 10_000)." # noqa: E501
121
+ ),
122
+ ] = attr.ib(default=10)
123
+ bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter)
124
+ datetime: Optional[DateTimeType] = attr.ib(
125
+ default=None, converter=_datetime_converter
126
+ )
126
127
 
127
128
 
128
129
  class GeoJSONResponse(JSONResponse):
@@ -0,0 +1,2 @@
1
+ """Library version."""
2
+ __version__ = "3.0.0b3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.api
3
- Version: 3.0.0b1
3
+ Version: 3.0.0b3
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,12 +1,13 @@
1
- from dataclasses import dataclass
2
1
  from datetime import datetime
3
2
  from typing import List, Optional, Union
4
3
 
4
+ import attr
5
5
  import pytest
6
6
  from fastapi import Path, Query
7
7
  from fastapi.testclient import TestClient
8
8
  from pydantic import ValidationError
9
9
  from stac_pydantic import api
10
+ from typing_extensions import Annotated
10
11
 
11
12
  from stac_fastapi.api import app
12
13
  from stac_fastapi.api.models import (
@@ -328,25 +329,25 @@ def test_fields_extension(validate, TestCoreClient, item_dict):
328
329
  def test_request_model(AsyncTestCoreClient):
329
330
  """Test if request models are passed correctly."""
330
331
 
331
- @dataclass
332
+ @attr.s
332
333
  class CollectionsRequest(APIRequest):
333
- user: str = Query(...)
334
+ user: Annotated[str, Query(...)] = attr.ib()
334
335
 
335
- @dataclass
336
+ @attr.s
336
337
  class CollectionRequest(APIRequest):
337
- collection_id: str = Path(description="Collection ID")
338
- user: str = Query(...)
338
+ collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
339
+ user: Annotated[str, Query(...)] = attr.ib()
339
340
 
340
- @dataclass
341
+ @attr.s
341
342
  class ItemsRequest(APIRequest):
342
- collection_id: str = Path(description="Collection ID")
343
- user: str = Query(...)
343
+ collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
344
+ user: Annotated[str, Query(...)] = attr.ib()
344
345
 
345
- @dataclass
346
+ @attr.s
346
347
  class ItemRequest(APIRequest):
347
- collection_id: str = Path(description="Collection ID")
348
- item_id: str = Path(description="Item ID")
349
- user: str = Query(...)
348
+ collection_id: Annotated[str, Path(description="Collection ID")] = attr.ib()
349
+ item_id: Annotated[str, Path(description="Item ID")] = attr.ib()
350
+ user: Annotated[str, Query(...)] = attr.ib()
350
351
 
351
352
  test_app = app.StacApi(
352
353
  settings=ApiSettings(),
@@ -1,19 +1,20 @@
1
1
  import json
2
2
 
3
3
  import pytest
4
- from fastapi import Depends, FastAPI
4
+ from fastapi import Depends, FastAPI, HTTPException
5
5
  from fastapi.testclient import TestClient
6
6
  from pydantic import ValidationError
7
7
 
8
8
  from stac_fastapi.api.models import create_get_request_model, create_post_request_model
9
- from stac_fastapi.extensions.core.filter.filter import FilterExtension
10
- from stac_fastapi.extensions.core.sort.sort import SortExtension
9
+ from stac_fastapi.extensions.core import FieldsExtension, FilterExtension, SortExtension
11
10
  from stac_fastapi.types.search import BaseSearchGetRequest, BaseSearchPostRequest
12
11
 
13
12
 
14
13
  def test_create_get_request_model():
15
- extensions = [FilterExtension()]
16
- request_model = create_get_request_model(extensions, BaseSearchGetRequest)
14
+ request_model = create_get_request_model(
15
+ extensions=[FilterExtension(), FieldsExtension()],
16
+ base_model=BaseSearchGetRequest,
17
+ )
17
18
 
18
19
  model = request_model(
19
20
  collections="test1,test2",
@@ -35,6 +36,9 @@ def test_create_get_request_model():
35
36
  assert model.collections == ["test1", "test2"]
36
37
  assert model.filter_crs == "epsg:4326"
37
38
 
39
+ with pytest.raises(HTTPException):
40
+ request_model(datetime="yo")
41
+
38
42
  app = FastAPI()
39
43
 
40
44
  @app.get("/test")
@@ -62,8 +66,10 @@ def test_create_get_request_model():
62
66
  [(None, True), ({"test": "test"}, True), ("test==test", False), ([], False)],
63
67
  )
64
68
  def test_create_post_request_model(filter, passes):
65
- extensions = [FilterExtension()]
66
- request_model = create_post_request_model(extensions, BaseSearchPostRequest)
69
+ request_model = create_post_request_model(
70
+ extensions=[FilterExtension(), FieldsExtension()],
71
+ base_model=BaseSearchPostRequest,
72
+ )
67
73
 
68
74
  if not passes:
69
75
  with pytest.raises(ValidationError):
@@ -100,8 +106,10 @@ def test_create_post_request_model(filter, passes):
100
106
  ],
101
107
  )
102
108
  def test_create_post_request_model_nested_fields(sortby, passes):
103
- extensions = [SortExtension()]
104
- request_model = create_post_request_model(extensions, BaseSearchPostRequest)
109
+ request_model = create_post_request_model(
110
+ extensions=[SortExtension()],
111
+ base_model=BaseSearchPostRequest,
112
+ )
105
113
 
106
114
  if not passes:
107
115
  with pytest.raises(ValidationError):
@@ -1,2 +0,0 @@
1
- """Library version."""
2
- __version__ = "3.0.0b1"