cadwyn 3.15.2__py3-none-any.whl → 3.15.3a1__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,13 +81,18 @@ 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(
85
+ generate_unique_id
86
+ ), # noqa: B008
80
87
  separate_input_output_schemas: bool = True,
81
88
  **extra: Any,
82
89
  ) -> None:
83
90
  self.versions = versions
84
91
  # TODO: Remove argument entirely in any major version.
85
- latest_schemas_package = extra.pop("latest_schemas_package", None) or self.versions.head_schemas_package
92
+ latest_schemas_package = (
93
+ extra.pop("latest_schemas_package", None)
94
+ or self.versions.head_schemas_package
95
+ )
86
96
  self.versions.head_schemas_package = latest_schemas_package
87
97
  self._latest_schemas_package = cast(ModuleType, latest_schemas_package)
88
98
 
@@ -138,10 +148,12 @@ class Cadwyn(FastAPI):
138
148
  "responses": responses,
139
149
  "generate_unique_id_function": generate_unique_id_function,
140
150
  }
141
- self.router: _RootHeaderAPIRouter = _RootHeaderAPIRouter( # pyright: ignore[reportIncompatibleVariableOverride]
142
- **self._kwargs_to_router,
143
- api_version_header_name=api_version_header_name,
144
- api_version_var=self.versions.api_version_var,
151
+ self.router: _RootHeaderAPIRouter = (
152
+ _RootHeaderAPIRouter( # pyright: ignore[reportIncompatibleVariableOverride]
153
+ **self._kwargs_to_router,
154
+ api_version_header_name=api_version_header_name,
155
+ api_version_var=self.versions.api_version_var,
156
+ )
145
157
  )
146
158
 
147
159
  self.docs_url = docs_url
@@ -161,12 +173,16 @@ class Cadwyn(FastAPI):
161
173
  )
162
174
 
163
175
  @property # pragma: no cover
164
- @deprecated("It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead")
176
+ @deprecated(
177
+ "It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead"
178
+ )
165
179
  def latest_schemas_package(self):
166
180
  return self._latest_schemas_package
167
181
 
168
182
  @latest_schemas_package.setter # pragma: no cover
169
- @deprecated("It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead")
183
+ @deprecated(
184
+ "It is going to be deleted in the future. Use VersionBundle.head_schemas_package instead"
185
+ )
170
186
  def latest_schemas_package(self, value: ModuleType | None):
171
187
  self._latest_schemas_package = value
172
188
 
@@ -228,7 +244,7 @@ class Cadwyn(FastAPI):
228
244
  terms_of_service=self.terms_of_service,
229
245
  contact=self.contact,
230
246
  license_info=self.license_info,
231
- routes=self.router.routes,
247
+ routes=self.router.unversioned_routes,
232
248
  tags=self.openapi_tags,
233
249
  servers=self.servers,
234
250
  )
@@ -253,7 +269,9 @@ class Cadwyn(FastAPI):
253
269
  self.swaggers[header_value_str] = openapi
254
270
 
255
271
  async def openapi_jsons(self, req: Request) -> JSONResponse:
256
- version = req.query_params.get("version") or req.headers.get(self.router.api_version_header_name)
272
+ version = req.query_params.get("version") or req.headers.get(
273
+ self.router.api_version_header_name
274
+ )
257
275
  openapi_of_a_version = self.swaggers.get(version)
258
276
  if not openapi_of_a_version:
259
277
  raise HTTPException(
@@ -287,7 +305,9 @@ class Cadwyn(FastAPI):
287
305
  if version:
288
306
  root_path = self._extract_root_path(req)
289
307
  openapi_url = root_path + f"{self.openapi_url}?version={version}"
290
- return get_redoc_html(openapi_url=openapi_url, title=f"{self.title} - ReDoc")
308
+ return get_redoc_html(
309
+ openapi_url=openapi_url, title=f"{self.title} - ReDoc"
310
+ )
291
311
 
292
312
  return self._render_docs_dashboard(req, docs_url=cast(str, self.redoc_url))
293
313
 
@@ -300,7 +320,10 @@ class Cadwyn(FastAPI):
300
320
  "docs.html",
301
321
  {
302
322
  "request": req,
303
- "table": {version: f"{base_url}{docs_url}?version={version}" for version in sorted(self.swaggers)},
323
+ "table": {
324
+ version: f"{base_url}{docs_url}?version={version}"
325
+ for version in sorted(self.swaggers)
326
+ },
304
327
  },
305
328
  )
306
329
 
@@ -317,7 +340,9 @@ class Cadwyn(FastAPI):
317
340
  raise ValueError("header_value should be in ISO 8601 format") from e
318
341
 
319
342
  if header_value_as_dt not in self.router.versioned_routers: # pragma: no branch
320
- self.router.versioned_routers[header_value_as_dt] = APIRouter(**self._kwargs_to_router)
343
+ self.router.versioned_routers[header_value_as_dt] = APIRouter(
344
+ **self._kwargs_to_router
345
+ )
321
346
  if self.openapi_url is not None: # pragma: no branch
322
347
  self.router.versioned_routers[header_value_as_dt].add_route(
323
348
  path=self.openapi_url,
@@ -325,12 +350,27 @@ class Cadwyn(FastAPI):
325
350
  include_in_schema=False,
326
351
  )
327
352
 
353
+ version_router = self.router.versioned_routers[header_value_as_dt]
328
354
  added_routes: list[BaseRoute] = []
355
+ added_route_count = 0
329
356
  for router in (first_router, *other_routers):
330
357
  self.router.versioned_routers[header_value_as_dt].include_router(
331
358
  router,
332
- dependencies=[Depends(_get_api_version_dependency(self.router.api_version_header_name, header_value))],
359
+ dependencies=[
360
+ Depends(
361
+ _get_api_version_dependency(
362
+ self.router.api_version_header_name, header_value
363
+ )
364
+ )
365
+ ],
333
366
  )
367
+ added_route_count += len(router.routes)
368
+
369
+ added_routes = (
370
+ version_router.routes[-added_route_count :]
371
+ )
372
+ self.router.routes.extend(added_routes)
373
+
334
374
  self.enrich_swagger()
335
375
  return added_routes
336
376
 
cadwyn/routing.py CHANGED
@@ -9,7 +9,7 @@ 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
15
  from .route_generation import InternalRepresentationOf, generate_versioned_routers # pyright: ignore[reportDeprecated]
@@ -46,6 +46,7 @@ class _RootHeaderAPIRouter(APIRouter):
46
46
  self.versioned_routers: dict[date, APIRouter] = {}
47
47
  self.api_version_header_name = api_version_header_name.lower()
48
48
  self.api_version_var = api_version_var
49
+ self.unversioned_routes: list[Route] = []
49
50
 
50
51
  @cached_property
51
52
  def sorted_versions(self):
@@ -94,13 +95,17 @@ class _RootHeaderAPIRouter(APIRouter):
94
95
  # if header_value is None, then it's an unversioned request and we need to use the unversioned routes
95
96
  # if there will be a value, we search for the most suitable version
96
97
  if not header_value:
97
- routes = self.routes
98
+ routes = self.unversioned_routes
98
99
  elif header_value in self.versioned_routers:
99
100
  routes = self.versioned_routers[header_value].routes
100
101
  else:
101
102
  routes = self.pick_version(request_header_value=header_value)
102
103
  await self.process_request(scope=scope, receive=receive, send=send, routes=routes)
103
104
 
105
+ def add_api_route(self, *args, **kwargs):
106
+ super().add_api_route(*args, **kwargs)
107
+ self.unversioned_routes.append(self.routes[-1])
108
+
104
109
  async def process_request(self, scope: Scope, receive: Receive, send: Send, routes: Sequence[BaseRoute]) -> None:
105
110
  """
106
111
  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.3a1
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=nreLcBP8CSc22JLfRWjPP1Ngt4xawTwgl0qTil4d_Hc,17983
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=38-NhKXGQkUlz3zKnfwIIw9QSYz2h2nXEaSMlBkXzoU,6507
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.3a1.dist-info/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
35
+ cadwyn-3.15.3a1.dist-info/METADATA,sha256=aaXSojcoje-vXvK6fGtFVPOJIlDkqjrMWozw2J9md28,4399
36
+ cadwyn-3.15.3a1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
37
+ cadwyn-3.15.3a1.dist-info/entry_points.txt,sha256=eO05hLn9GoRzzpwT9GONPmXKsonjuMNssM2D2WHWKGk,46
38
+ cadwyn-3.15.3a1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any