stac-fastapi.extensions 6.3.0__tar.gz → 6.3.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 (45) hide show
  1. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/PKG-INFO +1 -1
  2. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/aggregation/aggregation.py +6 -7
  3. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/aggregation/client.py +11 -12
  4. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/aggregation/request.py +5 -6
  5. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/aggregation/types.py +9 -9
  6. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/bulk_transactions/bulk_transactions.py +10 -9
  7. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/collection_search/collection_search.py +21 -21
  8. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/collection_search/request.py +14 -17
  9. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/fields/fields.py +6 -7
  10. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/fields/request.py +8 -9
  11. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/filter/client.py +5 -5
  12. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/filter/filter.py +10 -12
  13. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/filter/request.py +7 -8
  14. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/free_text/free_text.py +10 -11
  15. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/free_text/request.py +7 -8
  16. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/pagination/offset_pagination.py +4 -6
  17. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/pagination/pagination.py +4 -6
  18. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/pagination/request.py +7 -8
  19. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/pagination/token_pagination.py +4 -6
  20. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/query/query.py +6 -7
  21. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/query/request.py +3 -4
  22. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/sort/request.py +5 -6
  23. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/sort/sort.py +6 -7
  24. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/transaction/client.py +22 -23
  25. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/transaction/request.py +28 -28
  26. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/transaction/transaction.py +16 -16
  27. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/version.py +1 -1
  28. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/.gitignore +0 -0
  29. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/README.md +0 -0
  30. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/pyproject.toml +0 -0
  31. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/__init__.py +0 -0
  32. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/aggregation/__init__.py +0 -0
  33. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/bulk_transactions/__init__.py +0 -0
  34. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/collection_search/__init__.py +0 -0
  35. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/collection_search/client.py +0 -0
  36. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/core/__init__.py +0 -0
  37. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/fields/__init__.py +0 -0
  38. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/filter/__init__.py +0 -0
  39. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/free_text/__init__.py +0 -0
  40. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/pagination/__init__.py +0 -0
  41. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/py.typed +0 -0
  42. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/query/__init__.py +0 -0
  43. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/sort/__init__.py +0 -0
  44. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/third_party/__init__.py +0 -0
  45. {stac_fastapi_extensions-6.3.0 → stac_fastapi_extensions-6.3.2}/stac_fastapi/extensions/transaction/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stac-fastapi-extensions
3
- Version: 6.3.0
3
+ Version: 6.3.2
4
4
  Summary: Extensions for stac-fastapi apis.
5
5
  Project-URL: Homepage, https://github.com/stac-utils/stac-fastapi
6
6
  Author-email: ArturoAI <engineering@arturo.ai>
@@ -1,7 +1,6 @@
1
1
  """Aggregation Extension."""
2
2
 
3
- from enum import Enum
4
- from typing import List, Type, Union
3
+ from enum import StrEnum
5
4
 
6
5
  import attr
7
6
  from fastapi import APIRouter, FastAPI
@@ -16,7 +15,7 @@ from .client import AsyncBaseAggregationClient, BaseAggregationClient
16
15
  from .request import AggregationExtensionGetRequest, AggregationExtensionPostRequest
17
16
 
18
17
 
19
- class AggregationConformanceClasses(str, Enum):
18
+ class AggregationConformanceClasses(StrEnum):
20
19
  """Conformance classes for the Aggregation extension.
21
20
 
22
21
  See
@@ -53,14 +52,14 @@ class AggregationExtension(ApiExtension):
53
52
  conformance_classes: Conformance classes provided by the extension
54
53
  """
55
54
 
56
- GET: Type[APIRequest] = AggregationExtensionGetRequest
57
- POST: Type[BaseModel] = AggregationExtensionPostRequest
55
+ GET: type[APIRequest] = AggregationExtensionGetRequest
56
+ POST: type[BaseModel] = AggregationExtensionPostRequest
58
57
 
59
- client: Union[AsyncBaseAggregationClient, BaseAggregationClient] = attr.ib(
58
+ client: AsyncBaseAggregationClient | BaseAggregationClient = attr.ib(
60
59
  factory=BaseAggregationClient
61
60
  )
62
61
 
63
- conformance_classes: List[str] = attr.ib(
62
+ conformance_classes: list[str] = attr.ib(
64
63
  default=[AggregationConformanceClasses.AGGREGATION]
65
64
  )
66
65
  router: APIRouter = attr.ib(factory=APIRouter)
@@ -1,7 +1,6 @@
1
1
  """Aggregation extensions clients."""
2
2
 
3
3
  import abc
4
- from typing import List, Optional, Union
5
4
 
6
5
  import attr
7
6
  from geojson_pydantic.geometries import Geometry
@@ -21,7 +20,7 @@ class BaseAggregationClient(abc.ABC):
21
20
  # AGGREGATION_COLLECTION = AggregationCollection
22
21
 
23
22
  def get_aggregations(
24
- self, collection_id: Optional[str] = None, **kwargs
23
+ self, collection_id: str | None = None, **kwargs
25
24
  ) -> AggregationCollection:
26
25
  """Get the aggregations available for the given collection_id.
27
26
 
@@ -46,7 +45,7 @@ class BaseAggregationClient(abc.ABC):
46
45
  )
47
46
 
48
47
  def aggregate(
49
- self, collection_id: Optional[str] = None, **kwargs
48
+ self, collection_id: str | None = None, **kwargs
50
49
  ) -> AggregationCollection:
51
50
  """Return the aggregation buckets for a given search result"""
52
51
  return AggregationCollection(
@@ -76,7 +75,7 @@ class AsyncBaseAggregationClient(abc.ABC):
76
75
  # AGGREGATION_COLLECTION = AggregationCollection
77
76
 
78
77
  async def get_aggregations(
79
- self, collection_id: Optional[str] = None, **kwargs
78
+ self, collection_id: str | None = None, **kwargs
80
79
  ) -> AggregationCollection:
81
80
  """Get the aggregations available for the given collection_id.
82
81
 
@@ -102,14 +101,14 @@ class AsyncBaseAggregationClient(abc.ABC):
102
101
 
103
102
  async def aggregate(
104
103
  self,
105
- collection_id: Optional[str] = None,
106
- aggregations: Optional[Union[str, List[str]]] = None,
107
- collections: Optional[List[str]] = None,
108
- ids: Optional[List[str]] = None,
109
- bbox: Optional[BBox] = None,
110
- intersects: Optional[Geometry] = None,
111
- datetime: Optional[DateTimeType] = None,
112
- limit: Optional[int] = 10,
104
+ collection_id: str | None = None,
105
+ aggregations: str | list[str] | None = None,
106
+ collections: list[str] | None = None,
107
+ ids: list[str] | None = None,
108
+ bbox: BBox | None = None,
109
+ intersects: Geometry | None = None,
110
+ datetime: DateTimeType | None = None,
111
+ limit: int | None = 10,
113
112
  **kwargs,
114
113
  ) -> AggregationCollection:
115
114
  """Return the aggregation buckets for a given search result"""
@@ -1,11 +1,10 @@
1
1
  """Request model for the Aggregation extension."""
2
2
 
3
- from typing import List, Optional
3
+ from typing import Annotated
4
4
 
5
5
  import attr
6
6
  from fastapi import Query
7
7
  from pydantic import Field
8
- from typing_extensions import Annotated
9
8
 
10
9
  from stac_fastapi.types.search import (
11
10
  BaseSearchGetRequest,
@@ -16,10 +15,10 @@ from stac_fastapi.types.search import (
16
15
 
17
16
  def _agg_converter(
18
17
  val: Annotated[
19
- Optional[str],
18
+ str | None,
20
19
  Query(description="A list of aggregations to compute and return."),
21
20
  ] = None,
22
- ) -> Optional[List[str]]:
21
+ ) -> list[str] | None:
23
22
  return str2list(val)
24
23
 
25
24
 
@@ -27,13 +26,13 @@ def _agg_converter(
27
26
  class AggregationExtensionGetRequest(BaseSearchGetRequest):
28
27
  """Aggregation Extension GET request model."""
29
28
 
30
- aggregations: Optional[List[str]] = attr.ib(default=None, converter=_agg_converter)
29
+ aggregations: list[str] | None = attr.ib(default=None, converter=_agg_converter)
31
30
 
32
31
 
33
32
  class AggregationExtensionPostRequest(BaseSearchPostRequest):
34
33
  """Aggregation Extension POST request model."""
35
34
 
36
- aggregations: Optional[List[str]] = Field(
35
+ aggregations: list[str] | None = Field(
37
36
  default=None,
38
37
  description="A list of aggregations to compute and return.",
39
38
  )
@@ -1,8 +1,8 @@
1
1
  """Aggregation Extension types."""
2
2
 
3
- from typing import Any, Dict, List, Literal, Optional, Union
3
+ from typing import Any, Literal, NotRequired
4
4
 
5
- from typing_extensions import NotRequired, TypedDict
5
+ from typing_extensions import TypedDict
6
6
 
7
7
  from stac_fastapi.types.rfc3339 import DateTimeType
8
8
 
@@ -11,10 +11,10 @@ Bucket = TypedDict(
11
11
  {
12
12
  "key": str,
13
13
  "data_type": str,
14
- "frequency": NotRequired[Dict],
14
+ "frequency": NotRequired[dict],
15
15
  # we can't use the `class Bucket` notation because `from` is a reserved key
16
- "from": NotRequired[Union[int, float]],
17
- "to": NotRequired[Optional[Union[int, float]]],
16
+ "from": NotRequired[int | float],
17
+ "to": NotRequired[int | float | None],
18
18
  },
19
19
  )
20
20
 
@@ -24,14 +24,14 @@ class Aggregation(TypedDict):
24
24
 
25
25
  name: str
26
26
  data_type: str
27
- buckets: NotRequired[List[Bucket]]
27
+ buckets: NotRequired[list[Bucket]]
28
28
  overflow: NotRequired[int]
29
- value: NotRequired[Union[str, int, DateTimeType]]
29
+ value: NotRequired[str | int | DateTimeType]
30
30
 
31
31
 
32
32
  class AggregationCollection(TypedDict):
33
33
  """STAC Item Aggregation Collection."""
34
34
 
35
35
  type: Literal["AggregationCollection"]
36
- aggregations: List[Aggregation]
37
- links: List[Dict[str, Any]]
36
+ aggregations: list[Aggregation]
37
+ links: list[dict[str, Any]]
@@ -1,8 +1,9 @@
1
1
  """Bulk transactions extension."""
2
2
 
3
3
  import abc
4
- from enum import Enum
5
- from typing import Any, Dict, List, Optional, Sequence, Union
4
+ from collections.abc import Sequence
5
+ from enum import StrEnum
6
+ from typing import Any
6
7
 
7
8
  import attr
8
9
  from fastapi import APIRouter, FastAPI
@@ -14,7 +15,7 @@ from stac_fastapi.api.routes import create_async_endpoint
14
15
  from stac_fastapi.types.extension import ApiExtension
15
16
 
16
17
 
17
- class BulkTransactionMethod(str, Enum):
18
+ class BulkTransactionMethod(StrEnum):
18
19
  """Bulk Transaction Methods."""
19
20
 
20
21
  INSERT = "insert"
@@ -24,7 +25,7 @@ class BulkTransactionMethod(str, Enum):
24
25
  class Items(BaseModel):
25
26
  """A group of STAC Item objects, in the form of a dictionary from Item.id -> Item."""
26
27
 
27
- items: Dict[str, Any]
28
+ items: dict[str, Any]
28
29
  method: BulkTransactionMethod = BulkTransactionMethod.INSERT
29
30
 
30
31
  def __iter__(self):
@@ -49,7 +50,7 @@ class BaseBulkTransactionsClient(abc.ABC):
49
50
  def bulk_item_insert(
50
51
  self,
51
52
  items: Items,
52
- chunk_size: Optional[int] = None,
53
+ chunk_size: int | None = None,
53
54
  **kwargs,
54
55
  ) -> str:
55
56
  """Bulk creation of items.
@@ -111,10 +112,10 @@ class BulkTransactionExtension(ApiExtension):
111
112
  }
112
113
  """
113
114
 
114
- client: Union[AsyncBaseBulkTransactionsClient, BaseBulkTransactionsClient] = attr.ib()
115
- conformance_classes: List[str] = attr.ib(default=list())
116
- schema_href: Optional[str] = attr.ib(default=None)
117
- route_dependencies: Optional[Sequence[Depends]] = attr.ib(default=None)
115
+ client: AsyncBaseBulkTransactionsClient | BaseBulkTransactionsClient = attr.ib()
116
+ conformance_classes: list[str] = attr.ib(default=list())
117
+ schema_href: str | None = attr.ib(default=None)
118
+ route_dependencies: Sequence[Depends] | None = attr.ib(default=None)
118
119
 
119
120
  def register(self, app: FastAPI) -> None:
120
121
  """Register the extension with a FastAPI application.
@@ -1,7 +1,7 @@
1
1
  """Collection-Search extension."""
2
2
 
3
- from enum import Enum
4
- from typing import List, Optional, Type, Union, cast
3
+ from enum import StrEnum
4
+ from typing import cast
5
5
 
6
6
  import attr
7
7
  from fastapi import APIRouter, FastAPI
@@ -19,7 +19,7 @@ from .client import AsyncBaseCollectionSearchClient, BaseCollectionSearchClient
19
19
  from .request import BaseCollectionSearchGetRequest, BaseCollectionSearchPostRequest
20
20
 
21
21
 
22
- class CollectionSearchConformanceClasses(str, Enum):
22
+ class CollectionSearchConformanceClasses(StrEnum):
23
23
  """Conformance classes for the Collection-Search extension.
24
24
 
25
25
  See
@@ -49,16 +49,16 @@ class CollectionSearchExtension(ApiExtension):
49
49
  the extension
50
50
  """
51
51
 
52
- GET: Type[APIRequest] = attr.ib(default=BaseCollectionSearchGetRequest)
53
- POST: Optional[Type[BaseModel]] = attr.ib(init=False)
52
+ GET: type[APIRequest] = attr.ib(default=BaseCollectionSearchGetRequest)
53
+ POST: type[BaseModel] | None = attr.ib(init=False)
54
54
 
55
- conformance_classes: List[str] = attr.ib(
55
+ conformance_classes: list[str] = attr.ib(
56
56
  default=[
57
57
  CollectionSearchConformanceClasses.COLLECTIONSEARCH.value,
58
58
  CollectionSearchConformanceClasses.BASIS.value,
59
59
  ]
60
60
  )
61
- schema_href: Optional[str] = attr.ib(default=None)
61
+ schema_href: str | None = attr.ib(default=None)
62
62
 
63
63
  def register(self, app: FastAPI) -> None:
64
64
  """Register the extension with a FastAPI application.
@@ -74,9 +74,9 @@ class CollectionSearchExtension(ApiExtension):
74
74
  @classmethod
75
75
  def from_extensions(
76
76
  cls,
77
- extensions: List[ApiExtension],
77
+ extensions: list[ApiExtension],
78
78
  *,
79
- schema_href: Optional[str] = None,
79
+ schema_href: str | None = None,
80
80
  ) -> "CollectionSearchExtension":
81
81
  """Create CollectionSearchExtension object from extensions."""
82
82
 
@@ -88,7 +88,7 @@ class CollectionSearchExtension(ApiExtension):
88
88
  conformance_classes.extend(ext.conformance_classes)
89
89
 
90
90
  get_request_model = cast(
91
- Type[APIRequest],
91
+ type[APIRequest],
92
92
  create_request_model(
93
93
  model_name="CollectionsGetRequest",
94
94
  base_model=BaseCollectionSearchGetRequest,
@@ -121,19 +121,19 @@ class CollectionSearchPostExtension(CollectionSearchExtension):
121
121
  the extension
122
122
  """
123
123
 
124
- client: Union[AsyncBaseCollectionSearchClient, BaseCollectionSearchClient] = attr.ib()
124
+ client: AsyncBaseCollectionSearchClient | BaseCollectionSearchClient = attr.ib()
125
125
  settings: ApiSettings = attr.ib()
126
- conformance_classes: List[str] = attr.ib(
126
+ conformance_classes: list[str] = attr.ib(
127
127
  default=[
128
128
  CollectionSearchConformanceClasses.COLLECTIONSEARCH.value,
129
129
  CollectionSearchConformanceClasses.BASIS.value,
130
130
  ]
131
131
  )
132
- schema_href: Optional[str] = attr.ib(default=None)
132
+ schema_href: str | None = attr.ib(default=None)
133
133
  router: APIRouter = attr.ib(factory=APIRouter)
134
134
 
135
- GET: Type[APIRequest] = attr.ib(default=BaseCollectionSearchGetRequest)
136
- POST: Type[BaseModel] = attr.ib(default=BaseCollectionSearchPostRequest)
135
+ GET: type[APIRequest] = attr.ib(default=BaseCollectionSearchGetRequest)
136
+ POST: type[BaseModel] = attr.ib(default=BaseCollectionSearchPostRequest)
137
137
 
138
138
  def register(self, app: FastAPI) -> None:
139
139
  """Register the extension with a FastAPI application.
@@ -169,12 +169,12 @@ class CollectionSearchPostExtension(CollectionSearchExtension):
169
169
  @classmethod
170
170
  def from_extensions( # type: ignore [override]
171
171
  cls,
172
- extensions: List[ApiExtension],
172
+ extensions: list[ApiExtension],
173
173
  *,
174
- schema_href: Optional[str] = None,
175
- client: Union[AsyncBaseCollectionSearchClient, BaseCollectionSearchClient],
174
+ schema_href: str | None = None,
175
+ client: AsyncBaseCollectionSearchClient | BaseCollectionSearchClient,
176
176
  settings: ApiSettings,
177
- router: Optional[APIRouter] = None,
177
+ router: APIRouter | None = None,
178
178
  ) -> "CollectionSearchPostExtension":
179
179
  """Create CollectionSearchPostExtension object from extensions."""
180
180
  conformance_classes = [
@@ -185,7 +185,7 @@ class CollectionSearchPostExtension(CollectionSearchExtension):
185
185
  conformance_classes.extend(ext.conformance_classes)
186
186
 
187
187
  get_request_model = cast(
188
- Type[APIRequest],
188
+ type[APIRequest],
189
189
  create_request_model(
190
190
  model_name="CollectionsGetRequest",
191
191
  base_model=BaseCollectionSearchGetRequest,
@@ -195,7 +195,7 @@ class CollectionSearchPostExtension(CollectionSearchExtension):
195
195
  )
196
196
 
197
197
  post_request_model = cast(
198
- Type[BaseModel],
198
+ type[BaseModel],
199
199
  create_request_model(
200
200
  model_name="CollectionsPostRequest",
201
201
  base_model=BaseCollectionSearchPostRequest,
@@ -1,13 +1,12 @@
1
1
  """Request models for the Collection-Search extension."""
2
2
 
3
3
  from datetime import datetime as dt
4
- from typing import List, Optional, Tuple, cast
4
+ from typing import Annotated, cast
5
5
 
6
6
  import attr
7
7
  from fastapi import Query
8
8
  from pydantic import BaseModel, Field, PrivateAttr, ValidationInfo, field_validator
9
9
  from stac_pydantic.shared import BBox, SearchDatetime
10
- from typing_extensions import Annotated
11
10
 
12
11
  from stac_fastapi.types.search import (
13
12
  APIRequest,
@@ -23,10 +22,10 @@ from stac_fastapi.types.search import (
23
22
  class BaseCollectionSearchGetRequest(APIRequest, DatetimeMixin):
24
23
  """Basics additional Collection-Search parameters for the GET request."""
25
24
 
26
- bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter) # type: ignore
25
+ bbox: BBox | None = attr.ib(default=None, converter=_bbox_converter) # type: ignore
27
26
  datetime: DateTimeQueryType = attr.ib(default=None, validator=_validate_datetime)
28
27
  limit: Annotated[
29
- Optional[Limit],
28
+ Limit | None,
30
29
  Query(
31
30
  description="Limits the number of results that are included in each page of the response." # noqa: E501
32
31
  ),
@@ -36,7 +35,7 @@ class BaseCollectionSearchGetRequest(APIRequest, DatetimeMixin):
36
35
  class BaseCollectionSearchPostRequest(BaseModel):
37
36
  """Collection-Search POST model."""
38
37
 
39
- bbox: Optional[BBox] = Field(
38
+ bbox: BBox | None = Field(
40
39
  default=None,
41
40
  description="Only return items intersecting this bounding box. Mutually exclusive with **intersects**.", # noqa: E501
42
41
  json_schema_extra={
@@ -48,7 +47,7 @@ class BaseCollectionSearchPostRequest(BaseModel):
48
47
  ],
49
48
  },
50
49
  )
51
- datetime: Optional[str] = Field(
50
+ datetime: str | None = Field(
52
51
  default=None,
53
52
  description="""Only return items that have a temporal property that intersects this value.\n
54
53
  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
@@ -67,24 +66,24 @@ Either a date-time or an interval, open or closed. Date and time expressions adh
67
66
  ],
68
67
  },
69
68
  )
70
- limit: Optional[Limit] = Field(
69
+ limit: Limit | None = Field(
71
70
  10,
72
71
  description="Limits the number of results that are included in each page of the response (capped to 10_000).", # noqa: E501
73
72
  )
74
73
 
75
74
  # Private properties to store the parsed datetime values.
76
75
  # Not part of the model schema.
77
- _start_date: Optional[dt] = PrivateAttr(default=None)
78
- _end_date: Optional[dt] = PrivateAttr(default=None)
76
+ _start_date: dt | None = PrivateAttr(default=None)
77
+ _end_date: dt | None = PrivateAttr(default=None)
79
78
 
80
79
  # Properties to return the private values
81
80
  @property
82
- def start_date(self) -> Optional[dt]:
81
+ def start_date(self) -> dt | None:
83
82
  """start date."""
84
83
  return self._start_date
85
84
 
86
85
  @property
87
- def end_date(self) -> Optional[dt]:
86
+ def end_date(self) -> dt | None:
88
87
  """end date."""
89
88
  return self._end_date
90
89
 
@@ -95,10 +94,10 @@ Either a date-time or an interval, open or closed. Date and time expressions adh
95
94
  if v:
96
95
  # Validate order
97
96
  if len(v) == 4:
98
- xmin, ymin, xmax, ymax = cast(Tuple[int, int, int, int], v)
97
+ xmin, ymin, xmax, ymax = cast(tuple[int, int, int, int], v)
99
98
  else:
100
99
  xmin, ymin, min_elev, xmax, ymax, max_elev = cast(
101
- Tuple[int, int, int, int, int, int], v
100
+ tuple[int, int, int, int, int, int], v
102
101
  )
103
102
  if max_elev < min_elev:
104
103
  raise ValueError(
@@ -117,9 +116,7 @@ Either a date-time or an interval, open or closed. Date and time expressions adh
117
116
 
118
117
  @field_validator("datetime", mode="after")
119
118
  @classmethod
120
- def validate_datetime(
121
- cls, value: Optional[str], info: ValidationInfo
122
- ) -> Optional[str]:
119
+ def validate_datetime(cls, value: str | None, info: ValidationInfo) -> str | None:
123
120
  """validate datetime."""
124
121
  # Split on "/" and replace no value or ".." with None
125
122
  if value is None:
@@ -139,7 +136,7 @@ Either a date-time or an interval, open or closed. Date and time expressions adh
139
136
 
140
137
  # Cast because pylance gets confused by the type adapter and annotated type
141
138
  dates = cast(
142
- List[Optional[dt]],
139
+ list[dt | None],
143
140
  [
144
141
  # Use the type adapter to validate the datetime strings,
145
142
  # strict is necessary due to pydantic issues #8736 and #8762
@@ -1,7 +1,6 @@
1
1
  """Fields extension."""
2
2
 
3
- from enum import Enum
4
- from typing import List, Optional, Type
3
+ from enum import StrEnum
5
4
 
6
5
  import attr
7
6
  from fastapi import FastAPI
@@ -13,7 +12,7 @@ from stac_fastapi.types.search import APIRequest
13
12
  from .request import FieldsExtensionGetRequest, FieldsExtensionPostRequest
14
13
 
15
14
 
16
- class FieldsConformanceClasses(str, Enum):
15
+ class FieldsConformanceClasses(StrEnum):
17
16
  """Conformance classes for the Fields extension.
18
17
 
19
18
  See https://github.com/stac-api-extensions/fields
@@ -44,15 +43,15 @@ class FieldsExtension(ApiExtension):
44
43
  the extension
45
44
  """
46
45
 
47
- GET: Type[APIRequest] = FieldsExtensionGetRequest
48
- POST: Type[BaseModel] = FieldsExtensionPostRequest
46
+ GET: type[APIRequest] = FieldsExtensionGetRequest
47
+ POST: type[BaseModel] = FieldsExtensionPostRequest
49
48
 
50
- conformance_classes: List[str] = attr.ib(
49
+ conformance_classes: list[str] = attr.ib(
51
50
  factory=lambda: [
52
51
  FieldsConformanceClasses.SEARCH,
53
52
  ]
54
53
  )
55
- schema_href: Optional[str] = attr.ib(default=None)
54
+ schema_href: str | None = attr.ib(default=None)
56
55
 
57
56
  def register(self, app: FastAPI) -> None:
58
57
  """Register the extension with a FastAPI application.
@@ -1,11 +1,10 @@
1
1
  """Request models for the fields extension."""
2
2
 
3
- from typing import Dict, List, Optional, Set
3
+ from typing import Annotated
4
4
 
5
5
  import attr
6
6
  from fastapi import Query
7
7
  from pydantic import BaseModel, Field
8
- from typing_extensions import Annotated
9
8
 
10
9
  from stac_fastapi.types.search import APIRequest, str2list
11
10
 
@@ -18,11 +17,11 @@ class PostFieldsExtension(BaseModel):
18
17
  exclude: set of fields to exclude.
19
18
  """
20
19
 
21
- include: Optional[Set[str]] = set()
22
- exclude: Optional[Set[str]] = set()
20
+ include: set[str] | None = set()
21
+ exclude: set[str] | None = set()
23
22
 
24
23
  @staticmethod
25
- def _get_field_dict(fields: Optional[Set[str]]) -> Dict:
24
+ def _get_field_dict(fields: set[str] | None) -> dict:
26
25
  """Pydantic include/excludes notation.
27
26
 
28
27
  Internal method to create a dictionary for advanced include or exclude
@@ -46,7 +45,7 @@ class PostFieldsExtension(BaseModel):
46
45
 
47
46
  def _fields_converter(
48
47
  val: Annotated[
49
- Optional[str],
48
+ str | None,
50
49
  Query(
51
50
  description="Include or exclude fields from items body.",
52
51
  openapi_examples={
@@ -55,7 +54,7 @@ def _fields_converter(
55
54
  },
56
55
  ),
57
56
  ] = None,
58
- ) -> Optional[List[str]]:
57
+ ) -> list[str] | None:
59
58
  return str2list(val)
60
59
 
61
60
 
@@ -63,13 +62,13 @@ def _fields_converter(
63
62
  class FieldsExtensionGetRequest(APIRequest):
64
63
  """Additional fields for the GET request."""
65
64
 
66
- fields: Optional[List[str]] = attr.ib(default=None, converter=_fields_converter)
65
+ fields: list[str] | None = attr.ib(default=None, converter=_fields_converter)
67
66
 
68
67
 
69
68
  class FieldsExtensionPostRequest(BaseModel):
70
69
  """Additional fields and schema for the POST request."""
71
70
 
72
- fields: Optional[PostFieldsExtension] = Field(
71
+ fields: PostFieldsExtension | None = Field(
73
72
  PostFieldsExtension(),
74
73
  description="Include or exclude fields from items body.",
75
74
  )
@@ -1,7 +1,7 @@
1
1
  """Filter extensions clients."""
2
2
 
3
3
  import abc
4
- from typing import Any, Dict, Optional
4
+ from typing import Any
5
5
 
6
6
  import attr
7
7
 
@@ -11,8 +11,8 @@ class AsyncBaseFiltersClient(abc.ABC):
11
11
  """Defines a pattern for implementing the STAC filter extension."""
12
12
 
13
13
  async def get_queryables(
14
- self, collection_id: Optional[str] = None, **kwargs
15
- ) -> Dict[str, Any]:
14
+ self, collection_id: str | None = None, **kwargs
15
+ ) -> dict[str, Any]:
16
16
  """Get the queryables available for the given collection_id.
17
17
 
18
18
  If collection_id is None, returns the intersection of all queryables over all
@@ -37,8 +37,8 @@ class BaseFiltersClient(abc.ABC):
37
37
  """Defines a pattern for implementing the STAC filter extension."""
38
38
 
39
39
  def get_queryables(
40
- self, collection_id: Optional[str] = None, **kwargs
41
- ) -> Dict[str, Any]:
40
+ self, collection_id: str | None = None, **kwargs
41
+ ) -> dict[str, Any]:
42
42
  """Get the queryables available for the given collection_id.
43
43
 
44
44
  If collection_id is None, returns the intersection of all queryables over all
@@ -1,8 +1,6 @@
1
- # encoding: utf-8
2
1
  """Filter Extension."""
3
2
 
4
- from enum import Enum
5
- from typing import List, Type, Union
3
+ from enum import StrEnum
6
4
 
7
5
  import attr
8
6
  from fastapi import APIRouter, FastAPI
@@ -18,7 +16,7 @@ from .client import AsyncBaseFiltersClient, BaseFiltersClient
18
16
  from .request import FilterExtensionGetRequest, FilterExtensionPostRequest
19
17
 
20
18
 
21
- class FilterConformanceClasses(str, Enum):
19
+ class FilterConformanceClasses(StrEnum):
22
20
  """Conformance classes for the Filter extension.
23
21
 
24
22
  See
@@ -74,13 +72,13 @@ class FilterExtension(ApiExtension):
74
72
  conformance_classes: Conformance classes provided by the extension
75
73
  """
76
74
 
77
- GET: Type[APIRequest] = FilterExtensionGetRequest
78
- POST: Type[BaseModel] = FilterExtensionPostRequest
75
+ GET: type[APIRequest] = FilterExtensionGetRequest
76
+ POST: type[BaseModel] = FilterExtensionPostRequest
79
77
 
80
- client: Union[AsyncBaseFiltersClient, BaseFiltersClient] = attr.ib(
78
+ client: AsyncBaseFiltersClient | BaseFiltersClient = attr.ib(
81
79
  factory=BaseFiltersClient
82
80
  )
83
- conformance_classes: List[str] = attr.ib(
81
+ conformance_classes: list[str] = attr.ib(
84
82
  default=[
85
83
  FilterConformanceClasses.FILTER,
86
84
  FilterConformanceClasses.SEARCH,
@@ -91,7 +89,7 @@ class FilterExtension(ApiExtension):
91
89
  ]
92
90
  )
93
91
  router: APIRouter = attr.ib(factory=APIRouter)
94
- response_class: Type[Response] = attr.ib(default=JSONSchemaResponse)
92
+ response_class: type[Response] = attr.ib(default=JSONSchemaResponse)
95
93
 
96
94
  def register(self, app: FastAPI) -> None:
97
95
  """Register the extension with a FastAPI application.
@@ -140,7 +138,7 @@ class FilterExtension(ApiExtension):
140
138
  class SearchFilterExtension(FilterExtension):
141
139
  """Item Search Filter Extension."""
142
140
 
143
- conformance_classes: List[str] = attr.ib(
141
+ conformance_classes: list[str] = attr.ib(
144
142
  default=[
145
143
  FilterConformanceClasses.FILTER,
146
144
  FilterConformanceClasses.SEARCH,
@@ -182,7 +180,7 @@ class SearchFilterExtension(FilterExtension):
182
180
  class ItemCollectionFilterExtension(FilterExtension):
183
181
  """Item Collection Filter Extension."""
184
182
 
185
- conformance_classes: List[str] = attr.ib(
183
+ conformance_classes: list[str] = attr.ib(
186
184
  default=[
187
185
  FilterConformanceClasses.FILTER,
188
186
  FilterConformanceClasses.ITEMS,
@@ -224,7 +222,7 @@ class ItemCollectionFilterExtension(FilterExtension):
224
222
  class CollectionSearchFilterExtension(FilterExtension):
225
223
  """Collection Search Filter Extension."""
226
224
 
227
- conformance_classes: List[str] = attr.ib(
225
+ conformance_classes: list[str] = attr.ib(
228
226
  default=[
229
227
  FilterConformanceClasses.FILTER,
230
228
  FilterConformanceClasses.COLLECTIONS,