cadwyn 3.15.3a2__tar.gz → 3.15.5__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.
Potentially problematic release.
This version of cadwyn might be problematic. Click here for more details.
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/PKG-INFO +1 -1
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/applications.py +83 -174
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/routing.py +24 -9
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/pyproject.toml +1 -1
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/LICENSE +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/README.md +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/__init__.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/__main__.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/_asts.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/_compat.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/_package_utils.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/_utils.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/README.md +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/__init__.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_common.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_main.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_plugins/__init__.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_plugins/class_migrations.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_plugins/class_rebuilding.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_plugins/class_renaming.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_plugins/import_auto_adding.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/codegen/_plugins/module_migrations.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/exceptions.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/main.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/middleware.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/py.typed +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/route_generation.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/static/__init__.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/static/docs.html +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/common.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/data.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/endpoints.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/enums.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/modules.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/schemas.py +0 -0
- {cadwyn-3.15.3a2 → cadwyn-3.15.5}/cadwyn/structure/versions.py +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import datetime
|
|
1
3
|
from collections.abc import Callable, Coroutine, Sequence
|
|
2
4
|
from datetime import date
|
|
3
5
|
from logging import getLogger
|
|
@@ -24,7 +26,6 @@ from starlette.routing import BaseRoute, Route
|
|
|
24
26
|
from starlette.types import Lifespan
|
|
25
27
|
from typing_extensions import Self, deprecated
|
|
26
28
|
|
|
27
|
-
from cadwyn._utils import same_definition_as_in
|
|
28
29
|
from cadwyn.middleware import HeaderVersioningMiddleware, _get_api_version_dependency
|
|
29
30
|
from cadwyn.route_generation import generate_versioned_routers
|
|
30
31
|
from cadwyn.routing import _RootHeaderAPIRouter
|
|
@@ -34,6 +35,11 @@ CURR_DIR = Path(__file__).resolve()
|
|
|
34
35
|
logger = getLogger(__name__)
|
|
35
36
|
|
|
36
37
|
|
|
38
|
+
@dataclasses.dataclass(slots=True)
|
|
39
|
+
class FakeDependencyOverridesProvider:
|
|
40
|
+
dependency_overrides: dict[Callable[..., Any], Callable[..., Any]]
|
|
41
|
+
|
|
42
|
+
|
|
37
43
|
class Cadwyn(FastAPI):
|
|
38
44
|
_templates = Jinja2Templates(directory=CURR_DIR.parent / "static")
|
|
39
45
|
|
|
@@ -81,20 +87,18 @@ class Cadwyn(FastAPI):
|
|
|
81
87
|
deprecated: bool | None = None,
|
|
82
88
|
include_in_schema: bool = True,
|
|
83
89
|
swagger_ui_parameters: dict[str, Any] | None = None,
|
|
84
|
-
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
|
|
90
|
+
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( # noqa: B008
|
|
85
91
|
generate_unique_id
|
|
86
|
-
),
|
|
92
|
+
),
|
|
87
93
|
separate_input_output_schemas: bool = True,
|
|
88
94
|
**extra: Any,
|
|
89
95
|
) -> None:
|
|
90
96
|
self.versions = versions
|
|
91
97
|
# TODO: Remove argument entirely in any major version.
|
|
92
|
-
latest_schemas_package = (
|
|
93
|
-
extra.pop("latest_schemas_package", None)
|
|
94
|
-
or self.versions.head_schemas_package
|
|
95
|
-
)
|
|
98
|
+
latest_schemas_package = extra.pop("latest_schemas_package", None) or self.versions.head_schemas_package
|
|
96
99
|
self.versions.head_schemas_package = latest_schemas_package
|
|
97
100
|
self._latest_schemas_package = cast(ModuleType, latest_schemas_package)
|
|
101
|
+
self._dependency_overrides_provider = FakeDependencyOverridesProvider({})
|
|
98
102
|
|
|
99
103
|
super().__init__(
|
|
100
104
|
debug=debug,
|
|
@@ -148,23 +152,20 @@ class Cadwyn(FastAPI):
|
|
|
148
152
|
"responses": responses,
|
|
149
153
|
"generate_unique_id_function": generate_unique_id_function,
|
|
150
154
|
}
|
|
151
|
-
self.router: _RootHeaderAPIRouter = (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
api_version_var=self.versions.api_version_var,
|
|
156
|
-
)
|
|
155
|
+
self.router: _RootHeaderAPIRouter = _RootHeaderAPIRouter( # pyright: ignore[reportIncompatibleVariableOverride]
|
|
156
|
+
**self._kwargs_to_router,
|
|
157
|
+
api_version_header_name=api_version_header_name,
|
|
158
|
+
api_version_var=self.versions.api_version_var,
|
|
157
159
|
)
|
|
158
160
|
|
|
159
161
|
self.docs_url = docs_url
|
|
160
162
|
self.redoc_url = redoc_url
|
|
161
163
|
self.openapi_url = openapi_url
|
|
162
164
|
self.redoc_url = redoc_url
|
|
163
|
-
self.swaggers = {}
|
|
164
165
|
|
|
165
166
|
unversioned_router = APIRouter(**self._kwargs_to_router)
|
|
166
167
|
self._add_openapi_endpoints(unversioned_router)
|
|
167
|
-
self.
|
|
168
|
+
self.include_router(unversioned_router)
|
|
168
169
|
self.add_middleware(
|
|
169
170
|
HeaderVersioningMiddleware,
|
|
170
171
|
api_version_header_name=self.router.api_version_header_name,
|
|
@@ -172,17 +173,27 @@ class Cadwyn(FastAPI):
|
|
|
172
173
|
default_response_class=default_response_class,
|
|
173
174
|
)
|
|
174
175
|
|
|
176
|
+
@property
|
|
177
|
+
def dependency_overrides(self) -> dict[Callable[..., Any], Callable[..., Any]]:
|
|
178
|
+
# This is only necessary because we cannot send self to versioned router generator
|
|
179
|
+
# because it takes a deepcopy of the router and self.versions.head_schemas_package is a module
|
|
180
|
+
# which cannot be copied.
|
|
181
|
+
return self._dependency_overrides_provider.dependency_overrides
|
|
182
|
+
|
|
183
|
+
@dependency_overrides.setter
|
|
184
|
+
def dependency_overrides( # pyright: ignore[reportIncompatibleVariableOverride]
|
|
185
|
+
self,
|
|
186
|
+
value: dict[Callable[..., Any], Callable[..., Any]],
|
|
187
|
+
) -> None:
|
|
188
|
+
self._dependency_overrides_provider.dependency_overrides = value
|
|
189
|
+
|
|
175
190
|
@property # pragma: no cover
|
|
176
|
-
@deprecated(
|
|
177
|
-
"It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead"
|
|
178
|
-
)
|
|
191
|
+
@deprecated("It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead")
|
|
179
192
|
def latest_schemas_package(self):
|
|
180
193
|
return self._latest_schemas_package
|
|
181
194
|
|
|
182
195
|
@latest_schemas_package.setter # pragma: no cover
|
|
183
|
-
@deprecated(
|
|
184
|
-
"It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead"
|
|
185
|
-
)
|
|
196
|
+
@deprecated("It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead")
|
|
186
197
|
def latest_schemas_package(self, value: ModuleType | None):
|
|
187
198
|
self._latest_schemas_package = value
|
|
188
199
|
|
|
@@ -219,7 +230,7 @@ class Cadwyn(FastAPI):
|
|
|
219
230
|
)
|
|
220
231
|
|
|
221
232
|
def generate_and_include_versioned_routers(self, *routers: APIRouter) -> None:
|
|
222
|
-
root_router = APIRouter()
|
|
233
|
+
root_router = APIRouter(dependency_overrides_provider=self._dependency_overrides_provider)
|
|
223
234
|
for router in routers:
|
|
224
235
|
root_router.include_router(router)
|
|
225
236
|
router_versions = generate_versioned_routers(
|
|
@@ -229,57 +240,45 @@ class Cadwyn(FastAPI):
|
|
|
229
240
|
for version, router in router_versions.items():
|
|
230
241
|
self.add_header_versioned_routers(router, header_value=version.isoformat())
|
|
231
242
|
|
|
232
|
-
def
|
|
233
|
-
""
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
"""
|
|
239
|
-
unversioned_routes_openapi = get_openapi(
|
|
240
|
-
title=self.title,
|
|
241
|
-
version=self.version,
|
|
242
|
-
openapi_version=self.openapi_version,
|
|
243
|
-
description=self.description,
|
|
244
|
-
terms_of_service=self.terms_of_service,
|
|
245
|
-
contact=self.contact,
|
|
246
|
-
license_info=self.license_info,
|
|
247
|
-
routes=self.router.unversioned_routes,
|
|
248
|
-
tags=self.openapi_tags,
|
|
249
|
-
servers=self.servers,
|
|
243
|
+
async def openapi_jsons(self, req: Request) -> JSONResponse:
|
|
244
|
+
raw_version = req.query_params.get("version") or req.headers.get(self.router.api_version_header_name)
|
|
245
|
+
not_found_error = HTTPException(
|
|
246
|
+
status_code=404,
|
|
247
|
+
detail=f"OpenApi file of with version `{raw_version}` not found",
|
|
250
248
|
)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
249
|
+
try:
|
|
250
|
+
version = datetime.date.fromisoformat(raw_version) # pyright: ignore[reportArgumentType]
|
|
251
|
+
# TypeError when raw_version is None
|
|
252
|
+
# ValueError when raw_version is of the non-iso format
|
|
253
|
+
except (ValueError, TypeError):
|
|
254
|
+
version = raw_version
|
|
255
|
+
|
|
256
|
+
if version in self.router.versioned_routers:
|
|
257
|
+
routes = self.router.versioned_routers[version].routes
|
|
258
|
+
formatted_version = version.isoformat()
|
|
259
|
+
elif version == "unversioned" and self._there_are_public_unversioned_routes():
|
|
260
|
+
routes = self.router.unversioned_routes
|
|
261
|
+
formatted_version = "unversioned"
|
|
262
|
+
else:
|
|
263
|
+
raise not_found_error
|
|
264
|
+
|
|
265
|
+
return JSONResponse(
|
|
266
|
+
get_openapi(
|
|
257
267
|
title=self.title,
|
|
258
|
-
version=
|
|
268
|
+
version=formatted_version,
|
|
259
269
|
openapi_version=self.openapi_version,
|
|
260
270
|
description=self.description,
|
|
261
271
|
terms_of_service=self.terms_of_service,
|
|
262
272
|
contact=self.contact,
|
|
263
273
|
license_info=self.license_info,
|
|
264
|
-
routes=
|
|
274
|
+
routes=routes,
|
|
265
275
|
tags=self.openapi_tags,
|
|
266
276
|
servers=self.servers,
|
|
267
277
|
)
|
|
268
|
-
# in current implementation we expect header_value to be a date
|
|
269
|
-
self.swaggers[header_value_str] = openapi
|
|
270
|
-
|
|
271
|
-
async def openapi_jsons(self, req: Request) -> JSONResponse:
|
|
272
|
-
version = req.query_params.get("version") or req.headers.get(
|
|
273
|
-
self.router.api_version_header_name
|
|
274
278
|
)
|
|
275
|
-
openapi_of_a_version = self.swaggers.get(version)
|
|
276
|
-
if not openapi_of_a_version:
|
|
277
|
-
raise HTTPException(
|
|
278
|
-
status_code=404,
|
|
279
|
-
detail=f"OpenApi file of with version `{version}` not found",
|
|
280
|
-
)
|
|
281
279
|
|
|
282
|
-
|
|
280
|
+
def _there_are_public_unversioned_routes(self):
|
|
281
|
+
return any(isinstance(route, Route) and route.include_in_schema for route in self.router.unversioned_routes)
|
|
283
282
|
|
|
284
283
|
async def swagger_dashboard(self, req: Request) -> Response:
|
|
285
284
|
version = req.query_params.get("version")
|
|
@@ -305,9 +304,7 @@ class Cadwyn(FastAPI):
|
|
|
305
304
|
if version:
|
|
306
305
|
root_path = self._extract_root_path(req)
|
|
307
306
|
openapi_url = root_path + f"{self.openapi_url}?version={version}"
|
|
308
|
-
return get_redoc_html(
|
|
309
|
-
openapi_url=openapi_url, title=f"{self.title} - ReDoc"
|
|
310
|
-
)
|
|
307
|
+
return get_redoc_html(openapi_url=openapi_url, title=f"{self.title} - ReDoc")
|
|
311
308
|
|
|
312
309
|
return self._render_docs_dashboard(req, docs_url=cast(str, self.redoc_url))
|
|
313
310
|
|
|
@@ -316,15 +313,12 @@ class Cadwyn(FastAPI):
|
|
|
316
313
|
|
|
317
314
|
def _render_docs_dashboard(self, req: Request, docs_url: str):
|
|
318
315
|
base_url = str(req.base_url).rstrip("/")
|
|
316
|
+
table = {version: f"{base_url}{docs_url}?version={version}" for version in self.router.sorted_versions}
|
|
317
|
+
if self._there_are_public_unversioned_routes():
|
|
318
|
+
table |= {"unversioned": f"{base_url}{docs_url}?version=unversioned"}
|
|
319
319
|
return self._templates.TemplateResponse(
|
|
320
320
|
"docs.html",
|
|
321
|
-
{
|
|
322
|
-
"request": req,
|
|
323
|
-
"table": {
|
|
324
|
-
version: f"{base_url}{docs_url}?version={version}"
|
|
325
|
-
for version in sorted(self.swaggers)
|
|
326
|
-
},
|
|
327
|
-
},
|
|
321
|
+
{"request": req, "table": table},
|
|
328
322
|
)
|
|
329
323
|
|
|
330
324
|
def add_header_versioned_routers(
|
|
@@ -339,126 +333,41 @@ class Cadwyn(FastAPI):
|
|
|
339
333
|
except ValueError as e:
|
|
340
334
|
raise ValueError("header_value should be in ISO 8601 format") from e
|
|
341
335
|
|
|
336
|
+
added_routes: list[BaseRoute] = []
|
|
342
337
|
if header_value_as_dt not in self.router.versioned_routers: # pragma: no branch
|
|
343
|
-
self.router.versioned_routers[header_value_as_dt] = APIRouter(
|
|
344
|
-
|
|
338
|
+
self.router.versioned_routers[header_value_as_dt] = APIRouter(**self._kwargs_to_router)
|
|
339
|
+
|
|
340
|
+
versioned_router = self.router.versioned_routers[header_value_as_dt]
|
|
341
|
+
if self.openapi_url is not None: # pragma: no branch
|
|
342
|
+
versioned_router.add_route(
|
|
343
|
+
path=self.openapi_url,
|
|
344
|
+
endpoint=self.openapi_jsons,
|
|
345
|
+
include_in_schema=False,
|
|
345
346
|
)
|
|
346
|
-
|
|
347
|
-
self.router.versioned_routers[header_value_as_dt].add_route(
|
|
348
|
-
path=self.openapi_url,
|
|
349
|
-
endpoint=self.openapi_jsons,
|
|
350
|
-
include_in_schema=False,
|
|
351
|
-
)
|
|
347
|
+
added_routes.append(versioned_router.routes[-1])
|
|
352
348
|
|
|
353
|
-
version_router = self.router.versioned_routers[header_value_as_dt]
|
|
354
|
-
added_routes: list[BaseRoute] = []
|
|
355
349
|
added_route_count = 0
|
|
356
350
|
for router in (first_router, *other_routers):
|
|
357
351
|
self.router.versioned_routers[header_value_as_dt].include_router(
|
|
358
352
|
router,
|
|
359
|
-
dependencies=[
|
|
360
|
-
Depends(
|
|
361
|
-
_get_api_version_dependency(
|
|
362
|
-
self.router.api_version_header_name, header_value
|
|
363
|
-
)
|
|
364
|
-
)
|
|
365
|
-
],
|
|
353
|
+
dependencies=[Depends(_get_api_version_dependency(self.router.api_version_header_name, header_value))],
|
|
366
354
|
)
|
|
367
355
|
added_route_count += len(router.routes)
|
|
368
356
|
|
|
369
|
-
added_routes
|
|
370
|
-
version_router.routes[-added_route_count :]
|
|
371
|
-
)
|
|
357
|
+
added_routes.extend(versioned_router.routes[-added_route_count:])
|
|
372
358
|
self.router.routes.extend(added_routes)
|
|
373
359
|
|
|
374
|
-
self.enrich_swagger()
|
|
375
360
|
return added_routes
|
|
376
361
|
|
|
362
|
+
@deprecated("Use builtin FastAPI methods such as include_router instead")
|
|
377
363
|
def add_unversioned_routers(self, *routers: APIRouter):
|
|
378
364
|
for router in routers:
|
|
379
|
-
self.
|
|
380
|
-
self.enrich_swagger()
|
|
365
|
+
self.include_router(router)
|
|
381
366
|
|
|
382
|
-
@deprecated("Use
|
|
367
|
+
@deprecated("Use builtin FastAPI methods such as add_api_route instead")
|
|
383
368
|
def add_unversioned_routes(self, *routes: Route):
|
|
384
369
|
router = APIRouter(routes=list(routes))
|
|
385
370
|
self.include_router(router)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
def include_router(self, *args: Any, **kwargs: Any):
|
|
390
|
-
route = super().include_router(*args, **kwargs)
|
|
391
|
-
self.enrich_swagger()
|
|
392
|
-
return route
|
|
393
|
-
|
|
394
|
-
@same_definition_as_in(FastAPI.post)
|
|
395
|
-
def post(self, *args: Any, **kwargs: Any):
|
|
396
|
-
route = super().post(*args, **kwargs)
|
|
397
|
-
self.enrich_swagger()
|
|
398
|
-
return route
|
|
399
|
-
|
|
400
|
-
@same_definition_as_in(FastAPI.get)
|
|
401
|
-
def get(self, *args: Any, **kwargs: Any):
|
|
402
|
-
route = super().get(*args, **kwargs)
|
|
403
|
-
self.enrich_swagger()
|
|
404
|
-
return route
|
|
405
|
-
|
|
406
|
-
@same_definition_as_in(FastAPI.patch)
|
|
407
|
-
def patch(self, *args: Any, **kwargs: Any):
|
|
408
|
-
route = super().patch(*args, **kwargs)
|
|
409
|
-
self.enrich_swagger()
|
|
410
|
-
return route
|
|
411
|
-
|
|
412
|
-
@same_definition_as_in(FastAPI.delete)
|
|
413
|
-
def delete(self, *args: Any, **kwargs: Any):
|
|
414
|
-
route = super().delete(*args, **kwargs)
|
|
415
|
-
self.enrich_swagger()
|
|
416
|
-
return route
|
|
417
|
-
|
|
418
|
-
@same_definition_as_in(FastAPI.put)
|
|
419
|
-
def put(self, *args: Any, **kwargs: Any):
|
|
420
|
-
route = super().put(*args, **kwargs)
|
|
421
|
-
self.enrich_swagger()
|
|
422
|
-
return route
|
|
423
|
-
|
|
424
|
-
@same_definition_as_in(FastAPI.trace)
|
|
425
|
-
def trace(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
426
|
-
route = super().trace(*args, **kwargs)
|
|
427
|
-
self.enrich_swagger()
|
|
428
|
-
return route
|
|
429
|
-
|
|
430
|
-
@same_definition_as_in(FastAPI.options)
|
|
431
|
-
def options(self, *args: Any, **kwargs: Any):
|
|
432
|
-
route = super().options(*args, **kwargs)
|
|
433
|
-
self.enrich_swagger()
|
|
434
|
-
return route
|
|
435
|
-
|
|
436
|
-
@same_definition_as_in(FastAPI.head)
|
|
437
|
-
def head(self, *args: Any, **kwargs: Any):
|
|
438
|
-
route = super().head(*args, **kwargs)
|
|
439
|
-
self.enrich_swagger()
|
|
440
|
-
return route
|
|
441
|
-
|
|
442
|
-
@same_definition_as_in(FastAPI.add_api_route)
|
|
443
|
-
def add_api_route(self, *args: Any, **kwargs: Any):
|
|
444
|
-
route = super().add_api_route(*args, **kwargs)
|
|
445
|
-
self.enrich_swagger()
|
|
446
|
-
return route
|
|
447
|
-
|
|
448
|
-
@same_definition_as_in(FastAPI.api_route)
|
|
449
|
-
def api_route(self, *args: Any, **kwargs: Any):
|
|
450
|
-
route = super().api_route(*args, **kwargs)
|
|
451
|
-
self.enrich_swagger()
|
|
452
|
-
return route
|
|
453
|
-
|
|
454
|
-
@same_definition_as_in(FastAPI.add_api_websocket_route)
|
|
455
|
-
def add_api_websocket_route(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
456
|
-
route = super().add_api_websocket_route(*args, **kwargs)
|
|
457
|
-
self.enrich_swagger()
|
|
458
|
-
return route
|
|
459
|
-
|
|
460
|
-
@same_definition_as_in(FastAPI.websocket)
|
|
461
|
-
def websocket(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
462
|
-
route = super().websocket(*args, **kwargs)
|
|
463
|
-
self.enrich_swagger()
|
|
464
|
-
return route
|
|
371
|
+
|
|
372
|
+
@deprecated("It no longer does anything")
|
|
373
|
+
def enrich_swagger(self): ...
|
|
@@ -9,10 +9,15 @@ from typing import Any
|
|
|
9
9
|
from fastapi.routing import APIRouter
|
|
10
10
|
from starlette.datastructures import URL
|
|
11
11
|
from starlette.responses import RedirectResponse
|
|
12
|
-
from starlette.routing import BaseRoute, Match
|
|
12
|
+
from starlette.routing import BaseRoute, Match
|
|
13
13
|
from starlette.types import Receive, Scope, Send
|
|
14
14
|
|
|
15
|
-
from .
|
|
15
|
+
from cadwyn._utils import same_definition_as_in
|
|
16
|
+
|
|
17
|
+
from .route_generation import (
|
|
18
|
+
InternalRepresentationOf, # pyright: ignore[reportDeprecated]
|
|
19
|
+
generate_versioned_routers,
|
|
20
|
+
)
|
|
16
21
|
|
|
17
22
|
# TODO: Remove this in a major version. This is only here for backwards compatibility
|
|
18
23
|
__all__ = ["InternalRepresentationOf", "generate_versioned_routers"]
|
|
@@ -46,7 +51,7 @@ class _RootHeaderAPIRouter(APIRouter):
|
|
|
46
51
|
self.versioned_routers: dict[date, APIRouter] = {}
|
|
47
52
|
self.api_version_header_name = api_version_header_name.lower()
|
|
48
53
|
self.api_version_var = api_version_var
|
|
49
|
-
self.unversioned_routes: list[
|
|
54
|
+
self.unversioned_routes: list[BaseRoute] = []
|
|
50
55
|
|
|
51
56
|
@cached_property
|
|
52
57
|
def sorted_versions(self):
|
|
@@ -69,13 +74,19 @@ class _RootHeaderAPIRouter(APIRouter):
|
|
|
69
74
|
# then the request version is older that the oldest route we have
|
|
70
75
|
_logger.info(
|
|
71
76
|
"Request version is older than the oldest version. No route can match this version",
|
|
72
|
-
extra={
|
|
77
|
+
extra={
|
|
78
|
+
"oldest_version": self.min_routes_version.isoformat(),
|
|
79
|
+
"request_version": request_version,
|
|
80
|
+
},
|
|
73
81
|
)
|
|
74
82
|
return []
|
|
75
83
|
version_chosen = self.find_closest_date_but_not_new(request_header_value)
|
|
76
84
|
_logger.info(
|
|
77
85
|
"Partial match. The endpoint with a lower version was selected for the API call",
|
|
78
|
-
extra={
|
|
86
|
+
extra={
|
|
87
|
+
"version_chosen": version_chosen,
|
|
88
|
+
"request_version": request_version,
|
|
89
|
+
},
|
|
79
90
|
)
|
|
80
91
|
return self.versioned_routers[version_chosen].routes
|
|
81
92
|
|
|
@@ -102,19 +113,23 @@ class _RootHeaderAPIRouter(APIRouter):
|
|
|
102
113
|
routes = self.pick_version(request_header_value=header_value)
|
|
103
114
|
await self.process_request(scope=scope, receive=receive, send=send, routes=routes)
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
@same_definition_as_in(APIRouter.add_api_route)
|
|
117
|
+
def add_api_route(self, *args: Any, **kwargs: Any):
|
|
106
118
|
super().add_api_route(*args, **kwargs)
|
|
107
119
|
self.unversioned_routes.append(self.routes[-1])
|
|
108
120
|
|
|
109
|
-
|
|
121
|
+
@same_definition_as_in(APIRouter.add_route)
|
|
122
|
+
def add_route(self, *args: Any, **kwargs: Any):
|
|
110
123
|
super().add_route(*args, **kwargs)
|
|
111
124
|
self.unversioned_routes.append(self.routes[-1])
|
|
112
125
|
|
|
113
|
-
|
|
126
|
+
@same_definition_as_in(APIRouter.add_api_websocket_route)
|
|
127
|
+
def add_api_websocket_route(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
114
128
|
super().add_api_websocket_route(*args, **kwargs)
|
|
115
129
|
self.unversioned_routes.append(self.routes[-1])
|
|
116
130
|
|
|
117
|
-
|
|
131
|
+
@same_definition_as_in(APIRouter.add_websocket_route)
|
|
132
|
+
def add_websocket_route(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
118
133
|
super().add_websocket_route(*args, **kwargs)
|
|
119
134
|
self.unversioned_routes.append(self.routes[-1])
|
|
120
135
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|