cadwyn 2.0.3__py3-none-any.whl → 2.1.0rc0__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/codegen.py +160 -84
- cadwyn/header.py +1 -1
- cadwyn/routing.py +1 -1
- cadwyn/structure/versions.py +5 -1
- {cadwyn-2.0.3.dist-info → cadwyn-2.1.0rc0.dist-info}/METADATA +1 -1
- {cadwyn-2.0.3.dist-info → cadwyn-2.1.0rc0.dist-info}/RECORD +9 -9
- {cadwyn-2.0.3.dist-info → cadwyn-2.1.0rc0.dist-info}/LICENSE +0 -0
- {cadwyn-2.0.3.dist-info → cadwyn-2.1.0rc0.dist-info}/WHEEL +0 -0
- {cadwyn-2.0.3.dist-info → cadwyn-2.1.0rc0.dist-info}/entry_points.txt +0 -0
cadwyn/codegen.py
CHANGED
|
@@ -9,12 +9,14 @@ from copy import deepcopy
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from datetime import date
|
|
11
11
|
from enum import Enum, auto
|
|
12
|
+
from functools import cache
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
from types import GenericAlias, LambdaType, ModuleType, NoneType
|
|
14
15
|
from typing import (
|
|
15
16
|
Any,
|
|
16
17
|
TypeAlias,
|
|
17
|
-
_BaseGenericAlias,
|
|
18
|
+
_BaseGenericAlias,
|
|
19
|
+
cast, # pyright: ignore[reportGeneralTypeIssues]
|
|
18
20
|
final,
|
|
19
21
|
get_args,
|
|
20
22
|
get_origin,
|
|
@@ -109,10 +111,23 @@ class ModelPrivateAttrInfo:
|
|
|
109
111
|
annotation: Any
|
|
110
112
|
|
|
111
113
|
|
|
114
|
+
@dataclass
|
|
115
|
+
class ModelFieldInfo:
|
|
116
|
+
cls: type[BaseModel]
|
|
117
|
+
_annotation: ast.expr | None
|
|
118
|
+
field: ModelField | ModelFieldLike
|
|
119
|
+
field_ast: ast.expr | None
|
|
120
|
+
|
|
121
|
+
def get_annotation(self): # intentionally weird to not clash with ModelField
|
|
122
|
+
if self._annotation:
|
|
123
|
+
return PlainRepr(ast.unparse(self._annotation))
|
|
124
|
+
return self.field.annotation
|
|
125
|
+
|
|
126
|
+
|
|
112
127
|
@dataclass(slots=True)
|
|
113
128
|
class ModelInfo:
|
|
114
129
|
name: str
|
|
115
|
-
fields: dict[_FieldName,
|
|
130
|
+
fields: dict[_FieldName, ModelFieldInfo]
|
|
116
131
|
|
|
117
132
|
|
|
118
133
|
@dataclass(slots=True)
|
|
@@ -121,6 +136,33 @@ class _SchemaBundle:
|
|
|
121
136
|
schemas: dict[str, ModelInfo]
|
|
122
137
|
|
|
123
138
|
|
|
139
|
+
@cache
|
|
140
|
+
def _get_fields_from_model(cls: type):
|
|
141
|
+
mro_fields = [_get_fields_from_model(parent) for parent in cls.mro()[1:] if issubclass(parent, BaseModel)]
|
|
142
|
+
if not isinstance(cls, type) or not issubclass(cls, BaseModel):
|
|
143
|
+
raise CodeGenerationError(f"Model {cls} is not a subclass of BaseModel")
|
|
144
|
+
try:
|
|
145
|
+
source = inspect.getsource(cls)
|
|
146
|
+
except OSError:
|
|
147
|
+
current_field_defs = {
|
|
148
|
+
field_name: ModelFieldInfo(cls, None, field, None) for field_name, field in cls.__fields__.items()
|
|
149
|
+
}
|
|
150
|
+
else:
|
|
151
|
+
cls_ast = cast(ast.ClassDef, ast.parse(source).body[0])
|
|
152
|
+
current_field_defs = {
|
|
153
|
+
node.target.id: ModelFieldInfo(cls, node.annotation, cls.__fields__[node.target.id], node.value)
|
|
154
|
+
for node in cls_ast.body
|
|
155
|
+
if isinstance(node, ast.AnnAssign)
|
|
156
|
+
and isinstance(node.target, ast.Name)
|
|
157
|
+
and node.target.id in cls.__fields__
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
final_field_defs: dict[str, ModelFieldInfo] = {}
|
|
161
|
+
for attr in reversed(mro_fields):
|
|
162
|
+
final_field_defs |= attr
|
|
163
|
+
return final_field_defs | current_field_defs
|
|
164
|
+
|
|
165
|
+
|
|
124
166
|
def generate_code_for_versioned_packages(
|
|
125
167
|
template_module: ModuleType,
|
|
126
168
|
versions: VersionBundle,
|
|
@@ -136,7 +178,7 @@ def generate_code_for_versioned_packages(
|
|
|
136
178
|
version of the latest module.
|
|
137
179
|
"""
|
|
138
180
|
schemas = {
|
|
139
|
-
k: ModelInfo(v.__name__,
|
|
181
|
+
k: ModelInfo(v.__name__, _get_fields_from_model(v)) for k, v in deepcopy(versions.versioned_schemas).items()
|
|
140
182
|
}
|
|
141
183
|
enums = {k: (v, {member.name: member.value for member in v}) for k, v in deepcopy(versions.versioned_enums).items()}
|
|
142
184
|
schemas_per_version: list[_SchemaBundle] = []
|
|
@@ -276,7 +318,7 @@ def _apply_alter_schema_instructions( # noqa: C901
|
|
|
276
318
|
f'You tried to change the type of field "{alter_schema_instruction.field_name}" from '
|
|
277
319
|
f'"{schema.__name__}" in "{version_change_name}" but it doesn\'t have such a field.',
|
|
278
320
|
)
|
|
279
|
-
model_field = field_name_to_field_model[alter_schema_instruction.field_name]
|
|
321
|
+
model_field = field_name_to_field_model[alter_schema_instruction.field_name].field
|
|
280
322
|
if alter_schema_instruction.type is not Sentinel:
|
|
281
323
|
if model_field.annotation == alter_schema_instruction.type:
|
|
282
324
|
raise InvalidGenerationInstructionError(
|
|
@@ -285,6 +327,8 @@ def _apply_alter_schema_instructions( # noqa: C901
|
|
|
285
327
|
f'but it already has type "{model_field.annotation}"',
|
|
286
328
|
)
|
|
287
329
|
model_field.annotation = alter_schema_instruction.type
|
|
330
|
+
# TODO: Extend ast instead of removing it
|
|
331
|
+
field_name_to_field_model[alter_schema_instruction.field_name]._annotation = None
|
|
288
332
|
if alter_schema_instruction.new_name is not Sentinel:
|
|
289
333
|
if alter_schema_instruction.new_name == alter_schema_instruction.field_name:
|
|
290
334
|
raise InvalidGenerationInstructionError(
|
|
@@ -311,7 +355,17 @@ def _apply_alter_schema_instructions( # noqa: C901
|
|
|
311
355
|
f'from "{schema.__name__}" to {attr_value!r} in "{version_change_name}" '
|
|
312
356
|
"but it already has that value.",
|
|
313
357
|
)
|
|
314
|
-
|
|
358
|
+
|
|
359
|
+
if attr_name in model_field.annotation.__dict__ and _is_pydantic_constrained_type(
|
|
360
|
+
model_field.annotation,
|
|
361
|
+
):
|
|
362
|
+
setattr(model_field.annotation, attr_name, attr_value)
|
|
363
|
+
else:
|
|
364
|
+
setattr(field_info, attr_name, attr_value)
|
|
365
|
+
# TODO: Extend ast instead of removing it
|
|
366
|
+
field_name_to_field_model[alter_schema_instruction.field_name]._annotation = None
|
|
367
|
+
field_name_to_field_model[alter_schema_instruction.field_name].field_ast = None
|
|
368
|
+
|
|
315
369
|
elif isinstance(alter_schema_instruction, OldSchemaFieldExistedWith):
|
|
316
370
|
if alter_schema_instruction.field_name in field_name_to_field_model:
|
|
317
371
|
raise InvalidGenerationInstructionError(
|
|
@@ -322,9 +376,10 @@ def _apply_alter_schema_instructions( # noqa: C901
|
|
|
322
376
|
annotation = alter_schema_instruction.import_as
|
|
323
377
|
else:
|
|
324
378
|
annotation = alter_schema_instruction.type
|
|
325
|
-
field_name_to_field_model[alter_schema_instruction.field_name] = (
|
|
379
|
+
field_name_to_field_model[alter_schema_instruction.field_name] = ModelFieldInfo(
|
|
326
380
|
schema,
|
|
327
|
-
|
|
381
|
+
_annotation=None, # TODO: Get this from migration
|
|
382
|
+
field=ModelFieldLike(
|
|
328
383
|
name=alter_schema_instruction.field_name,
|
|
329
384
|
original_type=alter_schema_instruction.type,
|
|
330
385
|
annotation=annotation,
|
|
@@ -332,6 +387,7 @@ def _apply_alter_schema_instructions( # noqa: C901
|
|
|
332
387
|
import_from=alter_schema_instruction.import_from,
|
|
333
388
|
import_as=alter_schema_instruction.import_as,
|
|
334
389
|
),
|
|
390
|
+
field_ast=None, # TODO: Get this from migration
|
|
335
391
|
)
|
|
336
392
|
elif isinstance(alter_schema_instruction, AlterSchemaInstruction):
|
|
337
393
|
# We only handle names right now so we just go ahead and check
|
|
@@ -459,21 +515,6 @@ def _generate_parallel_directory(
|
|
|
459
515
|
shutil.copyfile(original_file, parallel_file)
|
|
460
516
|
|
|
461
517
|
|
|
462
|
-
def _get_fields_for_model(
|
|
463
|
-
model: type[BaseModel],
|
|
464
|
-
) -> dict[_FieldName, tuple[type[BaseModel], ModelField | ModelFieldLike]]:
|
|
465
|
-
actual_fields: dict[_FieldName, tuple[type[BaseModel], ModelField | ModelFieldLike]] = {}
|
|
466
|
-
for cls in model.__mro__:
|
|
467
|
-
if cls is BaseModel:
|
|
468
|
-
return actual_fields
|
|
469
|
-
if not issubclass(cls, BaseModel):
|
|
470
|
-
continue
|
|
471
|
-
for field_name, field in cls.__fields__.items():
|
|
472
|
-
if field_name not in actual_fields and field_name in cls.__annotations__:
|
|
473
|
-
actual_fields[field_name] = (cls, field)
|
|
474
|
-
raise CodeGenerationError(f"Model {model} is not a subclass of BaseModel")
|
|
475
|
-
|
|
476
|
-
|
|
477
518
|
def _parse_python_module(module: ModuleType) -> ast.Module:
|
|
478
519
|
try:
|
|
479
520
|
return ast.parse(inspect.getsource(module))
|
|
@@ -502,22 +543,37 @@ def _migrate_module_to_another_version(
|
|
|
502
543
|
else:
|
|
503
544
|
module_name = module.__name__
|
|
504
545
|
all_names_in_file = _get_all_names_defined_in_module(parsed_file, module_name)
|
|
505
|
-
|
|
506
546
|
# TODO: Does this play well with renaming?
|
|
507
547
|
extra_field_imports = [
|
|
508
548
|
ast.ImportFrom(
|
|
509
|
-
module=field.import_from,
|
|
510
|
-
names=[
|
|
549
|
+
module=field.field.import_from,
|
|
550
|
+
names=[
|
|
551
|
+
ast.alias(name=transformer.visit(field.field.original_type).strip("'"), asname=field.field.import_as),
|
|
552
|
+
],
|
|
511
553
|
level=0,
|
|
512
554
|
)
|
|
513
555
|
for val in modified_schemas.values()
|
|
514
|
-
for
|
|
515
|
-
if isinstance(field, ModelFieldLike) and field.import_from is not None
|
|
556
|
+
for field in val.fields.values()
|
|
557
|
+
if isinstance(field.field, ModelFieldLike) and field.field.import_from is not None
|
|
516
558
|
]
|
|
517
559
|
|
|
518
560
|
body = ast.Module(
|
|
519
561
|
[
|
|
520
|
-
ast.ImportFrom(
|
|
562
|
+
ast.ImportFrom(
|
|
563
|
+
module="pydantic",
|
|
564
|
+
names=[
|
|
565
|
+
ast.alias(name="Field"),
|
|
566
|
+
ast.alias(name="conbytes"),
|
|
567
|
+
ast.alias(name="conlist"),
|
|
568
|
+
ast.alias(name="conset"),
|
|
569
|
+
ast.alias(name="constr"),
|
|
570
|
+
ast.alias(name="conint"),
|
|
571
|
+
ast.alias(name="confloat"),
|
|
572
|
+
ast.alias(name="condecimal"),
|
|
573
|
+
ast.alias(name="condate"),
|
|
574
|
+
],
|
|
575
|
+
level=0,
|
|
576
|
+
),
|
|
521
577
|
ast.Import(names=[ast.alias(name="typing")], level=0),
|
|
522
578
|
ast.ImportFrom(module="typing", names=[ast.alias(name="Any")], level=0),
|
|
523
579
|
]
|
|
@@ -606,49 +662,64 @@ def _modify_schema_cls(
|
|
|
606
662
|
module_python_path: str,
|
|
607
663
|
cls_python_path: str,
|
|
608
664
|
) -> ast.ClassDef:
|
|
609
|
-
|
|
665
|
+
object_renamer = _AnnotationTransformer()
|
|
666
|
+
ast_renamer = _AnnotationASTNodeTransformerWithSchemaRenaming(
|
|
610
667
|
modified_schemas,
|
|
611
|
-
module_python_path,
|
|
612
668
|
all_names_in_module,
|
|
669
|
+
module_python_path,
|
|
613
670
|
)
|
|
614
|
-
ast_transformer = _AnnotationASTNodeTransformer(modified_schemas, all_names_in_module, module_python_path)
|
|
615
671
|
if cls_python_path in modified_schemas:
|
|
616
672
|
model_info = modified_schemas[cls_python_path]
|
|
673
|
+
# This is for possible schema renaming
|
|
617
674
|
cls_node.name = model_info.name
|
|
675
|
+
|
|
618
676
|
field_definitions = [
|
|
619
677
|
ast.AnnAssign(
|
|
620
678
|
target=ast.Name(name, ctx=ast.Store()),
|
|
621
|
-
annotation=ast.Name(
|
|
622
|
-
value=_generate_field_ast(field,
|
|
679
|
+
annotation=ast.Name(object_renamer.visit(field.get_annotation())),
|
|
680
|
+
value=_generate_field_ast(field, object_renamer),
|
|
623
681
|
simple=1,
|
|
624
682
|
)
|
|
625
|
-
for name,
|
|
683
|
+
for name, field in model_info.fields.items()
|
|
626
684
|
]
|
|
627
685
|
else:
|
|
628
686
|
field_definitions = [field for field in cls_node.body if isinstance(field, ast.AnnAssign)]
|
|
629
|
-
|
|
630
687
|
old_body = [n for n in cls_node.body if not isinstance(n, ast.AnnAssign | ast.Pass | ast.Ellipsis)]
|
|
631
688
|
docstring = _pop_docstring_from_cls_body(old_body)
|
|
632
689
|
cls_node.body = docstring + field_definitions + old_body
|
|
633
|
-
|
|
690
|
+
if not cls_node.body:
|
|
691
|
+
cls_node.body = [ast.Pass()]
|
|
692
|
+
|
|
693
|
+
return ast_renamer.visit(ast.parse(ast.unparse(cls_node)).body[0])
|
|
634
694
|
|
|
635
695
|
|
|
636
696
|
def _generate_field_ast(
|
|
637
|
-
field:
|
|
638
|
-
annotation_transformer: "
|
|
697
|
+
field: ModelFieldInfo,
|
|
698
|
+
annotation_transformer: "_AnnotationTransformer",
|
|
639
699
|
):
|
|
700
|
+
if field.field_ast is not None:
|
|
701
|
+
return field.field_ast
|
|
702
|
+
passed_attrs = {
|
|
703
|
+
attr: _get_attribute_from_field_info(field.field, attr)
|
|
704
|
+
for attr in _get_passed_attributes_to_field(field.field.field_info)
|
|
705
|
+
}
|
|
706
|
+
if _is_pydantic_constrained_type(field.field.annotation):
|
|
707
|
+
(
|
|
708
|
+
attrs_that_are_only_in_contype,
|
|
709
|
+
attrs_that_are_only_in_field,
|
|
710
|
+
) = _get_attrs_that_are_not_from_field_and_that_are_from_field(field.field.annotation)
|
|
711
|
+
if not attrs_that_are_only_in_contype:
|
|
712
|
+
passed_attrs |= attrs_that_are_only_in_field
|
|
713
|
+
|
|
640
714
|
return ast.Call(
|
|
641
715
|
func=ast.Name("Field"),
|
|
642
716
|
args=[],
|
|
643
717
|
keywords=[
|
|
644
718
|
ast.keyword(
|
|
645
719
|
arg=attr,
|
|
646
|
-
value=ast.parse(
|
|
647
|
-
annotation_transformer.visit(_get_attribute_from_field_info(field, attr)),
|
|
648
|
-
mode="eval",
|
|
649
|
-
).body,
|
|
720
|
+
value=ast.parse(annotation_transformer.visit(attr_value), mode="eval").body,
|
|
650
721
|
)
|
|
651
|
-
for attr in
|
|
722
|
+
for attr, attr_value in passed_attrs.items()
|
|
652
723
|
],
|
|
653
724
|
)
|
|
654
725
|
|
|
@@ -701,7 +772,7 @@ def _get_passed_attributes_to_field(field_info: FieldInfo):
|
|
|
701
772
|
yield from field_info.extra
|
|
702
773
|
|
|
703
774
|
|
|
704
|
-
class
|
|
775
|
+
class _AnnotationASTNodeTransformerWithSchemaRenaming(ast.NodeTransformer):
|
|
705
776
|
def __init__(
|
|
706
777
|
self,
|
|
707
778
|
modified_schemas: dict[str, ModelInfo],
|
|
@@ -724,6 +795,8 @@ class _AnnotationASTNodeTransformer(ast.NodeTransformer):
|
|
|
724
795
|
|
|
725
796
|
|
|
726
797
|
class _AnnotationTransformer:
|
|
798
|
+
"""Returns fancy and correct reprs of annotations"""
|
|
799
|
+
|
|
727
800
|
def visit(self, value: Any):
|
|
728
801
|
if isinstance(value, list | tuple | set | frozenset):
|
|
729
802
|
return self.transform_collection(value)
|
|
@@ -765,22 +838,27 @@ class _AnnotationTransformer:
|
|
|
765
838
|
def transform_type(self, value: type) -> Any:
|
|
766
839
|
# NOTE: Be wary of this hack when migrating to pydantic v2
|
|
767
840
|
# This is a hack for pydantic's Constrained types
|
|
768
|
-
if
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
cls_name.
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
841
|
+
if _is_pydantic_constrained_type(value):
|
|
842
|
+
if _get_attrs_that_are_not_from_field_and_that_are_from_field(value)[0]:
|
|
843
|
+
# No, get_origin and get_args don't work here. No idea why
|
|
844
|
+
parent = value.mro()[1]
|
|
845
|
+
snake_case = _RE_CAMEL_TO_SNAKE.sub("_", value.__name__)
|
|
846
|
+
cls_name = "con" + "".join(snake_case.split("_")[1:-1])
|
|
847
|
+
return (
|
|
848
|
+
cls_name.lower()
|
|
849
|
+
+ "("
|
|
850
|
+
+ ", ".join(
|
|
851
|
+
[
|
|
852
|
+
f"{key}={self.visit(val)}"
|
|
853
|
+
for key, val in value.__dict__.items()
|
|
854
|
+
if not key.startswith("_") and val is not None and val != parent.__dict__[key]
|
|
855
|
+
],
|
|
856
|
+
)
|
|
857
|
+
+ ")"
|
|
781
858
|
)
|
|
782
|
-
|
|
783
|
-
|
|
859
|
+
else:
|
|
860
|
+
value = value.mro()[-2]
|
|
861
|
+
|
|
784
862
|
return value.__name__
|
|
785
863
|
|
|
786
864
|
def transform_enum(self, value: Enum) -> Any:
|
|
@@ -804,36 +882,34 @@ class _AnnotationTransformer:
|
|
|
804
882
|
return PlainRepr(repr(value))
|
|
805
883
|
|
|
806
884
|
|
|
807
|
-
|
|
808
|
-
"""
|
|
809
|
-
String class where repr doesn't include quotes.
|
|
810
|
-
"""
|
|
885
|
+
def _is_pydantic_constrained_type(value: object):
|
|
886
|
+
return isinstance(value, type) and value.__name__.startswith("Constrained") and value.__name__.endswith("Value")
|
|
811
887
|
|
|
812
|
-
def __repr__(self) -> str:
|
|
813
|
-
return str(self)
|
|
814
888
|
|
|
889
|
+
def _get_attrs_that_are_not_from_field_and_that_are_from_field(value: type):
|
|
890
|
+
parent_public_attrs = {k: v for k, v in value.mro()[1].__dict__.items() if not k.startswith("_")}
|
|
891
|
+
value_private_attrs = {k: v for k, v in value.__dict__.items() if not k.startswith("_")}
|
|
892
|
+
attrs_in_value_different_from_parent = {
|
|
893
|
+
k: v for k, v in value_private_attrs.items() if k in parent_public_attrs and parent_public_attrs[k] != v
|
|
894
|
+
}
|
|
895
|
+
attrs_in_value_different_from_parent_that_are_not_in_field_def = {
|
|
896
|
+
k: v for k, v in attrs_in_value_different_from_parent.items() if k not in _dict_of_empty_field_info
|
|
897
|
+
}
|
|
898
|
+
attrs_in_value_different_from_parent_that_are_in_field_def = {
|
|
899
|
+
k: v for k, v in attrs_in_value_different_from_parent.items() if k in _dict_of_empty_field_info
|
|
900
|
+
}
|
|
815
901
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
module_python_path: str,
|
|
821
|
-
all_names_in_module: dict[str, str],
|
|
822
|
-
):
|
|
823
|
-
super().__init__()
|
|
902
|
+
return (
|
|
903
|
+
attrs_in_value_different_from_parent_that_are_not_in_field_def,
|
|
904
|
+
attrs_in_value_different_from_parent_that_are_in_field_def,
|
|
905
|
+
)
|
|
824
906
|
|
|
825
|
-
self.modified_schemas = modified_schemas
|
|
826
|
-
self.module_python_path = module_python_path
|
|
827
|
-
self.all_names_in_module = all_names_in_module
|
|
828
907
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
return model_info.name
|
|
835
|
-
else:
|
|
836
|
-
return super().transform_type(value)
|
|
908
|
+
class PlainRepr(str):
|
|
909
|
+
"""String class where repr doesn't include quotes"""
|
|
910
|
+
|
|
911
|
+
def __repr__(self) -> str:
|
|
912
|
+
return str(self)
|
|
837
913
|
|
|
838
914
|
|
|
839
915
|
def _find_a_lambda(source: str) -> str:
|
cadwyn/header.py
CHANGED
|
@@ -12,7 +12,7 @@ def get_cadwyn_dependency(
|
|
|
12
12
|
version_header_name: str,
|
|
13
13
|
default_version: datetime.date | None = None,
|
|
14
14
|
extra_kwargs_to_header_constructor: Mapping[str, Any] = types.MappingProxyType({}),
|
|
15
|
-
api_version_var: ContextVar[datetime.date | None],
|
|
15
|
+
api_version_var: ContextVar[datetime.date | None] | ContextVar[datetime.date],
|
|
16
16
|
) -> Any:
|
|
17
17
|
if default_version is None:
|
|
18
18
|
extra_kwargs: Mapping[str, Any] = extra_kwargs_to_header_constructor
|
cadwyn/routing.py
CHANGED
|
@@ -438,7 +438,7 @@ class _AnnotationTransformer:
|
|
|
438
438
|
elif annotation is typing.Any or isinstance(annotation, typing.NewType):
|
|
439
439
|
return annotation
|
|
440
440
|
elif isinstance(annotation, type):
|
|
441
|
-
if annotation.__module__ == "pydantic.main" and issubclass(annotation, BaseModel):
|
|
441
|
+
if annotation.__module__ == "pydantic.main" and issubclass(annotation, BaseModel):
|
|
442
442
|
return create_body_model(
|
|
443
443
|
fields=self._change_version_of_annotations(annotation.__fields__, version_dir).values(),
|
|
444
444
|
model_name=annotation.__name__,
|
cadwyn/structure/versions.py
CHANGED
|
@@ -200,7 +200,11 @@ class Version:
|
|
|
200
200
|
|
|
201
201
|
|
|
202
202
|
class VersionBundle:
|
|
203
|
-
def __init__(
|
|
203
|
+
def __init__(
|
|
204
|
+
self,
|
|
205
|
+
*versions: Version,
|
|
206
|
+
api_version_var: ContextVar[VersionDate | None] | ContextVar[VersionDate],
|
|
207
|
+
) -> None:
|
|
204
208
|
super().__init__()
|
|
205
209
|
|
|
206
210
|
self.versions = versions
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
cadwyn/__init__.py,sha256=IGJOStZuQ1cw7f8W40nymA7eYGDVKrWDXz5trMxsy3U,524
|
|
2
2
|
cadwyn/__main__.py,sha256=aKAwxVnhqi3ATd1UsifoLA1t3udTzz56t0BRTlktX1A,2845
|
|
3
3
|
cadwyn/_utils.py,sha256=Uh6No0FNY1AR2Z2E19fMPIU9_J4lbuG8XOQU2AlDIZw,3600
|
|
4
|
-
cadwyn/codegen.py,sha256=
|
|
4
|
+
cadwyn/codegen.py,sha256=wIQgzUrMiYsyoMu9iDRbzUy3L2RHre5FSbbDmjwrpnw,38212
|
|
5
5
|
cadwyn/exceptions.py,sha256=Utb6anOzrh97nOUgqCMmZHkQg8SFafLKSKO0EUPQ0yU,624
|
|
6
|
-
cadwyn/header.py,sha256=
|
|
6
|
+
cadwyn/header.py,sha256=2xw5wtxMQaGe2P7heSAvWu5GDHUEvWYpydZaQcKSc3s,901
|
|
7
7
|
cadwyn/main.py,sha256=pUFGHmiHk8dpS2kxUiyll0T3XTti3MPVySdTecUd38s,5282
|
|
8
8
|
cadwyn/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
cadwyn/routing.py,sha256=
|
|
9
|
+
cadwyn/routing.py,sha256=66wA0CwAnqSrZvkxDm-X443AqnCrmpHtVUGGIrC2WUI,32598
|
|
10
10
|
cadwyn/structure/__init__.py,sha256=2c6ivh7A-MQhhvovpsgiTsuk_ovYVVMWsqMqNC5QtuE,695
|
|
11
11
|
cadwyn/structure/common.py,sha256=Nc0IP4L6z_HNVFrLaeepG2NY0en2ycZndXllpgoloNg,291
|
|
12
12
|
cadwyn/structure/data.py,sha256=kzm3uf7VktH8nwShUk2hdfuuz0uYt9jzkRKMbWy0NtU,6564
|
|
13
13
|
cadwyn/structure/endpoints.py,sha256=ozpD3z8BFTThiCbj5pidjW2-r46GzZg0NipxgBmggsw,5156
|
|
14
14
|
cadwyn/structure/enums.py,sha256=iMokxA2QYJ61SzyB-Pmuq3y7KL7-e6TsnjLVUaVZQnw,954
|
|
15
15
|
cadwyn/structure/schemas.py,sha256=wpGFXzoq6qrOulEk7I_69UslapG5iD5crFLQp-kXEFQ,5241
|
|
16
|
-
cadwyn/structure/versions.py,sha256=
|
|
17
|
-
cadwyn-2.
|
|
18
|
-
cadwyn-2.
|
|
19
|
-
cadwyn-2.
|
|
20
|
-
cadwyn-2.
|
|
21
|
-
cadwyn-2.
|
|
16
|
+
cadwyn/structure/versions.py,sha256=TjRsTHkNTmxbP9WrpgbhN5mJYvkEZTl6zkp7ThjgSF0,22178
|
|
17
|
+
cadwyn-2.1.0rc0.dist-info/entry_points.txt,sha256=eO05hLn9GoRzzpwT9GONPmXKsonjuMNssM2D2WHWKGk,46
|
|
18
|
+
cadwyn-2.1.0rc0.dist-info/LICENSE,sha256=KeCWewiDQYpmSnzF-p_0YpoWiyDcUPaCuG8OWQs4ig4,1072
|
|
19
|
+
cadwyn-2.1.0rc0.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
|
|
20
|
+
cadwyn-2.1.0rc0.dist-info/METADATA,sha256=OQS1v_1qTRw-oJczL2OlbzCn5H0iDEOdzwV5WAluyu4,3807
|
|
21
|
+
cadwyn-2.1.0rc0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|