cadwyn 5.4.3__py3-none-any.whl → 5.4.5__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/changelogs.py CHANGED
@@ -2,14 +2,8 @@ import copy
2
2
  import sys
3
3
  from enum import auto
4
4
  from logging import getLogger
5
- from typing import Any, Literal, TypeVar, Union, cast, get_args
5
+ from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast, get_args
6
6
 
7
- from fastapi._compat import (
8
- GenerateJsonSchema,
9
- ModelField,
10
- get_compat_model_name_map,
11
- get_definitions,
12
- )
13
7
  from fastapi.openapi.constants import REF_TEMPLATE
14
8
  from fastapi.openapi.utils import (
15
9
  get_fields_from_routes,
@@ -41,6 +35,9 @@ from .structure.schemas import (
41
35
  ValidatorExistedInstruction,
42
36
  )
43
37
 
38
+ if TYPE_CHECKING:
39
+ from fastapi._compat import ModelField
40
+
44
41
  if sys.version_info >= (3, 11): # pragma: no cover
45
42
  from enum import StrEnum
46
43
  else: # pragma: no cover
@@ -120,7 +117,7 @@ def _get_affected_model_names(
120
117
  FieldDidntHaveInstruction,
121
118
  ],
122
119
  generator_from_newer_version: SchemaGenerator,
123
- schemas_from_last_version: list[ModelField],
120
+ schemas_from_last_version: "list[ModelField]",
124
121
  ):
125
122
  changed_model = generator_from_newer_version._get_wrapper_for_model(instruction.schema)
126
123
  annotations = [model.field_info.annotation for model in schemas_from_last_version]
@@ -156,6 +153,13 @@ def _get_all_pydantic_models_from_generic(annotation: Any) -> list[type[BaseMode
156
153
 
157
154
 
158
155
  def _get_openapi_representation_of_a_field(model: type[BaseModel], field_name: str) -> dict:
156
+ from fastapi._compat import (
157
+ GenerateJsonSchema,
158
+ ModelField,
159
+ get_compat_model_name_map,
160
+ get_definitions,
161
+ )
162
+
159
163
  class CadwynDummyModelForRepresentation(BaseModel):
160
164
  my_field: model
161
165
 
@@ -315,7 +319,7 @@ def _convert_version_change_instruction_to_changelog_entry( # noqa: C901
315
319
  version_change: type[VersionChange],
316
320
  generator_from_newer_version: SchemaGenerator,
317
321
  generator_from_older_version: SchemaGenerator,
318
- schemas_from_older_version: list[ModelField],
322
+ schemas_from_older_version: "list[ModelField]",
319
323
  routes_from_newer_version: list[APIRoute],
320
324
  ):
321
325
  if isinstance(instruction, EndpointDidntExistInstruction):
@@ -14,6 +14,7 @@ from functools import cache
14
14
  from typing import (
15
15
  TYPE_CHECKING,
16
16
  Annotated,
17
+ ClassVar,
17
18
  Generic,
18
19
  Union,
19
20
  _BaseGenericAlias, # pyright: ignore[reportAttributeAccessIssue]
@@ -41,6 +42,7 @@ from pydantic._internal._decorators import (
41
42
  from pydantic._internal._known_annotated_metadata import collect_known_metadata
42
43
  from pydantic._internal._typing_extra import try_eval_type as pydantic_try_eval_type
43
44
  from pydantic.fields import ComputedFieldInfo, FieldInfo
45
+ from pydantic_core import PydanticUndefined
44
46
  from typing_extensions import (
45
47
  Any,
46
48
  Doc,
@@ -316,7 +318,7 @@ def _wrap_pydantic_model(model: type[_T_PYDANTIC_MODEL]) -> "_PydanticModelWrapp
316
318
  field_name,
317
319
  )
318
320
  for field_name in model.__annotations__
319
- if field_name in defined_fields
321
+ if field_name in defined_fields and field_name in model.model_fields
320
322
  }
321
323
 
322
324
  main_attributes = fields | validators
@@ -539,7 +541,7 @@ class _AsyncGeneratorCallableWrapper(_CallableWrapper):
539
541
  class _AnnotationTransformer:
540
542
  def __init__(self, generator: "SchemaGenerator") -> None:
541
543
  # This cache is not here for speeding things up. It's for preventing the creation of copies of the same object
542
- # because such copies could produce weird behaviors at runtime, especially if you/fastapi do any comparisons.
544
+ # because such copies could produce weird behaviors at runtime, especially if you/FastAPI do any comparisons.
543
545
  # It's defined here and not on the method because of this: https://youtu.be/sVjtp6tGo0g
544
546
  self.generator = generator
545
547
  # TODO: Rewrite this to memoize
@@ -592,7 +594,12 @@ class _AnnotationTransformer:
592
594
  from typing_inspection.typing_objects import is_any, is_newtype, is_typealiastype
593
595
 
594
596
  if isinstance(annotation, (types.GenericAlias, _BaseGenericAlias)):
595
- return get_origin(annotation)[tuple(self.change_version_of_annotation(arg) for arg in get_args(annotation))]
597
+ origin = get_origin(annotation)
598
+ args = get_args(annotation)
599
+ # Classvar does not support generic tuple arguments
600
+ if origin is ClassVar:
601
+ return ClassVar[self.change_version_of_annotation(args[0])]
602
+ return origin[tuple(self.change_version_of_annotation(arg) for arg in get_args(annotation))]
596
603
  elif is_typealiastype(annotation):
597
604
  if (
598
605
  annotation.__module__ is not None and (annotation.__module__.startswith("pydantic."))
@@ -948,11 +955,20 @@ def _add_field_to_model(
948
955
  f'in "{version_change_name}" but there is already a field with that name.',
949
956
  )
950
957
 
951
- field = PydanticFieldWrapper(
952
- alter_schema_instruction.field, alter_schema_instruction.field.annotation, alter_schema_instruction.name
953
- )
954
- model.fields[alter_schema_instruction.name] = field
955
- model.annotations[alter_schema_instruction.name] = alter_schema_instruction.field.annotation
958
+ # Special handling for ClassVar fields
959
+ if get_origin(alter_schema_instruction.field.annotation) is ClassVar:
960
+ # ClassVar fields should not be in model.fields, only in annotations and other_attributes
961
+ model.annotations[alter_schema_instruction.name] = alter_schema_instruction.field.annotation
962
+ # Set the actual ClassVar value in other_attributes
963
+ if alter_schema_instruction.field.default is not PydanticUndefined:
964
+ model.other_attributes[alter_schema_instruction.name] = alter_schema_instruction.field.default
965
+ else:
966
+ # Regular field handling
967
+ field = PydanticFieldWrapper(
968
+ alter_schema_instruction.field, alter_schema_instruction.field.annotation, alter_schema_instruction.name
969
+ )
970
+ model.fields[alter_schema_instruction.name] = field
971
+ model.annotations[alter_schema_instruction.name] = alter_schema_instruction.field.annotation
956
972
 
957
973
 
958
974
  def _change_field_in_model(
@@ -1085,6 +1101,11 @@ def _delete_field_from_model(model: _PydanticModelWrapper, field_name: str, vers
1085
1101
  validator = model.validators[field_name]
1086
1102
  model.validators[field_name].is_deleted = True
1087
1103
  model.annotations.pop(field_name, None)
1104
+ elif field_name in model.annotations and get_origin(model.annotations[field_name]) is ClassVar:
1105
+ # Handle ClassVar fields - they exist in annotations but not in model.fields
1106
+ model.annotations.pop(field_name)
1107
+ # Also remove the attribute from other_attributes if it exists there
1108
+ model.other_attributes.pop(field_name, None)
1088
1109
  else:
1089
1110
  raise InvalidGenerationInstructionError(
1090
1111
  f'You tried to delete a field "{field_name}" from "{model.name}" '
@@ -18,7 +18,7 @@ HTTP_METHODS = {"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"}
18
18
 
19
19
  @dataclass(**DATACLASS_SLOTS)
20
20
  class EndpointAttributesPayload:
21
- # Fastapi API routes also have "endpoint" and "dependency_overrides_provider" fields.
21
+ # FastAPI API routes also have "endpoint" and "dependency_overrides_provider" fields.
22
22
  # We do not use them because:
23
23
  # 1. "endpoint" must not change -- otherwise this versioning is doomed
24
24
  # 2. "dependency_overrides_provider" is taken from router's attributes
@@ -694,7 +694,7 @@ class VersionBundle:
694
694
  # We use this instead of `.body()` to automatically guess body type and load the correct body, even if it's a form
695
695
  async def _get_body(
696
696
  request: FastapiRequest, body_field: Union[ModelField, None], exit_stack: AsyncExitStack
697
- ): # pragma: no cover # This is from fastapi
697
+ ): # pragma: no cover # This is from FastAPI
698
698
  is_body_form = body_field and isinstance(body_field.field_info, params.Form)
699
699
  try:
700
700
  body: Any = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cadwyn
3
- Version: 5.4.3
3
+ Version: 5.4.5
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
@@ -88,26 +88,3 @@ The [documentation](https://docs.cadwyn.dev) has everything you need to succeed.
88
88
  ## Sponsors
89
89
 
90
90
  These are our gorgeous sponsors. They are using Cadwyn and are sponsoring it through various means. Contact [me](https://github.com/zmievsa) if you would like to become one, too!
91
-
92
- ## Contributors
93
-
94
- <details>
95
-
96
- <summary>Thanks goes to these wonderful people:</summary>
97
- <a href="https://allcontributors.org/docs/en/emoji-key">Emoji Key </a>
98
-
99
- <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
100
- <!-- prettier-ignore-start -->
101
- <!-- markdownlint-disable -->
102
-
103
- <!-- markdownlint-restore -->
104
- <!-- prettier-ignore-end -->
105
-
106
- <!-- ALL-CONTRIBUTORS-LIST:END -->
107
-
108
- This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
109
- Contributions are welcome!
110
-
111
- </details>
112
-
113
- <!-- contributors-end -->
@@ -5,14 +5,14 @@ cadwyn/_importer.py,sha256=QV6HqODCG9K2oL4Vc15fAqL2-plMvUWw_cgaj4Ln4C8,1075
5
5
  cadwyn/_render.py,sha256=VAY2Twd_MfKaC8_X22AMIQd72_UHy87icdAbKL8hd90,5526
6
6
  cadwyn/_utils.py,sha256=q_mTtMKTNTDzqCza67XST-jaPSfuTgnFLmOe0dlGeYY,2295
7
7
  cadwyn/applications.py,sha256=FALDl4v_8dJWdrpHEuvG34C_vfnKKh01rAOiyg5wVak,21200
8
- cadwyn/changelogs.py,sha256=5S0yt94LAi2ani_uk-BGR_rK247IYWbZ3NvGmwnL7es,19632
8
+ cadwyn/changelogs.py,sha256=gJnK2Rtl2svVZYQ_J2F6kkfzdmXNgsKmI3MzuXS9dKQ,19738
9
9
  cadwyn/dependencies.py,sha256=phUJ4Fy3UTegpOfDfHMjxsvASWo-1NQgwqphNnPdoVQ,241
10
10
  cadwyn/exceptions.py,sha256=8D1G7ewLrMF5jq7leald1g0ulcH9zQl8ufEK3b7HHAE,1749
11
11
  cadwyn/middleware.py,sha256=4Ziq1ysnc8j5KmeZpsr9VJKllEFC8uYwXnG01I2FPR4,4853
12
12
  cadwyn/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  cadwyn/route_generation.py,sha256=conoTBtsOtjyiV2NdUxwGQX-h1zLyIjDQjD5bT2YSgg,27185
14
14
  cadwyn/routing.py,sha256=Ii6Qbgm9lGks1IAk-kDuIu_dX3FXsA77KSfGOFmLbgc,7604
15
- cadwyn/schema_generation.py,sha256=0Z81yHYk1aqE6aGsPCkaPI9IbmiHBlwbVBrfILuUNa0,47531
15
+ cadwyn/schema_generation.py,sha256=Q0Ma_2XA5plPcZ7sxNK1jZxubGDNcc-XMka3TkvFgEI,48848
16
16
  cadwyn/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  cadwyn/_internal/context_vars.py,sha256=VcM8eAoSlvrIMFQhjZmjflV5o1yrPSEZZGkwOK4OSf4,378
18
18
  cadwyn/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -20,12 +20,12 @@ cadwyn/static/docs.html,sha256=WNm5ANJVy51TcIUFOaqKf1Z8eF86CC85TTHPxACtkzw,3455
20
20
  cadwyn/structure/__init__.py,sha256=Wgvjdq3vfl9Yhe-BkcFGAMi_Co11YOfTmJQqgF5Gzx4,655
21
21
  cadwyn/structure/common.py,sha256=YuyfYMxkJcj2c5SFh9teBoEC2xLO5_2QjPzYjwdZcTs,478
22
22
  cadwyn/structure/data.py,sha256=eb4HlGTu3V_G5vJuQ4GLEaGd4LmPmFX3L8CXwJKzfOE,7795
23
- cadwyn/structure/endpoints.py,sha256=zUgzglNhBPnmWdJ03A8pFT4zPs_lj8nQ7c7Uo2d-ejU,6246
23
+ cadwyn/structure/endpoints.py,sha256=OYNaZ76VidtSutQfteFMba5nNIXtEjwCAvgpy3fRBT4,6246
24
24
  cadwyn/structure/enums.py,sha256=4FCc9aniLE3VuWAVIacrNP_FWxTIUm9JkeeHA_zZdwQ,1254
25
25
  cadwyn/structure/schemas.py,sha256=kuQJg60VpWHZkSPvrbvd9pe-Zetq8as5YYrERsG3IE8,10785
26
- cadwyn/structure/versions.py,sha256=IrtX8sGswjNc8z_6HsU9Im-U7-agZB_pFaqSHz_0SMk,34710
27
- cadwyn-5.4.3.dist-info/METADATA,sha256=N67ZpIucrREtYB2WUmWvRf0yG0Fowcj2B_5JTkEElEI,5076
28
- cadwyn-5.4.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- cadwyn-5.4.3.dist-info/entry_points.txt,sha256=mGX8wl-Xfhpr5M93SUmkykaqinUaYAvW9rtDSX54gx0,47
30
- cadwyn-5.4.3.dist-info/licenses/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
31
- cadwyn-5.4.3.dist-info/RECORD,,
26
+ cadwyn/structure/versions.py,sha256=3ZDKewBHHWmAwhOQbIR5p17ANzqglMDTvYUGKTAqXyk,34710
27
+ cadwyn-5.4.5.dist-info/METADATA,sha256=mgh_IMJ36E6I5rV8cyGSUR3e2QrEbYyUskWpimCbFLo,4504
28
+ cadwyn-5.4.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ cadwyn-5.4.5.dist-info/entry_points.txt,sha256=mGX8wl-Xfhpr5M93SUmkykaqinUaYAvW9rtDSX54gx0,47
30
+ cadwyn-5.4.5.dist-info/licenses/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
31
+ cadwyn-5.4.5.dist-info/RECORD,,
File without changes