Skip to content

Commit 7bb7832

Browse files
committed
Add end-to-end tests and proposed fixes to nullable array support
1 parent bbef24d commit 7bb7832

File tree

5 files changed

+85
-12
lines changed

5 files changed

+85
-12
lines changed

end_to_end_tests/baseline_openapi_3.0.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1778,9 +1778,10 @@
17781778
},
17791779
"some_array": {
17801780
"title": "Some Array",
1781+
"nullable": true,
17811782
"type": "array",
17821783
"items": {
1783-
"type": "number"
1784+
"$ref": "#/components/schemas/AFormData"
17841785
}
17851786
},
17861787
"some_object": {

end_to_end_tests/baseline_openapi_3.1.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,9 +1794,9 @@ info:
17941794
},
17951795
"some_array": {
17961796
"title": "Some Array",
1797-
"type": "array",
1797+
"type": [ "array", "null" ],
17981798
"items": {
1799-
"type": "number"
1799+
"$ref": "#/components/schemas/AFormData"
18001800
}
18011801
},
18021802
"some_object": {

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

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ..types import UNSET, File, FileJsonType, Unset
1212

1313
if TYPE_CHECKING:
14+
from ..models.a_form_data import AFormData
1415
from ..models.body_upload_file_tests_upload_post_additional_property import (
1516
BodyUploadFileTestsUploadPostAdditionalProperty,
1617
)
@@ -38,7 +39,7 @@ class BodyUploadFileTestsUploadPost:
3839
a_datetime (Union[Unset, datetime.datetime]):
3940
a_date (Union[Unset, datetime.date]):
4041
some_number (Union[Unset, float]):
41-
some_array (Union[Unset, List[float]]):
42+
some_array (Union[List['AFormData'], None, Unset]):
4243
some_optional_object (Union[Unset, BodyUploadFileTestsUploadPostSomeOptionalObject]):
4344
some_enum (Union[Unset, DifferentEnum]): An enumeration.
4445
"""
@@ -51,7 +52,7 @@ class BodyUploadFileTestsUploadPost:
5152
a_datetime: Union[Unset, datetime.datetime] = UNSET
5253
a_date: Union[Unset, datetime.date] = UNSET
5354
some_number: Union[Unset, float] = UNSET
54-
some_array: Union[Unset, List[float]] = UNSET
55+
some_array: Union[List["AFormData"], None, Unset] = UNSET
5556
some_optional_object: Union[Unset, "BodyUploadFileTestsUploadPostSomeOptionalObject"] = UNSET
5657
some_enum: Union[Unset, DifferentEnum] = UNSET
5758
additional_properties: Dict[str, "BodyUploadFileTestsUploadPostAdditionalProperty"] = _attrs_field(
@@ -89,8 +90,18 @@ def to_dict(self) -> Dict[str, Any]:
8990

9091
some_number = self.some_number
9192

92-
some_array: Union[Unset, List[float]] = UNSET
93-
if not isinstance(self.some_array, Unset):
93+
some_array: Union[List[Dict[str, Any]], None, Unset]
94+
if isinstance(self.some_array, Unset):
95+
some_array = UNSET
96+
elif isinstance(self.some_array, list):
97+
some_array = UNSET
98+
if not isinstance(self.some_array, Unset):
99+
some_array = []
100+
for some_array_type_0_item_data in self.some_array:
101+
some_array_type_0_item = some_array_type_0_item_data.to_dict()
102+
some_array.append(some_array_type_0_item)
103+
104+
else:
94105
some_array = self.some_array
95106

96107
some_optional_object: Union[Unset, Dict[str, Any]] = UNSET
@@ -165,10 +176,20 @@ def to_multipart(self) -> Dict[str, Any]:
165176
else (None, str(self.some_number).encode(), "text/plain")
166177
)
167178

168-
some_array: Union[Unset, Tuple[None, bytes, str]] = UNSET
169-
if not isinstance(self.some_array, Unset):
170-
_temp_some_array = self.some_array
171-
some_array = (None, json.dumps(_temp_some_array).encode(), "application/json")
179+
some_array: Union[None, Tuple[None, bytes, str], Unset]
180+
if isinstance(self.some_array, Unset):
181+
some_array = UNSET
182+
elif isinstance(self.some_array, list):
183+
some_array = UNSET
184+
if not isinstance(self.some_array, Unset):
185+
_temp_some_array = []
186+
for some_array_type_0_item_data in self.some_array:
187+
some_array_type_0_item = some_array_type_0_item_data.to_dict()
188+
_temp_some_array.append(some_array_type_0_item)
189+
some_array = (None, json.dumps(_temp_some_array).encode(), "application/json")
190+
191+
else:
192+
some_array = self.some_array
172193

173194
some_optional_object: Union[Unset, Tuple[None, bytes, str]] = UNSET
174195
if not isinstance(self.some_optional_object, Unset):
@@ -209,6 +230,7 @@ def to_multipart(self) -> Dict[str, Any]:
209230

210231
@classmethod
211232
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
233+
from ..models.a_form_data import AFormData
212234
from ..models.body_upload_file_tests_upload_post_additional_property import (
213235
BodyUploadFileTestsUploadPostAdditionalProperty,
214236
)
@@ -265,7 +287,27 @@ def _parse_some_nullable_object(data: object) -> Union["BodyUploadFileTestsUploa
265287

266288
some_number = d.pop("some_number", UNSET)
267289

268-
some_array = cast(List[float], d.pop("some_array", UNSET))
290+
def _parse_some_array(data: object) -> Union[List["AFormData"], None, Unset]:
291+
if data is None:
292+
return data
293+
if isinstance(data, Unset):
294+
return data
295+
try:
296+
if not isinstance(data, list):
297+
raise TypeError()
298+
some_array_type_0 = []
299+
_some_array_type_0 = data
300+
for some_array_type_0_item_data in _some_array_type_0 or []:
301+
some_array_type_0_item = AFormData.from_dict(some_array_type_0_item_data)
302+
303+
some_array_type_0.append(some_array_type_0_item)
304+
305+
return some_array_type_0
306+
except: # noqa: E722
307+
pass
308+
return cast(Union[List["AFormData"], None, Unset], data)
309+
310+
some_array = _parse_some_array(d.pop("some_array", UNSET))
269311

270312
_some_optional_object = d.pop("some_optional_object", UNSET)
271313
some_optional_object: Union[Unset, BodyUploadFileTestsUploadPostSomeOptionalObject]

openapi_python_client/parser/properties/list_property.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,30 @@ def get_lazy_imports(self, *, prefix: str) -> set[str]:
116116
lazy_imports = super().get_lazy_imports(prefix=prefix)
117117
lazy_imports.update(self.inner_property.get_lazy_imports(prefix=prefix))
118118
return lazy_imports
119+
120+
def get_type_string(
121+
self,
122+
no_optional: bool = False,
123+
json: bool = False,
124+
*,
125+
multipart: bool = False,
126+
quoted: bool = False,
127+
) -> str:
128+
"""
129+
Get a string representation of type that should be used when declaring this property
130+
131+
Args:
132+
no_optional: Do not include Optional or Unset even if the value is optional (needed for isinstance checks)
133+
json: True if the type refers to the property after JSON serialization
134+
"""
135+
if json:
136+
type_string = self.get_base_json_type_string()
137+
elif multipart:
138+
type_string = "Tuple[None, bytes, str]"
139+
else:
140+
type_string = self.get_base_type_string()
141+
142+
if no_optional or self.required:
143+
return type_string
144+
return f"Union[Unset, {type_string}]"
145+

openapi_python_client/templates/property_templates/list_property.py.jinja

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
{% import "property_templates/" + inner_property.template as inner_template %}
44
{% if inner_template.construct %}
55
{% set inner_source = inner_property.python_name + "_data" %}
6+
{% if initial_value == "UNSET" %}
7+
{% set initial_value = "[]" %}
8+
{% endif %}
69
{{ property.python_name }} = {{ initial_value }}
710
_{{ property.python_name }} = {{ source }}
811
{% if property.required %}

0 commit comments

Comments
 (0)