Skip to content

Commit 95a29a8

Browse files
dbantypackyg
andauthored
feat: Add allOf support for model definitions (#98) (#321)
* Add allOf support for model definitions (#98) Collapses the child elements into one, without class heirarchy, mixins, etc. * refactor: allOf support to happen in build_model_property * refactor: Clean up ModelProperty code * refactor: More test cleanup for ModelProperty * fix: Handle duplicate and conflicting properties in allOf * ci: Improve test coverage * refactor: A bit of cleanup for clarity * Merge main into benching-allof-support Co-authored-by: Packy Gallagher <[email protected]>
1 parent dc05117 commit 95a29a8

File tree

15 files changed

+876
-240
lines changed

15 files changed

+876
-240
lines changed

end_to_end_tests/golden-record/my_test_api_client/models/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
from .a_model_not_required_model import AModelNotRequiredModel
66
from .a_model_not_required_nullable_model import AModelNotRequiredNullableModel
77
from .a_model_nullable_model import AModelNullableModel
8+
from .all_of_sub_model import AllOfSubModel
89
from .an_enum import AnEnum
910
from .an_int_enum import AnIntEnum
11+
from .another_all_of_sub_model import AnotherAllOfSubModel
1012
from .body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost
1113
from .different_enum import DifferentEnum
1214
from .free_form_model import FreeFormModel
1315
from .http_validation_error import HTTPValidationError
16+
from .model_from_all_of import ModelFromAllOf
1417
from .model_with_additional_properties_inlined import ModelWithAdditionalPropertiesInlined
1518
from .model_with_additional_properties_inlined_additional_property import (
1619
ModelWithAdditionalPropertiesInlinedAdditionalProperty,

end_to_end_tests/golden-record/my_test_api_client/models/a_model_model.py

+51-2
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,77 @@
1-
from typing import Any, Dict, List, Type, TypeVar
1+
from typing import Any, Dict, List, Type, TypeVar, Union
22

33
import attr
44

5+
from ..models.an_enum import AnEnum
6+
from ..models.an_int_enum import AnIntEnum
7+
from ..types import UNSET, Unset
8+
59
T = TypeVar("T", bound="AModelModel")
610

711

812
@attr.s(auto_attribs=True)
913
class AModelModel:
1014
""" """
1115

16+
a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET
1217
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
1318

1419
def to_dict(self) -> Dict[str, Any]:
20+
a_property: Union[Unset, int, str]
21+
if isinstance(self.a_property, Unset):
22+
a_property = UNSET
23+
elif isinstance(self.a_property, AnEnum):
24+
a_property = UNSET
25+
if not isinstance(self.a_property, Unset):
26+
a_property = self.a_property.value
27+
28+
else:
29+
a_property = UNSET
30+
if not isinstance(self.a_property, Unset):
31+
a_property = self.a_property.value
1532

1633
field_dict: Dict[str, Any] = {}
1734
field_dict.update(self.additional_properties)
1835
field_dict.update({})
36+
if a_property is not UNSET:
37+
field_dict["a_property"] = a_property
1938

2039
return field_dict
2140

2241
@classmethod
2342
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
2443
d = src_dict.copy()
25-
a_model_model = cls()
44+
45+
def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]:
46+
if isinstance(data, Unset):
47+
return data
48+
try:
49+
a_property_type0: Union[Unset, AnEnum]
50+
if not isinstance(data, str):
51+
raise TypeError()
52+
a_property_type0 = UNSET
53+
_a_property_type0 = data
54+
if not isinstance(_a_property_type0, Unset):
55+
a_property_type0 = AnEnum(_a_property_type0)
56+
57+
return a_property_type0
58+
except: # noqa: E722
59+
pass
60+
if not isinstance(data, int):
61+
raise TypeError()
62+
a_property_type1: Union[Unset, AnIntEnum]
63+
a_property_type1 = UNSET
64+
_a_property_type1 = data
65+
if not isinstance(_a_property_type1, Unset):
66+
a_property_type1 = AnIntEnum(_a_property_type1)
67+
68+
return a_property_type1
69+
70+
a_property = _parse_a_property(d.pop("a_property", UNSET))
71+
72+
a_model_model = cls(
73+
a_property=a_property,
74+
)
2675

2776
a_model_model.additional_properties = d
2877
return a_model_model

end_to_end_tests/golden-record/my_test_api_client/models/a_model_not_required_model.py

+51-2
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,77 @@
1-
from typing import Any, Dict, List, Type, TypeVar
1+
from typing import Any, Dict, List, Type, TypeVar, Union
22

33
import attr
44

5+
from ..models.an_enum import AnEnum
6+
from ..models.an_int_enum import AnIntEnum
7+
from ..types import UNSET, Unset
8+
59
T = TypeVar("T", bound="AModelNotRequiredModel")
610

711

812
@attr.s(auto_attribs=True)
913
class AModelNotRequiredModel:
1014
""" """
1115

16+
a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET
1217
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
1318

1419
def to_dict(self) -> Dict[str, Any]:
20+
a_property: Union[Unset, int, str]
21+
if isinstance(self.a_property, Unset):
22+
a_property = UNSET
23+
elif isinstance(self.a_property, AnEnum):
24+
a_property = UNSET
25+
if not isinstance(self.a_property, Unset):
26+
a_property = self.a_property.value
27+
28+
else:
29+
a_property = UNSET
30+
if not isinstance(self.a_property, Unset):
31+
a_property = self.a_property.value
1532

1633
field_dict: Dict[str, Any] = {}
1734
field_dict.update(self.additional_properties)
1835
field_dict.update({})
36+
if a_property is not UNSET:
37+
field_dict["a_property"] = a_property
1938

2039
return field_dict
2140

2241
@classmethod
2342
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
2443
d = src_dict.copy()
25-
a_model_not_required_model = cls()
44+
45+
def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]:
46+
if isinstance(data, Unset):
47+
return data
48+
try:
49+
a_property_type0: Union[Unset, AnEnum]
50+
if not isinstance(data, str):
51+
raise TypeError()
52+
a_property_type0 = UNSET
53+
_a_property_type0 = data
54+
if not isinstance(_a_property_type0, Unset):
55+
a_property_type0 = AnEnum(_a_property_type0)
56+
57+
return a_property_type0
58+
except: # noqa: E722
59+
pass
60+
if not isinstance(data, int):
61+
raise TypeError()
62+
a_property_type1: Union[Unset, AnIntEnum]
63+
a_property_type1 = UNSET
64+
_a_property_type1 = data
65+
if not isinstance(_a_property_type1, Unset):
66+
a_property_type1 = AnIntEnum(_a_property_type1)
67+
68+
return a_property_type1
69+
70+
a_property = _parse_a_property(d.pop("a_property", UNSET))
71+
72+
a_model_not_required_model = cls(
73+
a_property=a_property,
74+
)
2675

2776
a_model_not_required_model.additional_properties = d
2877
return a_model_not_required_model

end_to_end_tests/golden-record/my_test_api_client/models/a_model_not_required_nullable_model.py

+51-2
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,77 @@
1-
from typing import Any, Dict, List, Type, TypeVar
1+
from typing import Any, Dict, List, Type, TypeVar, Union
22

33
import attr
44

5+
from ..models.an_enum import AnEnum
6+
from ..models.an_int_enum import AnIntEnum
7+
from ..types import UNSET, Unset
8+
59
T = TypeVar("T", bound="AModelNotRequiredNullableModel")
610

711

812
@attr.s(auto_attribs=True)
913
class AModelNotRequiredNullableModel:
1014
""" """
1115

16+
a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET
1217
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
1318

1419
def to_dict(self) -> Dict[str, Any]:
20+
a_property: Union[Unset, int, str]
21+
if isinstance(self.a_property, Unset):
22+
a_property = UNSET
23+
elif isinstance(self.a_property, AnEnum):
24+
a_property = UNSET
25+
if not isinstance(self.a_property, Unset):
26+
a_property = self.a_property.value
27+
28+
else:
29+
a_property = UNSET
30+
if not isinstance(self.a_property, Unset):
31+
a_property = self.a_property.value
1532

1633
field_dict: Dict[str, Any] = {}
1734
field_dict.update(self.additional_properties)
1835
field_dict.update({})
36+
if a_property is not UNSET:
37+
field_dict["a_property"] = a_property
1938

2039
return field_dict
2140

2241
@classmethod
2342
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
2443
d = src_dict.copy()
25-
a_model_not_required_nullable_model = cls()
44+
45+
def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]:
46+
if isinstance(data, Unset):
47+
return data
48+
try:
49+
a_property_type0: Union[Unset, AnEnum]
50+
if not isinstance(data, str):
51+
raise TypeError()
52+
a_property_type0 = UNSET
53+
_a_property_type0 = data
54+
if not isinstance(_a_property_type0, Unset):
55+
a_property_type0 = AnEnum(_a_property_type0)
56+
57+
return a_property_type0
58+
except: # noqa: E722
59+
pass
60+
if not isinstance(data, int):
61+
raise TypeError()
62+
a_property_type1: Union[Unset, AnIntEnum]
63+
a_property_type1 = UNSET
64+
_a_property_type1 = data
65+
if not isinstance(_a_property_type1, Unset):
66+
a_property_type1 = AnIntEnum(_a_property_type1)
67+
68+
return a_property_type1
69+
70+
a_property = _parse_a_property(d.pop("a_property", UNSET))
71+
72+
a_model_not_required_nullable_model = cls(
73+
a_property=a_property,
74+
)
2675

2776
a_model_not_required_nullable_model.additional_properties = d
2877
return a_model_not_required_nullable_model

end_to_end_tests/golden-record/my_test_api_client/models/a_model_nullable_model.py

+51-2
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,77 @@
1-
from typing import Any, Dict, List, Type, TypeVar
1+
from typing import Any, Dict, List, Type, TypeVar, Union
22

33
import attr
44

5+
from ..models.an_enum import AnEnum
6+
from ..models.an_int_enum import AnIntEnum
7+
from ..types import UNSET, Unset
8+
59
T = TypeVar("T", bound="AModelNullableModel")
610

711

812
@attr.s(auto_attribs=True)
913
class AModelNullableModel:
1014
""" """
1115

16+
a_property: Union[AnEnum, AnIntEnum, Unset] = UNSET
1217
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
1318

1419
def to_dict(self) -> Dict[str, Any]:
20+
a_property: Union[Unset, int, str]
21+
if isinstance(self.a_property, Unset):
22+
a_property = UNSET
23+
elif isinstance(self.a_property, AnEnum):
24+
a_property = UNSET
25+
if not isinstance(self.a_property, Unset):
26+
a_property = self.a_property.value
27+
28+
else:
29+
a_property = UNSET
30+
if not isinstance(self.a_property, Unset):
31+
a_property = self.a_property.value
1532

1633
field_dict: Dict[str, Any] = {}
1734
field_dict.update(self.additional_properties)
1835
field_dict.update({})
36+
if a_property is not UNSET:
37+
field_dict["a_property"] = a_property
1938

2039
return field_dict
2140

2241
@classmethod
2342
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
2443
d = src_dict.copy()
25-
a_model_nullable_model = cls()
44+
45+
def _parse_a_property(data: object) -> Union[AnEnum, AnIntEnum, Unset]:
46+
if isinstance(data, Unset):
47+
return data
48+
try:
49+
a_property_type0: Union[Unset, AnEnum]
50+
if not isinstance(data, str):
51+
raise TypeError()
52+
a_property_type0 = UNSET
53+
_a_property_type0 = data
54+
if not isinstance(_a_property_type0, Unset):
55+
a_property_type0 = AnEnum(_a_property_type0)
56+
57+
return a_property_type0
58+
except: # noqa: E722
59+
pass
60+
if not isinstance(data, int):
61+
raise TypeError()
62+
a_property_type1: Union[Unset, AnIntEnum]
63+
a_property_type1 = UNSET
64+
_a_property_type1 = data
65+
if not isinstance(_a_property_type1, Unset):
66+
a_property_type1 = AnIntEnum(_a_property_type1)
67+
68+
return a_property_type1
69+
70+
a_property = _parse_a_property(d.pop("a_property", UNSET))
71+
72+
a_model_nullable_model = cls(
73+
a_property=a_property,
74+
)
2675

2776
a_model_nullable_model.additional_properties = d
2877
return a_model_nullable_model
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import Any, Dict, List, Type, TypeVar, Union
2+
3+
import attr
4+
5+
from ..types import UNSET, Unset
6+
7+
T = TypeVar("T", bound="AllOfSubModel")
8+
9+
10+
@attr.s(auto_attribs=True)
11+
class AllOfSubModel:
12+
""" """
13+
14+
a_sub_property: Union[Unset, str] = UNSET
15+
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
16+
17+
def to_dict(self) -> Dict[str, Any]:
18+
a_sub_property = self.a_sub_property
19+
20+
field_dict: Dict[str, Any] = {}
21+
field_dict.update(self.additional_properties)
22+
field_dict.update({})
23+
if a_sub_property is not UNSET:
24+
field_dict["a_sub_property"] = a_sub_property
25+
26+
return field_dict
27+
28+
@classmethod
29+
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
30+
d = src_dict.copy()
31+
a_sub_property = d.pop("a_sub_property", UNSET)
32+
33+
all_of_sub_model = cls(
34+
a_sub_property=a_sub_property,
35+
)
36+
37+
all_of_sub_model.additional_properties = d
38+
return all_of_sub_model
39+
40+
@property
41+
def additional_keys(self) -> List[str]:
42+
return list(self.additional_properties.keys())
43+
44+
def __getitem__(self, key: str) -> Any:
45+
return self.additional_properties[key]
46+
47+
def __setitem__(self, key: str, value: Any) -> None:
48+
self.additional_properties[key] = value
49+
50+
def __delitem__(self, key: str) -> None:
51+
del self.additional_properties[key]
52+
53+
def __contains__(self, key: str) -> bool:
54+
return key in self.additional_properties

0 commit comments

Comments
 (0)