Skip to content

Commit 0a5d7f8

Browse files
author
Constantinos Symeonides
committed
fix: Non-string multipart fields must be stringified
1 parent 4a843fc commit 0a5d7f8

File tree

6 files changed

+127
-3
lines changed

6 files changed

+127
-3
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
from typing import Any, Dict, Optional, Union
23

34
import httpx
@@ -27,8 +28,10 @@ def _get_kwargs(
2728
for key, value in multipart_data.to_dict().items():
2829
if is_file(value):
2930
files[key] = value
30-
else:
31+
elif isinstance(value, str):
3132
data[key] = value
33+
else:
34+
data[key] = json.dumps(value)
3235

3336
return {
3437
"url": url,

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

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .an_int_enum import AnIntEnum
88
from .another_all_of_sub_model import AnotherAllOfSubModel
99
from .body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost
10+
from .body_upload_file_tests_upload_post_some_object import BodyUploadFileTestsUploadPostSomeObject
1011
from .different_enum import DifferentEnum
1112
from .free_form_model import FreeFormModel
1213
from .http_validation_error import HTTPValidationError

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

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from io import BytesIO
2-
from typing import Any, Dict, Type, TypeVar, Union
2+
from typing import Any, Dict, List, Type, TypeVar, Union, cast
33

44
import attr
55

6+
from ..models.body_upload_file_tests_upload_post_some_object import BodyUploadFileTestsUploadPostSomeObject
67
from ..types import UNSET, File, FileJsonType, Unset
78

89
T = TypeVar("T", bound="BodyUploadFileTestsUploadPost")
@@ -15,6 +16,9 @@ class BodyUploadFileTestsUploadPost:
1516
some_file: File
1617
some_optional_file: Union[Unset, File] = UNSET
1718
some_string: Union[Unset, str] = "some_default_string"
19+
some_number: Union[Unset, float] = UNSET
20+
some_array: Union[Unset, List[float]] = UNSET
21+
some_object: Union[Unset, BodyUploadFileTestsUploadPostSomeObject] = UNSET
1822

1923
def to_dict(self) -> Dict[str, Any]:
2024
some_file = self.some_file.to_tuple()
@@ -24,6 +28,14 @@ def to_dict(self) -> Dict[str, Any]:
2428
some_optional_file = self.some_optional_file.to_tuple()
2529

2630
some_string = self.some_string
31+
some_number = self.some_number
32+
some_array: Union[Unset, List[float]] = UNSET
33+
if not isinstance(self.some_array, Unset):
34+
some_array = self.some_array
35+
36+
some_object: Union[Unset, Dict[str, Any]] = UNSET
37+
if not isinstance(self.some_object, Unset):
38+
some_object = self.some_object.to_dict()
2739

2840
field_dict: Dict[str, Any] = {}
2941
field_dict.update(
@@ -35,6 +47,12 @@ def to_dict(self) -> Dict[str, Any]:
3547
field_dict["some_optional_file"] = some_optional_file
3648
if some_string is not UNSET:
3749
field_dict["some_string"] = some_string
50+
if some_number is not UNSET:
51+
field_dict["some_number"] = some_number
52+
if some_array is not UNSET:
53+
field_dict["some_array"] = some_array
54+
if some_object is not UNSET:
55+
field_dict["some_object"] = some_object
3856

3957
return field_dict
4058

@@ -50,10 +68,22 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
5068

5169
some_string = d.pop("some_string", UNSET)
5270

71+
some_number = d.pop("some_number", UNSET)
72+
73+
some_array = cast(List[float], d.pop("some_array", UNSET))
74+
75+
some_object: Union[Unset, BodyUploadFileTestsUploadPostSomeObject] = UNSET
76+
_some_object = d.pop("some_object", UNSET)
77+
if not isinstance(_some_object, Unset):
78+
some_object = BodyUploadFileTestsUploadPostSomeObject.from_dict(_some_object)
79+
5380
body_upload_file_tests_upload_post = cls(
5481
some_file=some_file,
5582
some_optional_file=some_optional_file,
5683
some_string=some_string,
84+
some_number=some_number,
85+
some_array=some_array,
86+
some_object=some_object,
5787
)
5888

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

end_to_end_tests/openapi.json

+24
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,30 @@
981981
"title": "Some String",
982982
"type": "string",
983983
"default": "some_default_string"
984+
},
985+
"some_number": {
986+
"title": "Some Number",
987+
"type": "number"
988+
},
989+
"some_array": {
990+
"title": "Some Array",
991+
"type": "array",
992+
"items": {
993+
"type": "number"
994+
}
995+
},
996+
"some_object": {
997+
"title": "Some Object",
998+
"type": "object",
999+
"required": ["num", "text"],
1000+
"properties": {
1001+
"num": {
1002+
"type": "number"
1003+
},
1004+
"text": {
1005+
"type": "string"
1006+
}
1007+
}
9841008
}
9851009
},
9861010
"additionalProperties": false

openapi_python_client/templates/endpoint_module.py.jinja

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from typing import Any, Dict, List, Optional, Union, cast
22

33
import httpx
4+
{% if endpoint.multipart_body_class %}
5+
import json
6+
{% endif %}
7+
48
from attr import asdict
59

610
from ...client import AuthenticatedClient, Client
@@ -42,8 +46,10 @@ def _get_kwargs(
4246
for key, value in multipart_data.to_dict().items():
4347
if is_file(value):
4448
files[key] = value
45-
else:
49+
elif isinstance(value, str):
4650
data[key] = value
51+
else:
52+
data[key] = json.dumps(value)
4753
{% endif %}
4854

4955
return {

0 commit comments

Comments
 (0)