cadwyn 3.14.0__tar.gz → 3.15.1__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.14.0 → cadwyn-3.15.1}/PKG-INFO +3 -3
- {cadwyn-3.14.0 → cadwyn-3.15.1}/README.md +2 -2
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/__init__.py +5 -1
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/__main__.py +1 -1
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/applications.py +47 -91
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/route_generation.py +4 -1
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/routing.py +1 -1
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/versions.py +1 -1
- {cadwyn-3.14.0 → cadwyn-3.15.1}/pyproject.toml +9 -3
- {cadwyn-3.14.0 → cadwyn-3.15.1}/LICENSE +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/_asts.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/_compat.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/_package_utils.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/_utils.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/README.md +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/__init__.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_common.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_main.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_plugins/__init__.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_plugins/class_migrations.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_plugins/class_rebuilding.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_plugins/class_renaming.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_plugins/import_auto_adding.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/codegen/_plugins/module_migrations.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/exceptions.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/main.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/middleware.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/py.typed +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/static/__init__.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/static/docs.html +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/common.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/data.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/endpoints.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/enums.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/modules.py +0 -0
- {cadwyn-3.14.0 → cadwyn-3.15.1}/cadwyn/structure/schemas.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cadwyn
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.15.1
|
|
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
|
|
@@ -54,8 +54,8 @@ Production-ready community-driven modern [Stripe-like](https://stripe.com/blog/a
|
|
|
54
54
|
<a href="https://github.com/zmievsa/cadwyn/actions/workflows/ci.yaml?branch=main&event=push" target="_blank">
|
|
55
55
|
<img src="https://github.com/zmievsa/cadwyn/actions/workflows/ci.yaml/badge.svg?branch=main&event=push" alt="Test">
|
|
56
56
|
</a>
|
|
57
|
-
<a href="https://codecov.io/gh/
|
|
58
|
-
<img src="https://img.shields.io/codecov/c/github/
|
|
57
|
+
<a href="https://codecov.io/gh/zmievsa/cadwyn" target="_blank">
|
|
58
|
+
<img src="https://img.shields.io/codecov/c/github/zmievsa/cadwyn?color=%2334D058&logo=codecov" alt="Coverage">
|
|
59
59
|
</a>
|
|
60
60
|
<a href="https://pypi.org/project/cadwyn/" target="_blank">
|
|
61
61
|
<img alt="PyPI" src="https://img.shields.io/pypi/v/cadwyn?color=%2334D058&logo=pypi&label=PyPI package" alt="Package version">
|
|
@@ -8,8 +8,8 @@ Production-ready community-driven modern [Stripe-like](https://stripe.com/blog/a
|
|
|
8
8
|
<a href="https://github.com/zmievsa/cadwyn/actions/workflows/ci.yaml?branch=main&event=push" target="_blank">
|
|
9
9
|
<img src="https://github.com/zmievsa/cadwyn/actions/workflows/ci.yaml/badge.svg?branch=main&event=push" alt="Test">
|
|
10
10
|
</a>
|
|
11
|
-
<a href="https://codecov.io/gh/
|
|
12
|
-
<img src="https://img.shields.io/codecov/c/github/
|
|
11
|
+
<a href="https://codecov.io/gh/zmievsa/cadwyn" target="_blank">
|
|
12
|
+
<img src="https://img.shields.io/codecov/c/github/zmievsa/cadwyn?color=%2334D058&logo=codecov" alt="Coverage">
|
|
13
13
|
</a>
|
|
14
14
|
<a href="https://pypi.org/project/cadwyn/" target="_blank">
|
|
15
15
|
<img alt="PyPI" src="https://img.shields.io/pypi/v/cadwyn?color=%2334D058&logo=pypi&label=PyPI package" alt="Package version">
|
|
@@ -2,7 +2,11 @@ import importlib.metadata
|
|
|
2
2
|
|
|
3
3
|
from .applications import Cadwyn
|
|
4
4
|
from .codegen import generate_code_for_versioned_packages
|
|
5
|
-
from .route_generation import
|
|
5
|
+
from .route_generation import (
|
|
6
|
+
InternalRepresentationOf, # pyright: ignore[reportDeprecated]
|
|
7
|
+
VersionedAPIRouter,
|
|
8
|
+
generate_versioned_routers,
|
|
9
|
+
)
|
|
6
10
|
from .structure import VersionBundle
|
|
7
11
|
|
|
8
12
|
__version__ = importlib.metadata.version("cadwyn")
|
|
@@ -60,7 +60,7 @@ def deprecated_generate_versioned_packages(
|
|
|
60
60
|
possibly_version_bundle = getattr(version_bundle_module, version_bundle_variable_name)
|
|
61
61
|
version_bundle = _get_version_bundle(possibly_version_bundle)
|
|
62
62
|
|
|
63
|
-
return generate_code_for_versioned_packages(
|
|
63
|
+
return generate_code_for_versioned_packages( # pyright: ignore[reportDeprecated]
|
|
64
64
|
template_package,
|
|
65
65
|
version_bundle,
|
|
66
66
|
ignore_coverage_for_latest_aliases=ignore_coverage_for_latest_aliases,
|
|
@@ -7,9 +7,14 @@ from typing import Any, cast
|
|
|
7
7
|
|
|
8
8
|
from fastapi import APIRouter, FastAPI, HTTPException, routing
|
|
9
9
|
from fastapi.datastructures import Default
|
|
10
|
-
from fastapi.openapi.docs import
|
|
10
|
+
from fastapi.openapi.docs import (
|
|
11
|
+
get_redoc_html,
|
|
12
|
+
get_swagger_ui_html,
|
|
13
|
+
get_swagger_ui_oauth2_redirect_html,
|
|
14
|
+
)
|
|
11
15
|
from fastapi.openapi.utils import get_openapi
|
|
12
16
|
from fastapi.params import Depends
|
|
17
|
+
from fastapi.responses import HTMLResponse
|
|
13
18
|
from fastapi.templating import Jinja2Templates
|
|
14
19
|
from fastapi.utils import generate_unique_id
|
|
15
20
|
from starlette.middleware import Middleware
|
|
@@ -19,7 +24,6 @@ from starlette.routing import BaseRoute, Route
|
|
|
19
24
|
from starlette.types import Lifespan
|
|
20
25
|
from typing_extensions import Self, deprecated
|
|
21
26
|
|
|
22
|
-
from cadwyn._utils import same_definition_as_in
|
|
23
27
|
from cadwyn.middleware import HeaderVersioningMiddleware, _get_api_version_dependency
|
|
24
28
|
from cadwyn.route_generation import generate_versioned_routers
|
|
25
29
|
from cadwyn.routing import _RootHeaderAPIRouter
|
|
@@ -139,6 +143,8 @@ class Cadwyn(FastAPI):
|
|
|
139
143
|
api_version_var=self.versions.api_version_var,
|
|
140
144
|
)
|
|
141
145
|
|
|
146
|
+
self.add_event_handler("startup", self.enrich_swagger)
|
|
147
|
+
|
|
142
148
|
self.docs_url = docs_url
|
|
143
149
|
self.redoc_url = redoc_url
|
|
144
150
|
self.openapi_url = openapi_url
|
|
@@ -178,6 +184,18 @@ class Cadwyn(FastAPI):
|
|
|
178
184
|
endpoint=self.swagger_dashboard,
|
|
179
185
|
include_in_schema=False,
|
|
180
186
|
)
|
|
187
|
+
if self.swagger_ui_oauth2_redirect_url:
|
|
188
|
+
|
|
189
|
+
async def swagger_ui_redirect(req: Request) -> HTMLResponse:
|
|
190
|
+
return (
|
|
191
|
+
get_swagger_ui_oauth2_redirect_html() # pragma: no cover # unimportant right now but # TODO
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
self.add_route(
|
|
195
|
+
self.swagger_ui_oauth2_redirect_url,
|
|
196
|
+
swagger_ui_redirect,
|
|
197
|
+
include_in_schema=False,
|
|
198
|
+
)
|
|
181
199
|
if self.redoc_url is not None:
|
|
182
200
|
unversioned_router.add_route(
|
|
183
201
|
path=self.redoc_url,
|
|
@@ -247,20 +265,38 @@ class Cadwyn(FastAPI):
|
|
|
247
265
|
return JSONResponse(openapi_of_a_version)
|
|
248
266
|
|
|
249
267
|
async def swagger_dashboard(self, req: Request) -> Response:
|
|
250
|
-
|
|
268
|
+
version = req.query_params.get("version")
|
|
251
269
|
|
|
252
|
-
|
|
253
|
-
|
|
270
|
+
if version:
|
|
271
|
+
root_path = self._extract_root_path(req)
|
|
272
|
+
openapi_url = root_path + f"{self.openapi_url}?version={version}"
|
|
273
|
+
oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url
|
|
274
|
+
if oauth2_redirect_url:
|
|
275
|
+
oauth2_redirect_url = root_path + oauth2_redirect_url
|
|
276
|
+
return get_swagger_ui_html(
|
|
277
|
+
openapi_url=openapi_url,
|
|
278
|
+
title=f"{self.title} - Swagger UI",
|
|
279
|
+
oauth2_redirect_url=oauth2_redirect_url,
|
|
280
|
+
init_oauth=self.swagger_ui_init_oauth,
|
|
281
|
+
swagger_ui_parameters=self.swagger_ui_parameters,
|
|
282
|
+
)
|
|
283
|
+
return self._render_docs_dashboard(req, cast(str, self.docs_url))
|
|
254
284
|
|
|
255
|
-
def
|
|
256
|
-
base_url = str(req.base_url).rstrip("/")
|
|
285
|
+
async def redoc_dashboard(self, req: Request) -> Response:
|
|
257
286
|
version = req.query_params.get("version")
|
|
258
287
|
|
|
259
288
|
if version:
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
289
|
+
root_path = self._extract_root_path(req)
|
|
290
|
+
openapi_url = root_path + f"{self.openapi_url}?version={version}"
|
|
291
|
+
return get_redoc_html(openapi_url=openapi_url, title=f"{self.title} - ReDoc")
|
|
292
|
+
|
|
293
|
+
return self._render_docs_dashboard(req, docs_url=cast(str, self.redoc_url))
|
|
294
|
+
|
|
295
|
+
def _extract_root_path(self, req: Request):
|
|
296
|
+
return req.scope.get("root_path", "").rstrip("/")
|
|
297
|
+
|
|
298
|
+
def _render_docs_dashboard(self, req: Request, docs_url: str):
|
|
299
|
+
base_url = str(req.base_url).rstrip("/")
|
|
264
300
|
return self._templates.TemplateResponse(
|
|
265
301
|
"docs.html",
|
|
266
302
|
{
|
|
@@ -297,91 +333,11 @@ class Cadwyn(FastAPI):
|
|
|
297
333
|
dependencies=[Depends(_get_api_version_dependency(self.router.api_version_header_name, header_value))],
|
|
298
334
|
)
|
|
299
335
|
|
|
300
|
-
self.enrich_swagger()
|
|
301
336
|
return added_routes
|
|
302
337
|
|
|
303
|
-
@same_definition_as_in(FastAPI.include_router)
|
|
304
|
-
def include_router(self, *args: Any, **kwargs: Any):
|
|
305
|
-
route = super().include_router(*args, **kwargs)
|
|
306
|
-
self.enrich_swagger()
|
|
307
|
-
return route
|
|
308
|
-
|
|
309
|
-
@same_definition_as_in(FastAPI.post)
|
|
310
|
-
def post(self, *args: Any, **kwargs: Any):
|
|
311
|
-
route = super().post(*args, **kwargs)
|
|
312
|
-
self.enrich_swagger()
|
|
313
|
-
return route
|
|
314
|
-
|
|
315
|
-
@same_definition_as_in(FastAPI.get)
|
|
316
|
-
def get(self, *args: Any, **kwargs: Any):
|
|
317
|
-
route = super().get(*args, **kwargs)
|
|
318
|
-
self.enrich_swagger()
|
|
319
|
-
return route
|
|
320
|
-
|
|
321
|
-
@same_definition_as_in(FastAPI.patch)
|
|
322
|
-
def patch(self, *args: Any, **kwargs: Any):
|
|
323
|
-
route = super().patch(*args, **kwargs)
|
|
324
|
-
self.enrich_swagger()
|
|
325
|
-
return route
|
|
326
|
-
|
|
327
|
-
@same_definition_as_in(FastAPI.delete)
|
|
328
|
-
def delete(self, *args: Any, **kwargs: Any):
|
|
329
|
-
route = super().delete(*args, **kwargs)
|
|
330
|
-
self.enrich_swagger()
|
|
331
|
-
return route
|
|
332
|
-
|
|
333
|
-
@same_definition_as_in(FastAPI.put)
|
|
334
|
-
def put(self, *args: Any, **kwargs: Any):
|
|
335
|
-
route = super().put(*args, **kwargs)
|
|
336
|
-
self.enrich_swagger()
|
|
337
|
-
return route
|
|
338
|
-
|
|
339
|
-
@same_definition_as_in(FastAPI.trace)
|
|
340
|
-
def trace(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
341
|
-
route = super().trace(*args, **kwargs)
|
|
342
|
-
self.enrich_swagger()
|
|
343
|
-
return route
|
|
344
|
-
|
|
345
|
-
@same_definition_as_in(FastAPI.options)
|
|
346
|
-
def options(self, *args: Any, **kwargs: Any):
|
|
347
|
-
route = super().options(*args, **kwargs)
|
|
348
|
-
self.enrich_swagger()
|
|
349
|
-
return route
|
|
350
|
-
|
|
351
|
-
@same_definition_as_in(FastAPI.head)
|
|
352
|
-
def head(self, *args: Any, **kwargs: Any):
|
|
353
|
-
route = super().head(*args, **kwargs)
|
|
354
|
-
self.enrich_swagger()
|
|
355
|
-
return route
|
|
356
|
-
|
|
357
|
-
@same_definition_as_in(FastAPI.add_api_route)
|
|
358
|
-
def add_api_route(self, *args: Any, **kwargs: Any):
|
|
359
|
-
route = super().add_api_route(*args, **kwargs)
|
|
360
|
-
self.enrich_swagger()
|
|
361
|
-
return route
|
|
362
|
-
|
|
363
|
-
@same_definition_as_in(FastAPI.api_route)
|
|
364
|
-
def api_route(self, *args: Any, **kwargs: Any):
|
|
365
|
-
route = super().api_route(*args, **kwargs)
|
|
366
|
-
self.enrich_swagger()
|
|
367
|
-
return route
|
|
368
|
-
|
|
369
|
-
@same_definition_as_in(FastAPI.add_api_websocket_route)
|
|
370
|
-
def add_api_websocket_route(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
371
|
-
route = super().add_api_websocket_route(*args, **kwargs)
|
|
372
|
-
self.enrich_swagger()
|
|
373
|
-
return route
|
|
374
|
-
|
|
375
|
-
@same_definition_as_in(FastAPI.websocket)
|
|
376
|
-
def websocket(self, *args: Any, **kwargs: Any): # pragma: no cover
|
|
377
|
-
route = super().websocket(*args, **kwargs)
|
|
378
|
-
self.enrich_swagger()
|
|
379
|
-
return route
|
|
380
|
-
|
|
381
338
|
def add_unversioned_routers(self, *routers: APIRouter):
|
|
382
339
|
for router in routers:
|
|
383
340
|
self.router.include_router(router)
|
|
384
|
-
self.enrich_swagger()
|
|
385
341
|
|
|
386
342
|
@deprecated("Use add add_unversioned_routers instead")
|
|
387
343
|
def add_unversioned_routes(self, *routes: Route):
|
|
@@ -452,7 +452,10 @@ def _extract_internal_request_schemas_from_router(
|
|
|
452
452
|
for key, annotation in annotations.items():
|
|
453
453
|
if isinstance(annotation, type(Annotated[int, int])):
|
|
454
454
|
args = get_args(annotation)
|
|
455
|
-
if isinstance(args[1], type) and issubclass(
|
|
455
|
+
if isinstance(args[1], type) and issubclass( # pragma: no branch
|
|
456
|
+
args[1],
|
|
457
|
+
InternalRepresentationOf, # pyright: ignore[reportDeprecated]
|
|
458
|
+
):
|
|
456
459
|
internal_schema = args[0]
|
|
457
460
|
original_schema = args[1].mro()[2]
|
|
458
461
|
schema_to_internal_request_body_representation[original_schema] = internal_schema
|
|
@@ -12,7 +12,7 @@ from starlette.responses import RedirectResponse
|
|
|
12
12
|
from starlette.routing import BaseRoute, Match
|
|
13
13
|
from starlette.types import Receive, Scope, Send
|
|
14
14
|
|
|
15
|
-
from .route_generation import InternalRepresentationOf, generate_versioned_routers
|
|
15
|
+
from .route_generation import InternalRepresentationOf, generate_versioned_routers # pyright: ignore[reportDeprecated]
|
|
16
16
|
|
|
17
17
|
# TODO: Remove this in a major version. This is only here for backwards compatibility
|
|
18
18
|
__all__ = ["InternalRepresentationOf", "generate_versioned_routers"]
|
|
@@ -420,7 +420,7 @@ class VersionBundle:
|
|
|
420
420
|
versioned_response_model: type[BaseModel] = get_another_version_of_cls(
|
|
421
421
|
latest_response_model, version_dir, self.versioned_directories_with_head
|
|
422
422
|
)
|
|
423
|
-
return versioned_response_model.parse_obj(migrated_response.body)
|
|
423
|
+
return versioned_response_model.parse_obj(migrated_response.body) # pyright: ignore[reportDeprecated]
|
|
424
424
|
|
|
425
425
|
def _get_closest_lesser_version(self, version: VersionDate):
|
|
426
426
|
for defined_version in self.version_dates:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "cadwyn"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.15.1"
|
|
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"
|
|
@@ -55,7 +55,7 @@ typing-extensions = "*"
|
|
|
55
55
|
fastapi = ">=0.110.0"
|
|
56
56
|
starlette = ">=0.36.3"
|
|
57
57
|
pydantic = ">=1.0.0"
|
|
58
|
-
typer = {version = ">=0.7.0", optional = true}
|
|
58
|
+
typer = { version = ">=0.7.0", optional = true }
|
|
59
59
|
better-ast-comments = "~1.2.1"
|
|
60
60
|
jinja2 = ">=3.1.2"
|
|
61
61
|
issubclass = "^0.1.2"
|
|
@@ -104,7 +104,13 @@ exclude_lines = [
|
|
|
104
104
|
"__rich_repr__",
|
|
105
105
|
"__repr__",
|
|
106
106
|
]
|
|
107
|
-
omit = [
|
|
107
|
+
omit = [
|
|
108
|
+
"./docs/plugin.py",
|
|
109
|
+
"./site/plugin.py",
|
|
110
|
+
"./tests/_data/_temp/**/*",
|
|
111
|
+
"tests/tutorial/data/**/*",
|
|
112
|
+
"scripts/*.py",
|
|
113
|
+
]
|
|
108
114
|
|
|
109
115
|
[tool.pyright]
|
|
110
116
|
reportMissingImports = true
|
|
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
|