stac-fastapi.types 3.0.0b2__tar.gz → 3.0.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.
Files changed (27) hide show
  1. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/PKG-INFO +2 -2
  2. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/setup.py +1 -1
  3. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/core.py +0 -17
  4. stac_fastapi_types-3.0.1/stac_fastapi/types/search.py +190 -0
  5. stac_fastapi_types-3.0.1/stac_fastapi/types/version.py +3 -0
  6. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi.types.egg-info/PKG-INFO +2 -2
  7. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi.types.egg-info/requires.txt +1 -1
  8. stac_fastapi_types-3.0.1/tests/test_limit.py +55 -0
  9. stac_fastapi_types-3.0.0b2/stac_fastapi/types/search.py +0 -74
  10. stac_fastapi_types-3.0.0b2/stac_fastapi/types/version.py +0 -2
  11. stac_fastapi_types-3.0.0b2/tests/test_limit.py +0 -22
  12. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/README.md +0 -0
  13. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/setup.cfg +0 -0
  14. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/__init__.py +0 -0
  15. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/config.py +0 -0
  16. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/conformance.py +0 -0
  17. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/errors.py +0 -0
  18. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/extension.py +0 -0
  19. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/links.py +0 -0
  20. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/requests.py +0 -0
  21. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/rfc3339.py +0 -0
  22. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi/types/stac.py +0 -0
  23. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi.types.egg-info/SOURCES.txt +0 -0
  24. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi.types.egg-info/dependency_links.txt +0 -0
  25. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi.types.egg-info/not-zip-safe +0 -0
  26. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/stac_fastapi.types.egg-info/top_level.txt +0 -0
  27. {stac_fastapi_types-3.0.0b2 → stac_fastapi_types-3.0.1}/tests/test_rfc3339.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.types
3
- Version: 3.0.0b2
3
+ Version: 3.0.1
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
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: License :: OSI Approved :: MIT License
19
19
  Requires-Python: >=3.8
20
20
  Description-Content-Type: text/markdown
21
- Requires-Dist: fastapi-slim>=0.111.0
21
+ Requires-Dist: fastapi>=0.109.0
22
22
  Requires-Dist: attrs>=23.2.0
23
23
  Requires-Dist: pydantic-settings>=2
24
24
  Requires-Dist: stac_pydantic~=3.1
@@ -6,7 +6,7 @@ with open("README.md") as f:
6
6
  desc = f.read()
7
7
 
8
8
  install_requires = [
9
- "fastapi-slim>=0.111.0",
9
+ "fastapi>=0.109.0",
10
10
  "attrs>=23.2.0",
11
11
  "pydantic-settings>=2",
12
12
  "stac_pydantic~=3.1",
@@ -1,8 +1,6 @@
1
1
  """Base clients."""
2
2
 
3
3
  import abc
4
- import importlib
5
- import warnings
6
4
  from typing import Any, Dict, List, Optional, Union
7
5
  from urllib.parse import urljoin
8
6
 
@@ -784,18 +782,3 @@ class AsyncBaseCoreClient(LandingPageMixin, abc.ABC):
784
782
  An ItemCollection.
785
783
  """
786
784
  ...
787
-
788
-
789
- # TODO: remove for 3.0.0 final release
790
- def __getattr__(name: str) -> Any:
791
- if name in ["AsyncBaseFiltersClient", "BaseFiltersClient"]:
792
- warnings.warn(
793
- f"""importing {name} from `stac_fastapi.types.core` is deprecated,
794
- please import it from `stac_fastapi.extensions.core.filter.client`.""",
795
- DeprecationWarning,
796
- stacklevel=2,
797
- )
798
- clients = importlib.import_module("stac_fastapi.extensions.core.filter.client")
799
- return getattr(clients, name)
800
-
801
- raise AttributeError(f"module {__name__} has no attribute {name}")
@@ -0,0 +1,190 @@
1
+ """stac_fastapi.types.search module.
2
+
3
+ """
4
+
5
+ from typing import Dict, List, Optional, Union
6
+
7
+ import attr
8
+ from fastapi import Query
9
+ from pydantic import Field, PositiveInt
10
+ from pydantic.functional_validators import AfterValidator
11
+ from stac_pydantic.api import Search
12
+ from stac_pydantic.shared import BBox
13
+ from typing_extensions import Annotated
14
+
15
+ from stac_fastapi.types.rfc3339 import DateTimeType, str_to_interval
16
+
17
+
18
+ def crop(v: PositiveInt) -> PositiveInt:
19
+ """Crop value to 10,000."""
20
+ limit = 10_000
21
+ if v > limit:
22
+ v = limit
23
+ return v
24
+
25
+
26
+ def str2list(x: str) -> Optional[List[str]]:
27
+ """Convert string to list base on , delimiter."""
28
+ if x:
29
+ return x.split(",")
30
+
31
+ return None
32
+
33
+
34
+ def str2bbox(x: str) -> Optional[BBox]:
35
+ """Convert string to BBox based on , delimiter."""
36
+ if x:
37
+ t = tuple(float(v) for v in str2list(x))
38
+ assert len(t) == 4
39
+ return t
40
+
41
+ return None
42
+
43
+
44
+ def _collection_converter(
45
+ val: Annotated[
46
+ Optional[str],
47
+ Query(
48
+ description="Array of collection Ids to search for items.",
49
+ json_schema_extra={
50
+ "example": "collection1,collection2",
51
+ },
52
+ ),
53
+ ] = None,
54
+ ) -> Optional[List[str]]:
55
+ return str2list(val)
56
+
57
+
58
+ def _ids_converter(
59
+ val: Annotated[
60
+ Optional[str],
61
+ Query(
62
+ description="Array of Item ids to return.",
63
+ json_schema_extra={
64
+ "example": "item1,item2",
65
+ },
66
+ ),
67
+ ] = None,
68
+ ) -> Optional[List[str]]:
69
+ return str2list(val)
70
+
71
+
72
+ def _bbox_converter(
73
+ val: Annotated[
74
+ Optional[str],
75
+ Query(
76
+ description="Only return items intersecting this bounding box. Mutually exclusive with **intersects**.", # noqa: E501
77
+ json_schema_extra={
78
+ "example": "-175.05,-85.05,175.05,85.05",
79
+ },
80
+ ),
81
+ ] = None,
82
+ ) -> Optional[BBox]:
83
+ return str2bbox(val)
84
+
85
+
86
+ def _datetime_converter(
87
+ val: Annotated[
88
+ Optional[str],
89
+ Query(
90
+ description="""Only return items that have a temporal property that intersects this value.\n
91
+ Either a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots.""", # noqa: E501
92
+ openapi_examples={
93
+ "datetime": {"value": "2018-02-12T23:20:50Z"},
94
+ "closed-interval": {"value": "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z"},
95
+ "open-interval-from": {"value": "2018-02-12T00:00:00Z/.."},
96
+ "open-interval-to": {"value": "../2018-03-18T12:31:12Z"},
97
+ },
98
+ ),
99
+ ] = None,
100
+ ):
101
+ return str_to_interval(val)
102
+
103
+
104
+ # Be careful: https://github.com/samuelcolvin/pydantic/issues/1423#issuecomment-642797287
105
+ NumType = Union[float, int]
106
+ Limit = Annotated[PositiveInt, AfterValidator(crop)]
107
+
108
+
109
+ @attr.s
110
+ class APIRequest:
111
+ """Generic API Request base class."""
112
+
113
+ def kwargs(self) -> Dict:
114
+ """Transform api request params into format which matches the signature of the
115
+ endpoint."""
116
+ return self.__dict__
117
+
118
+
119
+ @attr.s
120
+ class BaseSearchGetRequest(APIRequest):
121
+ """Base arguments for GET Request."""
122
+
123
+ collections: Optional[List[str]] = attr.ib(
124
+ default=None, converter=_collection_converter
125
+ )
126
+ ids: Optional[List[str]] = attr.ib(default=None, converter=_ids_converter)
127
+ bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter)
128
+ intersects: Annotated[
129
+ Optional[str],
130
+ Query(
131
+ description="""Only return items intersecting this GeoJSON Geometry. Mutually exclusive with **bbox**. \n
132
+ *Remember to URL encode the GeoJSON geometry when using GET request*.""", # noqa: E501
133
+ openapi_examples={
134
+ "madrid": {
135
+ "value": {
136
+ "type": "Feature",
137
+ "properties": {},
138
+ "geometry": {
139
+ "coordinates": [
140
+ [
141
+ [-3.8549260500072933, 40.54923557897152],
142
+ [-3.8549260500072933, 40.29428000041938],
143
+ [-3.516597069715033, 40.29428000041938],
144
+ [-3.516597069715033, 40.54923557897152],
145
+ [-3.8549260500072933, 40.54923557897152],
146
+ ]
147
+ ],
148
+ "type": "Polygon",
149
+ },
150
+ },
151
+ },
152
+ "new-york": {
153
+ "value": {
154
+ "type": "Feature",
155
+ "properties": {},
156
+ "geometry": {
157
+ "coordinates": [
158
+ [
159
+ [-74.50117532354284, 41.128266394414055],
160
+ [-74.50117532354284, 40.35633909727355],
161
+ [-73.46713183168603, 40.35633909727355],
162
+ [-73.46713183168603, 41.128266394414055],
163
+ [-74.50117532354284, 41.128266394414055],
164
+ ]
165
+ ],
166
+ "type": "Polygon",
167
+ },
168
+ },
169
+ },
170
+ },
171
+ ),
172
+ ] = attr.ib(default=None)
173
+ datetime: Optional[DateTimeType] = attr.ib(
174
+ default=None, converter=_datetime_converter
175
+ )
176
+ limit: Annotated[
177
+ Optional[Limit],
178
+ Query(
179
+ description="Limits the number of results that are included in each page of the response (capped to 10_000)." # noqa: E501
180
+ ),
181
+ ] = attr.ib(default=10)
182
+
183
+
184
+ class BaseSearchPostRequest(Search):
185
+ """Base arguments for POST Request."""
186
+
187
+ limit: Optional[Limit] = Field(
188
+ 10,
189
+ description="Limits the number of results that are included in each page of the response (capped to 10_000).", # noqa: E501
190
+ )
@@ -0,0 +1,3 @@
1
+ """Library version."""
2
+
3
+ __version__ = "3.0.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stac-fastapi.types
3
- Version: 3.0.0b2
3
+ Version: 3.0.1
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
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: License :: OSI Approved :: MIT License
19
19
  Requires-Python: >=3.8
20
20
  Description-Content-Type: text/markdown
21
- Requires-Dist: fastapi-slim>=0.111.0
21
+ Requires-Dist: fastapi>=0.109.0
22
22
  Requires-Dist: attrs>=23.2.0
23
23
  Requires-Dist: pydantic-settings>=2
24
24
  Requires-Dist: stac_pydantic~=3.1
@@ -1,4 +1,4 @@
1
- fastapi-slim>=0.111.0
1
+ fastapi>=0.109.0
2
2
  attrs>=23.2.0
3
3
  pydantic-settings>=2
4
4
  stac_pydantic~=3.1
@@ -0,0 +1,55 @@
1
+ import pytest
2
+ from fastapi import Depends, FastAPI
3
+ from fastapi.testclient import TestClient
4
+ from pydantic import ValidationError
5
+
6
+ from stac_fastapi.types.search import BaseSearchGetRequest, BaseSearchPostRequest
7
+
8
+
9
+ @pytest.mark.parametrize("value", [0, -1])
10
+ def test_limit_ge(value):
11
+ with pytest.raises(ValidationError):
12
+ BaseSearchPostRequest(limit=value)
13
+
14
+
15
+ @pytest.mark.parametrize("value", [1, 10_000])
16
+ def test_limit(value):
17
+ search = BaseSearchPostRequest(limit=value)
18
+ assert search.limit == value
19
+
20
+
21
+ @pytest.mark.parametrize("value", [10_001, 100_000, 1_000_000])
22
+ def test_limit_le(value):
23
+ search = BaseSearchPostRequest(limit=value)
24
+ assert search.limit == 10_000
25
+
26
+
27
+ def test_limit_get_request():
28
+ """test GET model."""
29
+
30
+ app = FastAPI()
31
+
32
+ @app.get("/test")
33
+ def route(model=Depends(BaseSearchGetRequest)):
34
+ return model
35
+
36
+ with TestClient(app) as client:
37
+ resp = client.get(
38
+ "/test",
39
+ params={
40
+ "limit": 10,
41
+ },
42
+ )
43
+ assert resp.status_code == 200
44
+ response_dict = resp.json()
45
+ assert response_dict["limit"] == 10
46
+
47
+ resp = client.get(
48
+ "/test",
49
+ params={
50
+ "limit": 100_000,
51
+ },
52
+ )
53
+ assert resp.status_code == 200
54
+ response_dict = resp.json()
55
+ assert response_dict["limit"] == 10_000
@@ -1,74 +0,0 @@
1
- """stac_fastapi.types.search module.
2
-
3
- """
4
-
5
- from typing import Dict, List, Optional, Union
6
-
7
- import attr
8
- from fastapi import Query
9
- from pydantic import PositiveInt
10
- from pydantic.functional_validators import AfterValidator
11
- from stac_pydantic.api import Search
12
- from stac_pydantic.shared import BBox
13
- from typing_extensions import Annotated
14
-
15
- from stac_fastapi.types.rfc3339 import DateTimeType, str_to_interval
16
-
17
-
18
- def crop(v: PositiveInt) -> PositiveInt:
19
- """Crop value to 10,000."""
20
- limit = 10_000
21
- if v > limit:
22
- v = limit
23
- return v
24
-
25
-
26
- def str2list(x: str) -> Optional[List]:
27
- """Convert string to list base on , delimiter."""
28
- if x:
29
- return x.split(",")
30
-
31
-
32
- def str2bbox(x: str) -> Optional[BBox]:
33
- """Convert string to BBox based on , delimiter."""
34
- if x:
35
- t = tuple(float(v) for v in str2list(x))
36
- assert len(t) == 4
37
- return t
38
-
39
-
40
- # Be careful: https://github.com/samuelcolvin/pydantic/issues/1423#issuecomment-642797287
41
- NumType = Union[float, int]
42
- Limit = Annotated[PositiveInt, AfterValidator(crop)]
43
-
44
-
45
- @attr.s
46
- class APIRequest:
47
- """Generic API Request base class."""
48
-
49
- def kwargs(self) -> Dict:
50
- """Transform api request params into format which matches the signature of the
51
- endpoint."""
52
- return self.__dict__
53
-
54
-
55
- @attr.s
56
- class BaseSearchGetRequest(APIRequest):
57
- """Base arguments for GET Request."""
58
-
59
- collections: Annotated[Optional[str], Query()] = attr.ib(
60
- default=None, converter=str2list
61
- )
62
- ids: Annotated[Optional[str], Query()] = attr.ib(default=None, converter=str2list)
63
- bbox: Annotated[Optional[BBox], Query()] = attr.ib(default=None, converter=str2bbox)
64
- intersects: Annotated[Optional[str], Query()] = attr.ib(default=None)
65
- datetime: Annotated[Optional[DateTimeType], Query()] = attr.ib(
66
- default=None, converter=str_to_interval
67
- )
68
- limit: Annotated[Optional[int], Query()] = attr.ib(default=10)
69
-
70
-
71
- class BaseSearchPostRequest(Search):
72
- """Base arguments for POST Request."""
73
-
74
- limit: Optional[Limit] = 10
@@ -1,2 +0,0 @@
1
- """Library version."""
2
- __version__ = "3.0.0b2"
@@ -1,22 +0,0 @@
1
- import pytest
2
- from pydantic import ValidationError
3
-
4
- from stac_fastapi.types.search import BaseSearchPostRequest
5
-
6
-
7
- @pytest.mark.parametrize("value", [0, -1])
8
- def test_limit_ge(value):
9
- with pytest.raises(ValidationError):
10
- BaseSearchPostRequest(limit=value)
11
-
12
-
13
- @pytest.mark.parametrize("value", [1, 10_000])
14
- def test_limit(value):
15
- search = BaseSearchPostRequest(limit=value)
16
- assert search.limit == value
17
-
18
-
19
- @pytest.mark.parametrize("value", [10_001, 100_000, 1_000_000])
20
- def test_limit_le(value):
21
- search = BaseSearchPostRequest(limit=value)
22
- assert search.limit == 10_000