stac-fastapi.api 6.1.2__tar.gz → 6.1.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stac-fastapi-api
3
- Version: 6.1.2
3
+ Version: 6.1.4
4
4
  Summary: An implementation of STAC API based on the FastAPI framework.
5
5
  Project-URL: Homepage, https://github.com/stac-utils/stac-fastapi
6
6
  Author-email: ArturoAI <engineering@arturo.ai>
@@ -8,6 +8,7 @@ import attr
8
8
  from brotli_asgi import BrotliMiddleware
9
9
  from fastapi import APIRouter, FastAPI
10
10
  from fastapi.params import Depends
11
+ from pydantic import BaseModel
11
12
  from stac_pydantic import api
12
13
  from stac_pydantic.shared import MimeTypes
13
14
  from stac_pydantic.version import STAC_VERSION
@@ -114,12 +115,8 @@ class StacApi:
114
115
  converter=update_openapi, # type: ignore
115
116
  )
116
117
  router: APIRouter = attr.ib(default=attr.Factory(APIRouter))
117
- search_get_request_model: Type[BaseSearchGetRequest] = attr.ib(
118
- default=BaseSearchGetRequest
119
- )
120
- search_post_request_model: Type[BaseSearchPostRequest] = attr.ib(
121
- default=BaseSearchPostRequest
122
- )
118
+ search_get_request_model: Type[APIRequest] = attr.ib(default=BaseSearchGetRequest)
119
+ search_post_request_model: Type[BaseModel] = attr.ib(default=BaseSearchPostRequest)
123
120
  collections_get_request_model: Type[APIRequest] = attr.ib(default=EmptyRequest)
124
121
  collection_get_request_model: Type[APIRequest] = attr.ib(default=CollectionUri)
125
122
  items_get_request_model: Type[APIRequest] = attr.ib(default=ItemCollectionUri)
@@ -93,6 +93,8 @@ def add_exception_handlers(
93
93
  status_code=status.HTTP_400_BAD_REQUEST,
94
94
  )
95
95
 
96
+ # TODO: Argument 2 to "add_exception_handler" of "Starlette" has incompatible type
96
97
  app.add_exception_handler(
97
- RequestValidationError, request_validation_exception_handler
98
+ RequestValidationError,
99
+ request_validation_exception_handler, # type: ignore [arg-type]
98
100
  )
@@ -86,7 +86,7 @@ class ProxyHeaderMiddleware:
86
86
  proto = scope.get("scheme", "http")
87
87
  header_host = self._get_header_value_by_name(scope, "host")
88
88
  if header_host is None:
89
- domain, port = scope.get("server")
89
+ domain, port = scope["server"]
90
90
  else:
91
91
  header_host_parts = header_host.split(":")
92
92
  if len(header_host_parts) == 2:
@@ -1,6 +1,6 @@
1
1
  """Api request/response models."""
2
2
 
3
- from typing import List, Literal, Optional, Type, Union
3
+ from typing import List, Literal, Optional, Type, Union, cast
4
4
 
5
5
  import attr
6
6
  from fastapi import Path, Query
@@ -24,7 +24,7 @@ try:
24
24
  import orjson # noqa
25
25
  from fastapi.responses import ORJSONResponse as JSONResponse
26
26
  except ImportError: # pragma: nocover
27
- from starlette.responses import JSONResponse
27
+ from starlette.responses import JSONResponse # type: ignore [assignment]
28
28
 
29
29
 
30
30
  def create_request_model(
@@ -32,11 +32,11 @@ def create_request_model(
32
32
  base_model: Union[Type[BaseModel], Type[APIRequest]] = BaseSearchGetRequest,
33
33
  extensions: Optional[List[ApiExtension]] = None,
34
34
  mixins: Optional[Union[List[Type[BaseModel]], List[Type[APIRequest]]]] = None,
35
- request_type: Optional[str] = "GET",
35
+ request_type: str = "GET",
36
36
  ) -> Union[Type[BaseModel], Type[APIRequest]]:
37
37
  """Create a pydantic model for validating request bodies."""
38
38
  fields = {}
39
- extension_models = []
39
+ extension_models: List[Union[Type[BaseModel], Type[APIRequest]]] = []
40
40
 
41
41
  # Check extensions for additional parameters to search
42
42
  for extension in extensions or []:
@@ -49,44 +49,47 @@ def create_request_model(
49
49
 
50
50
  # Handle GET requests
51
51
  if all([issubclass(m, APIRequest) for m in models]):
52
- return attr.make_class(model_name, attrs={}, bases=tuple(models))
52
+ get_model = attr.make_class(model_name, attrs={}, bases=tuple(models))
53
+ return cast(Type[APIRequest], get_model)
53
54
 
54
55
  # Handle POST requests
55
56
  elif all([issubclass(m, BaseModel) for m in models]):
56
57
  for model in models:
57
- for k, field_info in model.model_fields.items():
58
+ for k, field_info in model.model_fields.items(): # type: ignore
58
59
  fields[k] = (field_info.annotation, field_info)
59
60
 
60
- return create_model(model_name, **fields, __base__=base_model) # type: ignore
61
+ post_model = create_model(model_name, **fields, __base__=base_model) # type: ignore
62
+ return cast(Type[BaseModel], post_model)
61
63
 
62
64
  raise TypeError("Mixed Request Model types. Check extension request types.")
63
65
 
64
66
 
65
67
  def create_get_request_model(
66
68
  extensions: Optional[List[ApiExtension]],
67
- base_model: BaseSearchGetRequest = BaseSearchGetRequest,
69
+ base_model: Type[APIRequest] = BaseSearchGetRequest,
68
70
  ) -> Type[APIRequest]:
69
71
  """Wrap create_request_model to create the GET request model."""
70
-
71
- return create_request_model(
72
+ model = create_request_model(
72
73
  "SearchGetRequest",
73
74
  base_model=base_model,
74
75
  extensions=extensions,
75
76
  request_type="GET",
76
77
  )
78
+ return cast(Type[APIRequest], model)
77
79
 
78
80
 
79
81
  def create_post_request_model(
80
82
  extensions: Optional[List[ApiExtension]],
81
- base_model: BaseSearchPostRequest = BaseSearchPostRequest,
83
+ base_model: Type[BaseModel] = BaseSearchPostRequest,
82
84
  ) -> Type[BaseModel]:
83
85
  """Wrap create_request_model to create the POST request model."""
84
- return create_request_model(
86
+ model = create_request_model(
85
87
  "SearchPostRequest",
86
88
  base_model=base_model,
87
89
  extensions=extensions,
88
90
  request_type="POST",
89
91
  )
92
+ return cast(Type[BaseModel], model)
90
93
 
91
94
 
92
95
  @attr.s
@@ -122,7 +125,7 @@ class ItemCollectionUri(APIRequest, DatetimeMixin):
122
125
  description="Limits the number of results that are included in each page of the response (capped to 10_000)." # noqa: E501
123
126
  ),
124
127
  ] = attr.ib(default=10)
125
- bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter) # type: ignore
128
+ bbox: Optional[BBox] = attr.ib(default=None, converter=_bbox_converter) # type: ignore [misc]
126
129
  datetime: DateTimeQueryType = attr.ib(default=None, validator=_validate_datetime)
127
130
 
128
131
 
@@ -14,8 +14,11 @@ def update_openapi(app: FastAPI) -> FastAPI:
14
14
  content-type response header.
15
15
  """
16
16
  # Find the route for the openapi_url in the app
17
+ # TODO: Type info is Route, while it shoukd maybe be APIRoute? Check FastAPI source.
17
18
  openapi_route: Route = next(
18
- route for route in app.router.routes if route.path == app.openapi_url
19
+ route
20
+ for route in app.router.routes
21
+ if route.path == app.openapi_url # type: ignore
19
22
  )
20
23
  # Store the old endpoint function so we can call it from the patched function
21
24
  old_endpoint = openapi_route.endpoint
@@ -16,7 +16,7 @@ from starlette.responses import Response
16
16
  from starlette.routing import BaseRoute, Match
17
17
  from starlette.status import HTTP_204_NO_CONTENT
18
18
 
19
- from stac_fastapi.api.models import APIRequest
19
+ from stac_fastapi.types.search import APIRequest
20
20
 
21
21
 
22
22
  def _wrap_response(resp: Any) -> Any:
@@ -58,7 +58,7 @@ def create_async_endpoint(
58
58
 
59
59
  elif issubclass(request_model, APIRequest):
60
60
 
61
- async def _endpoint(request: Request, request_data=Depends(request_model)):
61
+ async def _endpoint(request: Request, request_data=Depends(request_model)): # type: ignore
62
62
  """Endpoint."""
63
63
  return _wrap_response(await func(request=request, **request_data.kwargs()))
64
64
 
@@ -100,10 +100,14 @@ def add_route_dependencies(
100
100
  _scope = copy.deepcopy(scope)
101
101
  for route in routes:
102
102
  if scope["path"] == "*":
103
- _scope["path"] = route.path
103
+ # NOTE: ignore type, because BaseRoute has no "path" attribute
104
+ # but APIRoute does.
105
+ _scope["path"] = route.path # type: ignore
104
106
 
107
+ # NOTE: ignore type, because BaseRoute has no "method" attribute
108
+ # but APIRoute does.
105
109
  if scope["method"] == "*":
106
- _scope["method"] = list(route.methods)[0]
110
+ _scope["method"] = list(route.methods)[0] # type: ignore
107
111
 
108
112
  match, _ = route.matches({"type": "http", **_scope})
109
113
  if match != Match.FULL:
@@ -119,7 +123,10 @@ def add_route_dependencies(
119
123
  route.dependant.dependencies.insert(
120
124
  0,
121
125
  get_parameterless_sub_dependant(
122
- depends=depends, path=route.path_format
126
+ # NOTE: ignore type, because BaseRoute has no "path_format"
127
+ # attribute but APIRoute does.
128
+ depends=depends,
129
+ path=route.path_format, # type: ignore
123
130
  ),
124
131
  )
125
132
 
@@ -128,7 +135,9 @@ def add_route_dependencies(
128
135
  # app.include_router(router))
129
136
  # https://github.com/tiangolo/fastapi/blob/58ab733f19846b4875c5b79bfb1f4d1cb7f4823f/fastapi/applications.py#L337-L360
130
137
  # https://github.com/tiangolo/fastapi/blob/58ab733f19846b4875c5b79bfb1f4d1cb7f4823f/fastapi/routing.py#L677-L678
131
- route.dependencies.extend(dependencies)
138
+ # NOTE: ignore type, because BaseRoute has no "dependencies" attribute
139
+ # but APIRoute does.
140
+ route.dependencies.extend(dependencies) # type: ignore
132
141
 
133
142
 
134
143
  def add_direct_response(app: FastAPI) -> None:
@@ -1,3 +1,3 @@
1
1
  """Library version."""
2
2
 
3
- __version__ = "6.1.2"
3
+ __version__ = "6.1.4"