Skip to content

Commit 20eed9e

Browse files
dbantypackyg
andauthored
Fix additionalProperty Union spacing and construction (#266) (#273)
* Fix indentation of union-ed addtionalProperties * Fix instance check for lists in unions * Handle non-templated union values separately from ones with templates * Add ModelWithAnyJsonProperties to e2e tests * Union Property - use `data` from inner function when returning primitive values Co-authored-by: Packy Gallagher <[email protected]>
1 parent e2d6e27 commit 20eed9e

File tree

16 files changed

+363
-33
lines changed

16 files changed

+363
-33
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## 0.7.3 - Unreleased
9+
### Fixes
10+
- Spacing and extra returns for Union types of `additionalProperties` (#266 & #268). Thanks @joshzana & @packyg!
11+
812
## 0.7.2 - 2020-12-08
913
### Fixes
1014
- A bug in handling optional properties that are themselves models (introduced in 0.7.1) (#262). Thanks @packyg!

end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,20 @@ def httpx_request(
7171
json_union_prop: Union[Unset, float, str]
7272
if isinstance(union_prop, Unset):
7373
json_union_prop = UNSET
74-
elif isinstance(union_prop, float):
75-
json_union_prop = union_prop
7674
else:
7775
json_union_prop = union_prop
7876

7977
json_union_prop_with_ref: Union[Unset, float, AnEnum]
8078
if isinstance(union_prop_with_ref, Unset):
8179
json_union_prop_with_ref = UNSET
82-
elif isinstance(union_prop_with_ref, float):
83-
json_union_prop_with_ref = union_prop_with_ref
84-
else:
80+
elif isinstance(union_prop_with_ref, AnEnum):
8581
json_union_prop_with_ref = UNSET
8682
if not isinstance(union_prop_with_ref, Unset):
8783
json_union_prop_with_ref = union_prop_with_ref
8884

85+
else:
86+
json_union_prop_with_ref = union_prop_with_ref
87+
8988
json_enum_prop: Union[Unset, AnEnum] = UNSET
9089
if not isinstance(enum_prop, Unset):
9190
json_enum_prop = enum_prop

end_to_end_tests/golden-record-custom/custom_e2e/models/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
ModelWithAdditionalPropertiesInlinedAdditionalProperty,
1313
)
1414
from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed
15+
from .model_with_any_json_properties import ModelWithAnyJsonProperties
16+
from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty
1517
from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties
1618
from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder
1719
from .model_with_union_property import ModelWithUnionProperty
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from typing import Any, Dict, List, Union, cast
2+
3+
import attr
4+
5+
from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty
6+
from ..types import Unset
7+
8+
9+
@attr.s(auto_attribs=True)
10+
class ModelWithAnyJsonProperties:
11+
""" """
12+
13+
additional_properties: Dict[
14+
str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]
15+
] = attr.ib(init=False, factory=dict)
16+
17+
def to_dict(self) -> Dict[str, Any]:
18+
19+
field_dict: Dict[str, Any] = {}
20+
for prop_name, prop in self.additional_properties.items():
21+
if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty):
22+
field_dict[prop_name] = prop.to_dict()
23+
24+
elif isinstance(prop, list):
25+
field_dict[prop_name] = prop
26+
27+
else:
28+
field_dict[prop_name] = prop
29+
30+
field_dict.update({})
31+
32+
return field_dict
33+
34+
@staticmethod
35+
def from_dict(src_dict: Dict[str, Any]) -> "ModelWithAnyJsonProperties":
36+
d = src_dict.copy()
37+
model_with_any_json_properties = ModelWithAnyJsonProperties()
38+
39+
additional_properties = {}
40+
for prop_name, prop_dict in d.items():
41+
42+
def _parse_additional_property(
43+
data: Any,
44+
) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]:
45+
data = None if isinstance(data, Unset) else data
46+
additional_property: Union[
47+
ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool
48+
]
49+
try:
50+
additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data)
51+
52+
return additional_property
53+
except: # noqa: E722
54+
pass
55+
try:
56+
additional_property = cast(List[str], data)
57+
58+
return additional_property
59+
except: # noqa: E722
60+
pass
61+
return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data)
62+
63+
additional_property = _parse_additional_property(prop_dict)
64+
65+
additional_properties[prop_name] = additional_property
66+
67+
model_with_any_json_properties.additional_properties = additional_properties
68+
return model_with_any_json_properties
69+
70+
@property
71+
def additional_keys(self) -> List[str]:
72+
return list(self.additional_properties.keys())
73+
74+
def __getitem__(
75+
self, key: str
76+
) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]:
77+
return self.additional_properties[key]
78+
79+
def __setitem__(
80+
self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]
81+
) -> None:
82+
self.additional_properties[key] = value
83+
84+
def __delitem__(self, key: str) -> None:
85+
del self.additional_properties[key]
86+
87+
def __contains__(self, key: str) -> bool:
88+
return key in self.additional_properties
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import Any, Dict, List
2+
3+
import attr
4+
5+
6+
@attr.s(auto_attribs=True)
7+
class ModelWithAnyJsonPropertiesAdditionalProperty:
8+
""" """
9+
10+
additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict)
11+
12+
def to_dict(self) -> Dict[str, Any]:
13+
14+
field_dict: Dict[str, Any] = {}
15+
field_dict.update(self.additional_properties)
16+
field_dict.update({})
17+
18+
return field_dict
19+
20+
@staticmethod
21+
def from_dict(src_dict: Dict[str, Any]) -> "ModelWithAnyJsonPropertiesAdditionalProperty":
22+
d = src_dict.copy()
23+
model_with_any_json_properties_additional_property = ModelWithAnyJsonPropertiesAdditionalProperty()
24+
25+
model_with_any_json_properties_additional_property.additional_properties = d
26+
return model_with_any_json_properties_additional_property
27+
28+
@property
29+
def additional_keys(self) -> List[str]:
30+
return list(self.additional_properties.keys())
31+
32+
def __getitem__(self, key: str) -> str:
33+
return self.additional_properties[key]
34+
35+
def __setitem__(self, key: str, value: str) -> None:
36+
self.additional_properties[key] = value
37+
38+
def __delitem__(self, key: str) -> None:
39+
del self.additional_properties[key]
40+
41+
def __contains__(self, key: str) -> bool:
42+
return key in self.additional_properties

end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,20 @@ def _get_kwargs(
4747
json_union_prop: Union[Unset, float, str]
4848
if isinstance(union_prop, Unset):
4949
json_union_prop = UNSET
50-
elif isinstance(union_prop, float):
51-
json_union_prop = union_prop
5250
else:
5351
json_union_prop = union_prop
5452

5553
json_union_prop_with_ref: Union[Unset, float, AnEnum]
5654
if isinstance(union_prop_with_ref, Unset):
5755
json_union_prop_with_ref = UNSET
58-
elif isinstance(union_prop_with_ref, float):
59-
json_union_prop_with_ref = union_prop_with_ref
60-
else:
56+
elif isinstance(union_prop_with_ref, AnEnum):
6157
json_union_prop_with_ref = UNSET
6258
if not isinstance(union_prop_with_ref, Unset):
6359
json_union_prop_with_ref = union_prop_with_ref
6460

61+
else:
62+
json_union_prop_with_ref = union_prop_with_ref
63+
6564
json_enum_prop: Union[Unset, AnEnum] = UNSET
6665
if not isinstance(enum_prop, Unset):
6766
json_enum_prop = enum_prop

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

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
ModelWithAdditionalPropertiesInlinedAdditionalProperty,
1313
)
1414
from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed
15+
from .model_with_any_json_properties import ModelWithAnyJsonProperties
16+
from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty
1517
from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties
1618
from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder
1719
from .model_with_union_property import ModelWithUnionProperty
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from typing import Any, Dict, List, Union, cast
2+
3+
import attr
4+
5+
from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty
6+
from ..types import Unset
7+
8+
9+
@attr.s(auto_attribs=True)
10+
class ModelWithAnyJsonProperties:
11+
""" """
12+
13+
additional_properties: Dict[
14+
str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]
15+
] = attr.ib(init=False, factory=dict)
16+
17+
def to_dict(self) -> Dict[str, Any]:
18+
19+
field_dict: Dict[str, Any] = {}
20+
for prop_name, prop in self.additional_properties.items():
21+
if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty):
22+
field_dict[prop_name] = prop.to_dict()
23+
24+
elif isinstance(prop, list):
25+
field_dict[prop_name] = prop
26+
27+
else:
28+
field_dict[prop_name] = prop
29+
30+
field_dict.update({})
31+
32+
return field_dict
33+
34+
@staticmethod
35+
def from_dict(src_dict: Dict[str, Any]) -> "ModelWithAnyJsonProperties":
36+
d = src_dict.copy()
37+
model_with_any_json_properties = ModelWithAnyJsonProperties()
38+
39+
additional_properties = {}
40+
for prop_name, prop_dict in d.items():
41+
42+
def _parse_additional_property(
43+
data: Any,
44+
) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]:
45+
data = None if isinstance(data, Unset) else data
46+
additional_property: Union[
47+
ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool
48+
]
49+
try:
50+
additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data)
51+
52+
return additional_property
53+
except: # noqa: E722
54+
pass
55+
try:
56+
additional_property = cast(List[str], data)
57+
58+
return additional_property
59+
except: # noqa: E722
60+
pass
61+
return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data)
62+
63+
additional_property = _parse_additional_property(prop_dict)
64+
65+
additional_properties[prop_name] = additional_property
66+
67+
model_with_any_json_properties.additional_properties = additional_properties
68+
return model_with_any_json_properties
69+
70+
@property
71+
def additional_keys(self) -> List[str]:
72+
return list(self.additional_properties.keys())
73+
74+
def __getitem__(
75+
self, key: str
76+
) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]:
77+
return self.additional_properties[key]
78+
79+
def __setitem__(
80+
self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]
81+
) -> None:
82+
self.additional_properties[key] = value
83+
84+
def __delitem__(self, key: str) -> None:
85+
del self.additional_properties[key]
86+
87+
def __contains__(self, key: str) -> bool:
88+
return key in self.additional_properties
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import Any, Dict, List
2+
3+
import attr
4+
5+
6+
@attr.s(auto_attribs=True)
7+
class ModelWithAnyJsonPropertiesAdditionalProperty:
8+
""" """
9+
10+
additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict)
11+
12+
def to_dict(self) -> Dict[str, Any]:
13+
14+
field_dict: Dict[str, Any] = {}
15+
field_dict.update(self.additional_properties)
16+
field_dict.update({})
17+
18+
return field_dict
19+
20+
@staticmethod
21+
def from_dict(src_dict: Dict[str, Any]) -> "ModelWithAnyJsonPropertiesAdditionalProperty":
22+
d = src_dict.copy()
23+
model_with_any_json_properties_additional_property = ModelWithAnyJsonPropertiesAdditionalProperty()
24+
25+
model_with_any_json_properties_additional_property.additional_properties = d
26+
return model_with_any_json_properties_additional_property
27+
28+
@property
29+
def additional_keys(self) -> List[str]:
30+
return list(self.additional_properties.keys())
31+
32+
def __getitem__(self, key: str) -> str:
33+
return self.additional_properties[key]
34+
35+
def __setitem__(self, key: str, value: str) -> None:
36+
self.additional_properties[key] = value
37+
38+
def __delitem__(self, key: str) -> None:
39+
del self.additional_properties[key]
40+
41+
def __contains__(self, key: str) -> bool:
42+
return key in self.additional_properties

end_to_end_tests/openapi.json

+32
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,38 @@
806806
"additionalProperties": {
807807
"$ref": "#/components/schemas/AnEnum"
808808
}
809+
},
810+
"ModelWithAnyJsonProperties": {
811+
"title": "ModelWithAnyJsonProperties",
812+
"type": "object",
813+
"additionalProperties": {
814+
"anyOf": [
815+
{
816+
"type": "object",
817+
"additionalProperties": {
818+
"type": "string"
819+
}
820+
},
821+
{
822+
"type": "array",
823+
"items": {
824+
"type": "string"
825+
}
826+
},
827+
{
828+
"type": "string"
829+
},
830+
{
831+
"type": "number"
832+
},
833+
{
834+
"type": "integer"
835+
},
836+
{
837+
"type": "boolean"
838+
}
839+
]
840+
}
809841
}
810842
}
811843
}

0 commit comments

Comments
 (0)