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.

Files changed (37) hide show
  1. {cadwyn-3.15.2 → cadwyn-3.15.3}/PKG-INFO +1 -1
  2. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/applications.py +27 -11
  3. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/routing.py +37 -5
  4. {cadwyn-3.15.2 → cadwyn-3.15.3}/pyproject.toml +1 -1
  5. {cadwyn-3.15.2 → cadwyn-3.15.3}/LICENSE +0 -0
  6. {cadwyn-3.15.2 → cadwyn-3.15.3}/README.md +0 -0
  7. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/__init__.py +0 -0
  8. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/__main__.py +0 -0
  9. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_asts.py +0 -0
  10. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_compat.py +0 -0
  11. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_package_utils.py +0 -0
  12. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/_utils.py +0 -0
  13. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/README.md +0 -0
  14. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/__init__.py +0 -0
  15. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_common.py +0 -0
  16. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_main.py +0 -0
  17. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/__init__.py +0 -0
  18. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/class_migrations.py +0 -0
  19. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/class_rebuilding.py +0 -0
  20. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/class_renaming.py +0 -0
  21. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/import_auto_adding.py +0 -0
  22. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/codegen/_plugins/module_migrations.py +0 -0
  23. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/exceptions.py +0 -0
  24. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/main.py +0 -0
  25. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/middleware.py +0 -0
  26. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/py.typed +0 -0
  27. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/route_generation.py +0 -0
  28. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/static/__init__.py +0 -0
  29. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/static/docs.html +0 -0
  30. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/__init__.py +0 -0
  31. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/common.py +0 -0
  32. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/data.py +0 -0
  33. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/endpoints.py +0 -0
  34. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/enums.py +0 -0
  35. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/modules.py +0 -0
  36. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/schemas.py +0 -0
  37. {cadwyn-3.15.2 → cadwyn-3.15.3}/cadwyn/structure/versions.py +0 -0
@@ -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
@@ -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
 
@@ -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
  [tool.poetry]
2
2
  name = "cadwyn"
3
- version = "3.15.2"
3
+ version = "3.15.3"
4
4
  description = "Production-ready community-driven modern Stripe-like API versioning in FastAPI"
5
5
  authors = ["Stanislav Zmiev <zmievsa@gmail.com>"]
6
6
  license = "MIT"
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