cadwyn 5.1.1__py3-none-any.whl → 5.1.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/__init__.py +2 -0
- cadwyn/dependencies.py +5 -0
- cadwyn/exceptions.py +1 -2
- cadwyn/schema_generation.py +33 -1
- cadwyn/structure/versions.py +9 -1
- {cadwyn-5.1.1.dist-info → cadwyn-5.1.3.dist-info}/METADATA +2 -2
- {cadwyn-5.1.1.dist-info → cadwyn-5.1.3.dist-info}/RECORD +10 -9
- {cadwyn-5.1.1.dist-info → cadwyn-5.1.3.dist-info}/WHEEL +0 -0
- {cadwyn-5.1.1.dist-info → cadwyn-5.1.3.dist-info}/entry_points.txt +0 -0
- {cadwyn-5.1.1.dist-info → cadwyn-5.1.3.dist-info}/licenses/LICENSE +0 -0
cadwyn/__init__.py
CHANGED
|
@@ -2,6 +2,7 @@ import importlib.metadata
|
|
|
2
2
|
|
|
3
3
|
from .applications import Cadwyn
|
|
4
4
|
from .changelogs import hidden
|
|
5
|
+
from .dependencies import current_dependency_solver
|
|
5
6
|
from .route_generation import VersionedAPIRouter, generate_versioned_routers
|
|
6
7
|
from .schema_generation import generate_versioned_models, migrate_response_body
|
|
7
8
|
from .structure import (
|
|
@@ -32,6 +33,7 @@ __all__ = [
|
|
|
32
33
|
"VersionedAPIRouter",
|
|
33
34
|
"convert_request_to_next_version_for",
|
|
34
35
|
"convert_response_to_previous_version_for",
|
|
36
|
+
"current_dependency_solver",
|
|
35
37
|
"endpoint",
|
|
36
38
|
"enum",
|
|
37
39
|
"generate_versioned_models",
|
cadwyn/dependencies.py
ADDED
cadwyn/exceptions.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import json
|
|
2
1
|
from typing import Any
|
|
3
2
|
|
|
4
3
|
from fastapi.routing import APIRoute
|
|
@@ -21,7 +20,7 @@ class CadwynHeadRequestValidationError(CadwynError):
|
|
|
21
20
|
f"We failed to migrate the request with version={self.version}. "
|
|
22
21
|
"This means that there is some error in your migrations or schema structure that makes it impossible "
|
|
23
22
|
"to migrate the request of that version to latest.\n"
|
|
24
|
-
f"body={self.body}\n\nerrors={
|
|
23
|
+
f"body={self.body}\n\nerrors={self.errors}"
|
|
25
24
|
)
|
|
26
25
|
|
|
27
26
|
|
cadwyn/schema_generation.py
CHANGED
|
@@ -20,6 +20,7 @@ import pydantic
|
|
|
20
20
|
import pydantic._internal._decorators
|
|
21
21
|
import typing_extensions
|
|
22
22
|
from fastapi import Response
|
|
23
|
+
from fastapi.dependencies.utils import is_async_gen_callable, is_coroutine_callable, is_gen_callable
|
|
23
24
|
from fastapi.routing import APIRoute
|
|
24
25
|
from pydantic import BaseModel, Field, RootModel
|
|
25
26
|
from pydantic._internal import _decorators
|
|
@@ -39,6 +40,7 @@ from typing_extensions import (
|
|
|
39
40
|
NewType,
|
|
40
41
|
Self,
|
|
41
42
|
TypeAlias,
|
|
43
|
+
TypeAliasType,
|
|
42
44
|
TypeVar,
|
|
43
45
|
_AnnotatedAlias,
|
|
44
46
|
assert_never,
|
|
@@ -77,6 +79,7 @@ from cadwyn.structure.versions import _CADWYN_REQUEST_PARAM_NAME, _CADWYN_RESPON
|
|
|
77
79
|
if TYPE_CHECKING:
|
|
78
80
|
from cadwyn.structure.versions import HeadVersion, Version, VersionBundle
|
|
79
81
|
|
|
82
|
+
|
|
80
83
|
if sys.version_info >= (3, 10):
|
|
81
84
|
from typing import _BaseGenericAlias # pyright: ignore[reportAttributeAccessIssue]
|
|
82
85
|
else:
|
|
@@ -98,6 +101,7 @@ PYDANTIC_DECORATOR_TYPE_TO_DECORATOR_MAP = {
|
|
|
98
101
|
ModelSerializerDecoratorInfo: pydantic.model_serializer,
|
|
99
102
|
ComputedFieldInfo: pydantic.computed_field,
|
|
100
103
|
}
|
|
104
|
+
_PYDANTIC_ALL_EXPORTED_NAMES = set(pydantic.__all__)
|
|
101
105
|
|
|
102
106
|
|
|
103
107
|
VALIDATOR_CONFIG_KEY = "__validators__"
|
|
@@ -486,6 +490,7 @@ class _CallableWrapper:
|
|
|
486
490
|
self._original_callable = original_callable
|
|
487
491
|
if not is_regular_function(original_callable):
|
|
488
492
|
original_callable = original_callable.__call__
|
|
493
|
+
|
|
489
494
|
functools.update_wrapper(self, original_callable)
|
|
490
495
|
|
|
491
496
|
@property
|
|
@@ -510,6 +515,17 @@ class _AsyncCallableWrapper(_CallableWrapper):
|
|
|
510
515
|
return await self._original_callable(*args, **kwargs)
|
|
511
516
|
|
|
512
517
|
|
|
518
|
+
class _GeneratorCallableWrapper(_CallableWrapper):
|
|
519
|
+
def __call__(self, *args: Any, **kwargs: Any):
|
|
520
|
+
yield from self._original_callable(*args, **kwargs)
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
class _AsyncGeneratorCallableWrapper(_CallableWrapper):
|
|
524
|
+
async def __call__(self, *args: Any, **kwargs: Any):
|
|
525
|
+
async for value in self._original_callable(*args, **kwargs):
|
|
526
|
+
yield value
|
|
527
|
+
|
|
528
|
+
|
|
513
529
|
@final
|
|
514
530
|
class _AnnotationTransformer:
|
|
515
531
|
def __init__(self, generator: "SchemaGenerator") -> None:
|
|
@@ -566,6 +582,17 @@ class _AnnotationTransformer:
|
|
|
566
582
|
def _change_version_of_a_non_container_annotation(self, annotation: Any) -> Any:
|
|
567
583
|
if isinstance(annotation, (_BaseGenericAlias, types.GenericAlias)):
|
|
568
584
|
return get_origin(annotation)[tuple(self.change_version_of_annotation(arg) for arg in get_args(annotation))]
|
|
585
|
+
elif isinstance(annotation, TypeAliasType):
|
|
586
|
+
if (
|
|
587
|
+
annotation.__module__ is not None and (annotation.__module__.startswith("pydantic."))
|
|
588
|
+
) or annotation.__name__ in _PYDANTIC_ALL_EXPORTED_NAMES:
|
|
589
|
+
return annotation
|
|
590
|
+
else:
|
|
591
|
+
return TypeAliasType( # pyright: ignore[reportGeneralTypeIssues]
|
|
592
|
+
name=annotation.__name__,
|
|
593
|
+
value=self.change_version_of_annotation(annotation.__value__),
|
|
594
|
+
type_params=self.change_version_of_annotation(annotation.__type_params__),
|
|
595
|
+
)
|
|
569
596
|
elif isinstance(annotation, fastapi.params.Security):
|
|
570
597
|
return fastapi.params.Security(
|
|
571
598
|
self.change_version_of_annotation(annotation.dependency),
|
|
@@ -690,8 +717,12 @@ class _AnnotationTransformer:
|
|
|
690
717
|
actual_call = call.__call__
|
|
691
718
|
else:
|
|
692
719
|
actual_call = call
|
|
693
|
-
if
|
|
720
|
+
if is_async_gen_callable(actual_call):
|
|
721
|
+
return _AsyncGeneratorCallableWrapper(call)
|
|
722
|
+
elif is_coroutine_callable(actual_call):
|
|
694
723
|
return _AsyncCallableWrapper(call)
|
|
724
|
+
elif is_gen_callable(actual_call):
|
|
725
|
+
return _GeneratorCallableWrapper(call)
|
|
695
726
|
else:
|
|
696
727
|
return _CallableWrapper(call)
|
|
697
728
|
|
|
@@ -1061,6 +1092,7 @@ class _EnumWrapper(Generic[_T_ENUM]):
|
|
|
1061
1092
|
initialization_namespace = self._get_initialization_namespace_for_enum(self.cls) | raw_member_map
|
|
1062
1093
|
for attr_name, attr in initialization_namespace.items():
|
|
1063
1094
|
enum_dict[attr_name] = attr
|
|
1095
|
+
enum_dict["__doc__"] = self.cls.__doc__
|
|
1064
1096
|
model_copy = cast(type[_T_ENUM], type(self.name, self.cls.__bases__, enum_dict))
|
|
1065
1097
|
model_copy.__cadwyn_original_model__ = self.cls # pyright: ignore[reportAttributeAccessIssue]
|
|
1066
1098
|
return model_copy
|
cadwyn/structure/versions.py
CHANGED
|
@@ -23,7 +23,7 @@ from fastapi.routing import APIRoute, _prepare_response_content
|
|
|
23
23
|
from pydantic import BaseModel
|
|
24
24
|
from pydantic_core import PydanticUndefined
|
|
25
25
|
from starlette._utils import is_async_callable
|
|
26
|
-
from typing_extensions import Any, ParamSpec, TypeAlias, TypeVar, assert_never, deprecated, get_args
|
|
26
|
+
from typing_extensions import Any, Literal, ParamSpec, TypeAlias, TypeVar, assert_never, deprecated, get_args
|
|
27
27
|
|
|
28
28
|
from cadwyn._utils import classproperty
|
|
29
29
|
from cadwyn.exceptions import (
|
|
@@ -51,6 +51,11 @@ _CADWYN_REQUEST_PARAM_NAME = "cadwyn_request_param"
|
|
|
51
51
|
_CADWYN_RESPONSE_PARAM_NAME = "cadwyn_response_param"
|
|
52
52
|
_P = ParamSpec("_P")
|
|
53
53
|
_R = TypeVar("_R")
|
|
54
|
+
_CURRENT_DEPENDENCY_SOLVER_OPTIONS = Literal["cadwyn", "fastapi"]
|
|
55
|
+
_CURRENT_DEPENDENCY_SOLVER_VAR: ContextVar[_CURRENT_DEPENDENCY_SOLVER_OPTIONS] = ContextVar(
|
|
56
|
+
"cadwyn_dependencies_dry_run"
|
|
57
|
+
)
|
|
58
|
+
|
|
54
59
|
PossibleInstructions: TypeAlias = Union[
|
|
55
60
|
AlterSchemaSubInstruction, AlterEndpointSubInstruction, AlterEnumSubInstruction, SchemaHadInstruction, staticmethod
|
|
56
61
|
]
|
|
@@ -276,6 +281,7 @@ class VersionBundle:
|
|
|
276
281
|
|
|
277
282
|
if api_version_var is None:
|
|
278
283
|
api_version_var = ContextVar("cadwyn_api_version")
|
|
284
|
+
|
|
279
285
|
self.version_values = tuple(version.value for version in self.versions)
|
|
280
286
|
self.reversed_version_values = tuple(reversed(self.version_values))
|
|
281
287
|
self.api_version_var = api_version_var
|
|
@@ -379,6 +385,8 @@ class VersionBundle:
|
|
|
379
385
|
instruction(request_info)
|
|
380
386
|
request.scope["headers"] = tuple((key.encode(), value.encode()) for key, value in request_info.headers.items())
|
|
381
387
|
del request._headers
|
|
388
|
+
# This gives us the ability to tell the user whether cadwyn is running its dependencies or FastAPI
|
|
389
|
+
_CURRENT_DEPENDENCY_SOLVER_VAR.set("cadwyn")
|
|
382
390
|
# Remember this: if len(body_params) == 1, then route.body_schema == route.dependant.body_params[0]
|
|
383
391
|
result = await solve_dependencies(
|
|
384
392
|
request=request,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cadwyn
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.3
|
|
4
4
|
Summary: Production-ready community-driven modern Stripe-like API versioning in FastAPI
|
|
5
5
|
Project-URL: Source code, https://github.com/zmievsa/cadwyn
|
|
6
6
|
Project-URL: Documentation, https://docs.cadwyn.dev
|
|
@@ -35,7 +35,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
35
35
|
Classifier: Typing :: Typed
|
|
36
36
|
Requires-Python: >=3.9
|
|
37
37
|
Requires-Dist: backports-strenum<2,>=1.3.1; python_version < '3.11'
|
|
38
|
-
Requires-Dist: fastapi>=0.112.
|
|
38
|
+
Requires-Dist: fastapi>=0.112.4
|
|
39
39
|
Requires-Dist: issubclass>=0.1.2
|
|
40
40
|
Requires-Dist: jinja2>=3.1.2
|
|
41
41
|
Requires-Dist: pydantic>=2.0.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
cadwyn/__init__.py,sha256=
|
|
1
|
+
cadwyn/__init__.py,sha256=uXmQDTDNA5BeRlLFn0cmIo6ohXvEApg2FSl2sFb8frw,1120
|
|
2
2
|
cadwyn/__main__.py,sha256=fGoKJPNVueqqXW4rqwmRUBBMoDGeLEyATdT-rel5Pvs,2449
|
|
3
3
|
cadwyn/_asts.py,sha256=QvqZmDdwH8U-Ocpj9vYR6MRrIANF8ugk9oZgAo76qLs,5223
|
|
4
4
|
cadwyn/_importer.py,sha256=QV6HqODCG9K2oL4Vc15fAqL2-plMvUWw_cgaj4Ln4C8,1075
|
|
@@ -6,12 +6,13 @@ cadwyn/_render.py,sha256=7jb32Cnbf6xJicYBGRuhGz4U5LUzo8InZbf-gENgnEw,5537
|
|
|
6
6
|
cadwyn/_utils.py,sha256=q_mTtMKTNTDzqCza67XST-jaPSfuTgnFLmOe0dlGeYY,2295
|
|
7
7
|
cadwyn/applications.py,sha256=YyESoMwQMq9jxqai6lNrsL0BAKxjTKW5lm3Se_U81j4,20391
|
|
8
8
|
cadwyn/changelogs.py,sha256=aBTlsZ8PQpw9t4sSyezNTYDs6CMPtzIGulgAHA1ELPs,19622
|
|
9
|
-
cadwyn/
|
|
9
|
+
cadwyn/dependencies.py,sha256=9JihGg7MPbP0oBFRWebvIzhh6B-oYqd1EYNjB-OZqpw,241
|
|
10
|
+
cadwyn/exceptions.py,sha256=8D1G7ewLrMF5jq7leald1g0ulcH9zQl8ufEK3b7HHAE,1749
|
|
10
11
|
cadwyn/middleware.py,sha256=jtcysj66Fck_3EteK0zLJCOTMms3g6avi3U8lV-roQI,4316
|
|
11
12
|
cadwyn/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
13
|
cadwyn/route_generation.py,sha256=e7mnVqtvTx1Oh_khmrM0dAowhVUOO1K4vaVVEGgXgrY,25230
|
|
13
14
|
cadwyn/routing.py,sha256=EkV38cDQFAtR1M_fGWeq81lYaSPuDK4Pr8fjTTJVZvY,6912
|
|
14
|
-
cadwyn/schema_generation.py,sha256=
|
|
15
|
+
cadwyn/schema_generation.py,sha256=QK_G-G56S1brGTSpEGEE77tbifSi7IzwNK1oiVfMkPA,46850
|
|
15
16
|
cadwyn/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
17
|
cadwyn/static/docs.html,sha256=WNm5ANJVy51TcIUFOaqKf1Z8eF86CC85TTHPxACtkzw,3455
|
|
17
18
|
cadwyn/structure/__init__.py,sha256=Wgvjdq3vfl9Yhe-BkcFGAMi_Co11YOfTmJQqgF5Gzx4,655
|
|
@@ -20,9 +21,9 @@ cadwyn/structure/data.py,sha256=NWURVnP_84VI2ugp9ppo0Ofyve3pVYjymF9K82Jh-SA,7791
|
|
|
20
21
|
cadwyn/structure/endpoints.py,sha256=zUgzglNhBPnmWdJ03A8pFT4zPs_lj8nQ7c7Uo2d-ejU,6246
|
|
21
22
|
cadwyn/structure/enums.py,sha256=4FCc9aniLE3VuWAVIacrNP_FWxTIUm9JkeeHA_zZdwQ,1254
|
|
22
23
|
cadwyn/structure/schemas.py,sha256=80AUbko1cksXh7qPBmnknDFLK52xr4kw9HfHeXqcw1I,10813
|
|
23
|
-
cadwyn/structure/versions.py,sha256=
|
|
24
|
-
cadwyn-5.1.
|
|
25
|
-
cadwyn-5.1.
|
|
26
|
-
cadwyn-5.1.
|
|
27
|
-
cadwyn-5.1.
|
|
28
|
-
cadwyn-5.1.
|
|
24
|
+
cadwyn/structure/versions.py,sha256=PrWA2m-81b7LuYqrmaaEr-LhQ54nXz7sSe_-WKb-9g0,34271
|
|
25
|
+
cadwyn-5.1.3.dist-info/METADATA,sha256=0potORxoJReb0o3x-XcCIP1BcASKGUDOJAeW45AggHY,4562
|
|
26
|
+
cadwyn-5.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
27
|
+
cadwyn-5.1.3.dist-info/entry_points.txt,sha256=mGX8wl-Xfhpr5M93SUmkykaqinUaYAvW9rtDSX54gx0,47
|
|
28
|
+
cadwyn-5.1.3.dist-info/licenses/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
|
|
29
|
+
cadwyn-5.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|