cadwyn 3.15.2__tar.gz → 3.15.3__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.2 → cadwyn-3.15.3}/PKG-INFO +1 -1
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/applications.py +27 -11
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/routing.py +37 -5
- {cadwyn-3.15.2 → cadwyn-3.15.3}/pyproject.toml +1 -1
- {cadwyn-3.15.2 → cadwyn-3.15.3}/LICENSE +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/README.md +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/__init__.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/__main__.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_asts.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_compat.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_package_utils.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_utils.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/README.md +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/__init__.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_common.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_main.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/__init__.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/class_migrations.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/class_rebuilding.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/class_renaming.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/import_auto_adding.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/module_migrations.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/exceptions.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/main.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/middleware.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/py.typed +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/route_generation.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/static/__init__.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/static/docs.html +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/common.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/data.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/endpoints.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/enums.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/modules.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/schemas.py +0 -0
- {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/versions.py +0 -0
|
@@ -59,8 +59,13 @@ class Cadwyn(FastAPI):
|
|
|
59
59
|
swagger_ui_oauth2_redirect_url: str | None = "/docs/oauth2-redirect",
|
|
60
60
|
swagger_ui_init_oauth: dict[str, Any] | None = None,
|
|
61
61
|
middleware: Sequence[Middleware] | None = None,
|
|
62
|
-
exception_handlers:
|
|
63
|
-
|
|
62
|
+
exception_handlers: (
|
|
63
|
+
dict[
|
|
64
|
+
int | type[Exception],
|
|
65
|
+
Callable[[Request, Any], Coroutine[Any, Any, Response]],
|
|
66
|
+
]
|
|
67
|
+
| None
|
|
68
|
+
) = None,
|
|
64
69
|
on_startup: Sequence[Callable[[], Any]] | None = None,
|
|
65
70
|
on_shutdown: Sequence[Callable[[], Any]] | None = None,
|
|
66
71
|
lifespan: Lifespan[Self] | None = None,
|
|
@@ -76,7 +81,9 @@ class Cadwyn(FastAPI):
|
|
|
76
81
|
deprecated: bool | None = None,
|
|
77
82
|
include_in_schema: bool = True,
|
|
78
83
|
swagger_ui_parameters: dict[str, Any] | None = None,
|
|
79
|
-
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
|
|
84
|
+
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( # noqa: B008
|
|
85
|
+
generate_unique_id
|
|
86
|
+
),
|
|
80
87
|
separate_input_output_schemas: bool = True,
|
|
81
88
|
**extra: Any,
|
|
82
89
|
) -> None:
|
|
@@ -228,7 +235,7 @@ class Cadwyn(FastAPI):
|
|
|
228
235
|
terms_of_service=self.terms_of_service,
|
|
229
236
|
contact=self.contact,
|
|
230
237
|
license_info=self.license_info,
|
|
231
|
-
routes=self.router.
|
|
238
|
+
routes=self.router.unversioned_routes,
|
|
232
239
|
tags=self.openapi_tags,
|
|
233
240
|
servers=self.servers,
|
|
234
241
|
)
|
|
@@ -316,21 +323,30 @@ class Cadwyn(FastAPI):
|
|
|
316
323
|
except ValueError as e:
|
|
317
324
|
raise ValueError("header_value should be in ISO 8601 format") from e
|
|
318
325
|
|
|
326
|
+
added_routes: list[BaseRoute] = []
|
|
319
327
|
if header_value_as_dt not in self.router.versioned_routers: # pragma: no branch
|
|
320
328
|
self.router.versioned_routers[header_value_as_dt] = APIRouter(**self._kwargs_to_router)
|
|
321
|
-
if self.openapi_url is not None: # pragma: no branch
|
|
322
|
-
self.router.versioned_routers[header_value_as_dt].add_route(
|
|
323
|
-
path=self.openapi_url,
|
|
324
|
-
endpoint=self.openapi_jsons,
|
|
325
|
-
include_in_schema=False,
|
|
326
|
-
)
|
|
327
329
|
|
|
328
|
-
|
|
330
|
+
versioned_router = self.router.versioned_routers[header_value_as_dt]
|
|
331
|
+
if self.openapi_url is not None: # pragma: no branch
|
|
332
|
+
versioned_router.add_route(
|
|
333
|
+
path=self.openapi_url,
|
|
334
|
+
endpoint=self.openapi_jsons,
|
|
335
|
+
include_in_schema=False,
|
|
336
|
+
)
|
|
337
|
+
added_routes.append(versioned_router.routes[-1])
|
|
338
|
+
|
|
339
|
+
added_route_count = 0
|
|
329
340
|
for router in (first_router, *other_routers):
|
|
330
341
|
self.router.versioned_routers[header_value_as_dt].include_router(
|
|
331
342
|
router,
|
|
332
343
|
dependencies=[Depends(_get_api_version_dependency(self.router.api_version_header_name, header_value))],
|
|
333
344
|
)
|
|
345
|
+
added_route_count += len(router.routes)
|
|
346
|
+
|
|
347
|
+
added_routes.extend(versioned_router.routes[-added_route_count:])
|
|
348
|
+
self.router.routes.extend(added_routes)
|
|
349
|
+
|
|
334
350
|
self.enrich_swagger()
|
|
335
351
|
return added_routes
|
|
336
352
|
|
|
@@ -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, Route
|
|
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,
|
|
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,6 +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
|
|
54
|
+
self.unversioned_routes: list[Route] = []
|
|
49
55
|
|
|
50
56
|
@cached_property
|
|
51
57
|
def sorted_versions(self):
|
|
@@ -68,13 +74,19 @@ class _RootHeaderAPIRouter(APIRouter):
|
|
|
68
74
|
# then the request version is older that the oldest route we have
|
|
69
75
|
_logger.info(
|
|
70
76
|
"Request version is older than the oldest version. No route can match this version",
|
|
71
|
-
extra={
|
|
77
|
+
extra={
|
|
78
|
+
"oldest_version": self.min_routes_version.isoformat(),
|
|
79
|
+
"request_version": request_version,
|
|
80
|
+
},
|
|
72
81
|
)
|
|
73
82
|
return []
|
|
74
83
|
version_chosen = self.find_closest_date_but_not_new(request_header_value)
|
|
75
84
|
_logger.info(
|
|
76
85
|
"Partial match. The endpoint with a lower version was selected for the API call",
|
|
77
|
-
extra={
|
|
86
|
+
extra={
|
|
87
|
+
"version_chosen": version_chosen,
|
|
88
|
+
"request_version": request_version,
|
|
89
|
+
},
|
|
78
90
|
)
|
|
79
91
|
return self.versioned_routers[version_chosen].routes
|
|
80
92
|
|
|
@@ -94,13 +106,33 @@ class _RootHeaderAPIRouter(APIRouter):
|
|
|
94
106
|
# if header_value is None, then it's an unversioned request and we need to use the unversioned routes
|
|
95
107
|
# if there will be a value, we search for the most suitable version
|
|
96
108
|
if not header_value:
|
|
97
|
-
routes = self.
|
|
109
|
+
routes = self.unversioned_routes
|
|
98
110
|
elif header_value in self.versioned_routers:
|
|
99
111
|
routes = self.versioned_routers[header_value].routes
|
|
100
112
|
else:
|
|
101
113
|
routes = self.pick_version(request_header_value=header_value)
|
|
102
114
|
await self.process_request(scope=scope, receive=receive, send=send, routes=routes)
|
|
103
115
|
|
|
116
|
+
@same_definition_as_in(APIRouter.add_api_route)
|
|
117
|
+
def add_api_route(self, *args: Any, **kwargs: Any):
|
|
118
|
+
super().add_api_route(*args, **kwargs)
|
|
119
|
+
self.unversioned_routes.append(self.routes[-1])
|
|
120
|
+
|
|
121
|
+
@same_definition_as_in(APIRouter.add_route)
|
|
122
|
+
def add_route(self, *args: Any, **kwargs: Any):
|
|
123
|
+
super().add_route(*args, **kwargs)
|
|
124
|
+
self.unversioned_routes.append(self.routes[-1])
|
|
125
|
+
|
|
126
|
+
@same_definition_as_in(APIRouter.add_api_websocket_route)
|
|
127
|
+
def add_api_websocket_route(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
128
|
+
super().add_api_websocket_route(*args, **kwargs)
|
|
129
|
+
self.unversioned_routes.append(self.routes[-1])
|
|
130
|
+
|
|
131
|
+
@same_definition_as_in(APIRouter.add_websocket_route)
|
|
132
|
+
def add_websocket_route(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
133
|
+
super().add_websocket_route(*args, **kwargs)
|
|
134
|
+
self.unversioned_routes.append(self.routes[-1])
|
|
135
|
+
|
|
104
136
|
async def process_request(self, scope: Scope, receive: Receive, send: Send, routes: Sequence[BaseRoute]) -> None:
|
|
105
137
|
"""
|
|
106
138
|
its a copy-paste from starlette.routing.Router
|
|
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
|