cadwyn 3.15.2__py3-none-any.whl → 3.15.3__py3-none-any.whl

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/applications.py CHANGED
@@ -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: dict[int | type[Exception], Callable[[Request, Any], Coroutine[Any, Any, Response]]]
63
- | None = None,
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(generate_unique_id), # noqa: B008
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.routes,
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
- added_routes: list[BaseRoute] = []
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
 
cadwyn/routing.py CHANGED
@@ -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 .route_generation import InternalRepresentationOf, generate_versioned_routers # pyright: ignore[reportDeprecated]
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={"oldest_version": self.min_routes_version.isoformat(), "request_version": request_version},
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={"version_chosen": version_chosen, "request_version": request_version},
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.routes
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cadwyn
3
- Version: 3.15.2
3
+ Version: 3.15.3
4
4
  Summary: Production-ready community-driven modern Stripe-like API versioning in FastAPI
5
5
  Home-page: https://github.com/zmievsa/cadwyn
6
6
  License: MIT
@@ -4,7 +4,7 @@ cadwyn/_asts.py,sha256=OF1qQKPqTbgYhH1tYF-MB8CCU0r6YITZpMFegzmk0Ic,10118
4
4
  cadwyn/_compat.py,sha256=yAPmfGl2vVEYXlNHHPMoa2JkEJCVPjbP_Uz0WOIVOp4,5494
5
5
  cadwyn/_package_utils.py,sha256=trxTYLmppv-10SKhScfyDQJh21rsQGFoLaOtHycKKR0,1443
6
6
  cadwyn/_utils.py,sha256=BFsfZBpdoL5RMAaT1V1cXJVpTZCmwksQ-Le2MTHivGI,4841
7
- cadwyn/applications.py,sha256=kjHgGu1ZHnmchtuuJQkzJ3leJyIz2A8M_QTMguUhNXU,17194
7
+ cadwyn/applications.py,sha256=3J_MLmwItVnGbIrqtiO7jwKoXIYkZJ2MYBX-hNRWaS8,17591
8
8
  cadwyn/codegen/README.md,sha256=hc7AE87LsEsvbh-wX1H10JEWh-8bLHoe-1CkY3h00FI,879
9
9
  cadwyn/codegen/__init__.py,sha256=JgddDjxMTjSfVrMXHwNu1ODgdn2QfPWpccrRKquBV6k,355
10
10
  cadwyn/codegen/_common.py,sha256=FTI4fqpUFGBMACVlPiDMHTWhqwW_-zQNa_4Qh7m-hCA,5877
@@ -20,7 +20,7 @@ cadwyn/main.py,sha256=kt2Vn7TIA4ZnD_xrgz57TOjUk-4zVP8SV8nuTZBEaaU,218
20
20
  cadwyn/middleware.py,sha256=8cuBri_yRkl0goe6G0MLwtL04WGbW9Infah3wy9hUVM,3372
21
21
  cadwyn/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  cadwyn/route_generation.py,sha256=nn_PWDa2WQOF-z3IOYBfG9K8po0tHm2C_Q0sRJRr5Ck,39843
23
- cadwyn/routing.py,sha256=9xC0EeI4jFVpxIkziaCsG1F5pL8l93RSGgHo_zGhqtI,6287
23
+ cadwyn/routing.py,sha256=3rxo4jzdL4rD5EntSAW9ZPWvYfD8AEy8olRum7iSE8A,7411
24
24
  cadwyn/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  cadwyn/static/docs.html,sha256=WNm5ANJVy51TcIUFOaqKf1Z8eF86CC85TTHPxACtkzw,3455
26
26
  cadwyn/structure/__init__.py,sha256=HjaNd6H4m4Cia42-dCO7A7sLWuVII7oldjaCabhbs_o,697
@@ -31,8 +31,8 @@ cadwyn/structure/enums.py,sha256=iMokxA2QYJ61SzyB-Pmuq3y7KL7-e6TsnjLVUaVZQnw,954
31
31
  cadwyn/structure/modules.py,sha256=1FK-lLm-zOTXEvn-QtyBH38aDRht5PDQiZrOPCsBlM4,1268
32
32
  cadwyn/structure/schemas.py,sha256=0ylArAkUw626VkUOJSulOwJs7CS6lrGBRECEG5HFD4Q,8897
33
33
  cadwyn/structure/versions.py,sha256=PuXYze89tWvLsOOiuAQtYRi-p1ue2FPfBWWR2bl8hLg,37236
34
- cadwyn-3.15.2.dist-info/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
35
- cadwyn-3.15.2.dist-info/METADATA,sha256=ztQ2PytxeBG0yEGNW5fTS_CVT4JCDDZyg3D7EdFn4qo,4397
36
- cadwyn-3.15.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
37
- cadwyn-3.15.2.dist-info/entry_points.txt,sha256=eO05hLn9GoRzzpwT9GONPmXKsonjuMNssM2D2WHWKGk,46
38
- cadwyn-3.15.2.dist-info/RECORD,,
34
+ cadwyn-3.15.3.dist-info/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
35
+ cadwyn-3.15.3.dist-info/METADATA,sha256=0Pb2wYzcfzNUs3RLWRFqhAiYzLLQ0-49iK1ie0vMfjg,4397
36
+ cadwyn-3.15.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
37
+ cadwyn-3.15.3.dist-info/entry_points.txt,sha256=eO05hLn9GoRzzpwT9GONPmXKsonjuMNssM2D2WHWKGk,46
38
+ cadwyn-3.15.3.dist-info/RECORD,,