cadwyn 5.4.6__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.
- cadwyn/__init__.py +44 -0
- cadwyn/__main__.py +78 -0
- cadwyn/_asts.py +155 -0
- cadwyn/_importer.py +31 -0
- cadwyn/_internal/__init__.py +0 -0
- cadwyn/_internal/context_vars.py +9 -0
- cadwyn/_render.py +155 -0
- cadwyn/_utils.py +79 -0
- cadwyn/applications.py +484 -0
- cadwyn/changelogs.py +503 -0
- cadwyn/dependencies.py +5 -0
- cadwyn/exceptions.py +78 -0
- cadwyn/middleware.py +131 -0
- cadwyn/py.typed +0 -0
- cadwyn/route_generation.py +536 -0
- cadwyn/routing.py +159 -0
- cadwyn/schema_generation.py +1162 -0
- cadwyn/static/__init__.py +0 -0
- cadwyn/static/docs.html +136 -0
- cadwyn/structure/__init__.py +31 -0
- cadwyn/structure/common.py +18 -0
- cadwyn/structure/data.py +249 -0
- cadwyn/structure/endpoints.py +170 -0
- cadwyn/structure/enums.py +42 -0
- cadwyn/structure/schemas.py +338 -0
- cadwyn/structure/versions.py +756 -0
- cadwyn-5.4.6.dist-info/METADATA +90 -0
- cadwyn-5.4.6.dist-info/RECORD +31 -0
- cadwyn-5.4.6.dist-info/WHEEL +4 -0
- cadwyn-5.4.6.dist-info/entry_points.txt +2 -0
- cadwyn-5.4.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Literal, Union, cast
|
|
4
|
+
|
|
5
|
+
from pydantic import AliasChoices, AliasPath, BaseModel, Field
|
|
6
|
+
from pydantic._internal._decorators import PydanticDescriptorProxy, unwrap_wrapped_function
|
|
7
|
+
from pydantic.fields import FieldInfo
|
|
8
|
+
|
|
9
|
+
from cadwyn._utils import (
|
|
10
|
+
DATACLASS_SLOTS,
|
|
11
|
+
Sentinel,
|
|
12
|
+
fully_unwrap_decorator,
|
|
13
|
+
get_name_of_function_wrapped_in_pydantic_validator,
|
|
14
|
+
lenient_issubclass,
|
|
15
|
+
)
|
|
16
|
+
from cadwyn.exceptions import CadwynStructureError
|
|
17
|
+
|
|
18
|
+
from .common import _HiddenAttributeMixin
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from pydantic.typing import AbstractSetIntStr, MappingIntStrAny
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
PossibleFieldAttributes = Literal[
|
|
25
|
+
"default",
|
|
26
|
+
"alias",
|
|
27
|
+
"alias_priority",
|
|
28
|
+
"default_factory",
|
|
29
|
+
"validation_alias",
|
|
30
|
+
"serialization_alias",
|
|
31
|
+
"title",
|
|
32
|
+
"field_title_generator",
|
|
33
|
+
"description",
|
|
34
|
+
"examples",
|
|
35
|
+
"exclude",
|
|
36
|
+
"const",
|
|
37
|
+
"deprecated",
|
|
38
|
+
"frozen",
|
|
39
|
+
"validate_default",
|
|
40
|
+
"repr",
|
|
41
|
+
"init",
|
|
42
|
+
"init_var",
|
|
43
|
+
"kw_only",
|
|
44
|
+
"fail_fast",
|
|
45
|
+
"gt",
|
|
46
|
+
"ge",
|
|
47
|
+
"lt",
|
|
48
|
+
"le",
|
|
49
|
+
"strict",
|
|
50
|
+
"coerce_numbers_to_str",
|
|
51
|
+
"multiple_of",
|
|
52
|
+
"allow_inf_nan",
|
|
53
|
+
"max_digits",
|
|
54
|
+
"decimal_places",
|
|
55
|
+
"min_length",
|
|
56
|
+
"max_length",
|
|
57
|
+
"union_mode",
|
|
58
|
+
"allow_mutation",
|
|
59
|
+
"pattern",
|
|
60
|
+
"discriminator",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# TODO: Add json_schema_extra as a breaking change in a major version
|
|
65
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
66
|
+
class FieldChanges:
|
|
67
|
+
default: Any
|
|
68
|
+
alias: Union[str, None]
|
|
69
|
+
default_factory: Any
|
|
70
|
+
alias_priority: Union[int, None]
|
|
71
|
+
validation_alias: Union[str, AliasPath, AliasChoices, None]
|
|
72
|
+
serialization_alias: Union[str, None]
|
|
73
|
+
title: Union[str, None]
|
|
74
|
+
field_title_generator: Union[Callable[[str, FieldInfo], str], None]
|
|
75
|
+
description: str
|
|
76
|
+
examples: Union[list[Any], None]
|
|
77
|
+
exclude: "AbstractSetIntStr | MappingIntStrAny | Any"
|
|
78
|
+
const: bool
|
|
79
|
+
deprecated: bool
|
|
80
|
+
frozen: Union[bool, None]
|
|
81
|
+
validate_default: Union[bool, None]
|
|
82
|
+
repr: bool
|
|
83
|
+
init: Union[bool, None]
|
|
84
|
+
init_var: Union[bool, None]
|
|
85
|
+
kw_only: Union[bool, None]
|
|
86
|
+
fail_fast: bool
|
|
87
|
+
gt: float
|
|
88
|
+
ge: float
|
|
89
|
+
lt: float
|
|
90
|
+
le: float
|
|
91
|
+
strict: bool
|
|
92
|
+
coerce_numbers_to_str: Union[bool, None]
|
|
93
|
+
multiple_of: float
|
|
94
|
+
allow_inf_nan: bool
|
|
95
|
+
max_digits: int
|
|
96
|
+
decimal_places: int
|
|
97
|
+
min_length: int
|
|
98
|
+
max_length: int
|
|
99
|
+
union_mode: Literal["smart", "left_to_right"]
|
|
100
|
+
allow_mutation: bool
|
|
101
|
+
pattern: str
|
|
102
|
+
discriminator: str
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
106
|
+
class FieldHadInstruction(_HiddenAttributeMixin):
|
|
107
|
+
schema: type[BaseModel]
|
|
108
|
+
name: str
|
|
109
|
+
type: type
|
|
110
|
+
field_changes: FieldChanges
|
|
111
|
+
new_name: str
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
115
|
+
class FieldDidntHaveInstruction(_HiddenAttributeMixin):
|
|
116
|
+
schema: type[BaseModel]
|
|
117
|
+
name: str
|
|
118
|
+
attributes: tuple[str, ...]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
122
|
+
class FieldDidntExistInstruction(_HiddenAttributeMixin):
|
|
123
|
+
schema: type[BaseModel]
|
|
124
|
+
name: str
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
128
|
+
class FieldExistedAsInstruction(_HiddenAttributeMixin):
|
|
129
|
+
schema: type[BaseModel]
|
|
130
|
+
name: str
|
|
131
|
+
field: FieldInfo
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# TODO (https://github.com/zmievsa/cadwyn/issues/112): Add an ability to add extras
|
|
135
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
136
|
+
class AlterFieldInstructionFactory:
|
|
137
|
+
schema: type[BaseModel]
|
|
138
|
+
name: str
|
|
139
|
+
|
|
140
|
+
def had(
|
|
141
|
+
self,
|
|
142
|
+
*,
|
|
143
|
+
name: str = Sentinel,
|
|
144
|
+
type: Any = Sentinel,
|
|
145
|
+
default: Any = Sentinel,
|
|
146
|
+
alias: Union[str, None] = Sentinel,
|
|
147
|
+
default_factory: Callable = Sentinel,
|
|
148
|
+
alias_priority: Union[int, None] = Sentinel,
|
|
149
|
+
validation_alias: Union[str, AliasPath, AliasChoices, None] = Sentinel,
|
|
150
|
+
serialization_alias: Union[str, None] = Sentinel,
|
|
151
|
+
title: Union[str, None] = Sentinel,
|
|
152
|
+
field_title_generator: Union[Callable[[str, FieldInfo], str], None] = Sentinel,
|
|
153
|
+
description: str = Sentinel,
|
|
154
|
+
examples: Union[list[Any], None] = Sentinel,
|
|
155
|
+
exclude: "AbstractSetIntStr | MappingIntStrAny | Any" = Sentinel,
|
|
156
|
+
const: bool = Sentinel,
|
|
157
|
+
deprecated: bool = Sentinel,
|
|
158
|
+
frozen: Union[bool, None] = Sentinel,
|
|
159
|
+
validate_default: Union[bool, None] = Sentinel,
|
|
160
|
+
repr: bool = Sentinel,
|
|
161
|
+
init: bool = Sentinel,
|
|
162
|
+
init_var: bool = Sentinel,
|
|
163
|
+
kw_only: bool = Sentinel,
|
|
164
|
+
fail_fast: bool = Sentinel,
|
|
165
|
+
gt: float = Sentinel,
|
|
166
|
+
ge: float = Sentinel,
|
|
167
|
+
lt: float = Sentinel,
|
|
168
|
+
le: float = Sentinel,
|
|
169
|
+
strict: bool = Sentinel,
|
|
170
|
+
coerce_numbers_to_str: bool = Sentinel,
|
|
171
|
+
multiple_of: float = Sentinel,
|
|
172
|
+
allow_inf_nan: bool = Sentinel,
|
|
173
|
+
max_digits: int = Sentinel,
|
|
174
|
+
decimal_places: int = Sentinel,
|
|
175
|
+
min_length: int = Sentinel,
|
|
176
|
+
max_length: int = Sentinel,
|
|
177
|
+
union_mode: Literal["smart", "left_to_right"] = Sentinel,
|
|
178
|
+
allow_mutation: bool = Sentinel,
|
|
179
|
+
pattern: str = Sentinel,
|
|
180
|
+
discriminator: str = Sentinel,
|
|
181
|
+
) -> FieldHadInstruction:
|
|
182
|
+
return FieldHadInstruction(
|
|
183
|
+
is_hidden_from_changelog=False,
|
|
184
|
+
schema=self.schema,
|
|
185
|
+
name=self.name,
|
|
186
|
+
type=type,
|
|
187
|
+
new_name=name,
|
|
188
|
+
field_changes=FieldChanges(
|
|
189
|
+
default=default,
|
|
190
|
+
default_factory=default_factory,
|
|
191
|
+
alias_priority=alias_priority,
|
|
192
|
+
alias=alias,
|
|
193
|
+
validation_alias=validation_alias,
|
|
194
|
+
serialization_alias=serialization_alias,
|
|
195
|
+
title=title,
|
|
196
|
+
field_title_generator=field_title_generator,
|
|
197
|
+
description=description,
|
|
198
|
+
examples=examples,
|
|
199
|
+
exclude=exclude,
|
|
200
|
+
const=const,
|
|
201
|
+
deprecated=deprecated,
|
|
202
|
+
frozen=frozen,
|
|
203
|
+
validate_default=validate_default,
|
|
204
|
+
repr=repr,
|
|
205
|
+
init=init,
|
|
206
|
+
init_var=init_var,
|
|
207
|
+
kw_only=kw_only,
|
|
208
|
+
fail_fast=fail_fast,
|
|
209
|
+
gt=gt,
|
|
210
|
+
ge=ge,
|
|
211
|
+
lt=lt,
|
|
212
|
+
le=le,
|
|
213
|
+
strict=strict,
|
|
214
|
+
coerce_numbers_to_str=coerce_numbers_to_str,
|
|
215
|
+
multiple_of=multiple_of,
|
|
216
|
+
allow_inf_nan=allow_inf_nan,
|
|
217
|
+
max_digits=max_digits,
|
|
218
|
+
decimal_places=decimal_places,
|
|
219
|
+
min_length=min_length,
|
|
220
|
+
max_length=max_length,
|
|
221
|
+
union_mode=union_mode,
|
|
222
|
+
allow_mutation=allow_mutation,
|
|
223
|
+
pattern=pattern,
|
|
224
|
+
discriminator=discriminator,
|
|
225
|
+
),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
def didnt_have(self, *attributes: PossibleFieldAttributes) -> FieldDidntHaveInstruction:
|
|
229
|
+
for attribute in attributes:
|
|
230
|
+
if attribute not in FieldChanges.__dataclass_fields__:
|
|
231
|
+
raise CadwynStructureError(
|
|
232
|
+
f"Unknown attribute {attribute!r}. Are you sure it's a valid field attribute?"
|
|
233
|
+
)
|
|
234
|
+
return FieldDidntHaveInstruction(
|
|
235
|
+
is_hidden_from_changelog=False, schema=self.schema, name=self.name, attributes=attributes
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def didnt_exist(self) -> FieldDidntExistInstruction:
|
|
240
|
+
return FieldDidntExistInstruction(is_hidden_from_changelog=False, schema=self.schema, name=self.name)
|
|
241
|
+
|
|
242
|
+
def existed_as(
|
|
243
|
+
self,
|
|
244
|
+
*,
|
|
245
|
+
type: Any,
|
|
246
|
+
info: Union[FieldInfo, Any, None] = None,
|
|
247
|
+
) -> FieldExistedAsInstruction:
|
|
248
|
+
if info is None:
|
|
249
|
+
info = cast("FieldInfo", Field())
|
|
250
|
+
info.annotation = type
|
|
251
|
+
return FieldExistedAsInstruction(is_hidden_from_changelog=False, schema=self.schema, name=self.name, field=info)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _get_model_decorators(model: type[BaseModel]):
|
|
255
|
+
return [
|
|
256
|
+
*model.__pydantic_decorators__.validators.values(),
|
|
257
|
+
*model.__pydantic_decorators__.field_validators.values(),
|
|
258
|
+
*model.__pydantic_decorators__.root_validators.values(),
|
|
259
|
+
*model.__pydantic_decorators__.field_serializers.values(),
|
|
260
|
+
*model.__pydantic_decorators__.model_serializers.values(),
|
|
261
|
+
*model.__pydantic_decorators__.model_validators.values(),
|
|
262
|
+
*model.__pydantic_decorators__.computed_fields.values(),
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
267
|
+
class ValidatorExistedInstruction:
|
|
268
|
+
schema: type[BaseModel]
|
|
269
|
+
validator: Union[Callable[..., Any], PydanticDescriptorProxy]
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
273
|
+
class ValidatorDidntExistInstruction:
|
|
274
|
+
schema: type[BaseModel]
|
|
275
|
+
name: str
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
279
|
+
class AlterValidatorInstructionFactory:
|
|
280
|
+
schema: type[BaseModel]
|
|
281
|
+
func: Union[Callable[..., Any], PydanticDescriptorProxy]
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def existed(self) -> ValidatorExistedInstruction:
|
|
285
|
+
return ValidatorExistedInstruction(self.schema, self.func)
|
|
286
|
+
|
|
287
|
+
@property
|
|
288
|
+
def didnt_exist(self) -> ValidatorDidntExistInstruction:
|
|
289
|
+
return ValidatorDidntExistInstruction(
|
|
290
|
+
self.schema, get_name_of_function_wrapped_in_pydantic_validator(self.func)
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
AlterSchemaSubInstruction = Union[
|
|
295
|
+
FieldHadInstruction,
|
|
296
|
+
FieldDidntHaveInstruction,
|
|
297
|
+
FieldDidntExistInstruction,
|
|
298
|
+
FieldExistedAsInstruction,
|
|
299
|
+
ValidatorExistedInstruction,
|
|
300
|
+
ValidatorDidntExistInstruction,
|
|
301
|
+
]
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
305
|
+
class SchemaHadInstruction(_HiddenAttributeMixin):
|
|
306
|
+
schema: type[BaseModel]
|
|
307
|
+
name: str
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
@dataclass(**DATACLASS_SLOTS)
|
|
311
|
+
class AlterSchemaInstructionFactory:
|
|
312
|
+
schema: type[BaseModel]
|
|
313
|
+
|
|
314
|
+
def field(self, name: str, /) -> AlterFieldInstructionFactory:
|
|
315
|
+
return AlterFieldInstructionFactory(self.schema, name)
|
|
316
|
+
|
|
317
|
+
def validator(
|
|
318
|
+
self, func: "Union[Callable[..., Any], classmethod[Any, Any, Any], PydanticDescriptorProxy]", /
|
|
319
|
+
) -> AlterValidatorInstructionFactory:
|
|
320
|
+
func = cast("Union[Callable[..., Any], PydanticDescriptorProxy]", unwrap_wrapped_function(func))
|
|
321
|
+
|
|
322
|
+
if not isinstance(func, PydanticDescriptorProxy):
|
|
323
|
+
if hasattr(func, "__self__"):
|
|
324
|
+
owner = func.__self__
|
|
325
|
+
if lenient_issubclass(owner, BaseModel) and any( # pragma: no branch
|
|
326
|
+
fully_unwrap_decorator(decorator.func, decorator.shim) == func
|
|
327
|
+
for decorator in _get_model_decorators(owner)
|
|
328
|
+
):
|
|
329
|
+
return AlterValidatorInstructionFactory(self.schema, func)
|
|
330
|
+
raise CadwynStructureError("The passed function must be a pydantic validator")
|
|
331
|
+
return AlterValidatorInstructionFactory(self.schema, func)
|
|
332
|
+
|
|
333
|
+
def had(self, *, name: str) -> SchemaHadInstruction:
|
|
334
|
+
return SchemaHadInstruction(is_hidden_from_changelog=False, schema=self.schema, name=name)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def schema(model: type[BaseModel], /) -> AlterSchemaInstructionFactory:
|
|
338
|
+
return AlterSchemaInstructionFactory(model)
|