Skip to content

Commit e798afe

Browse files
committed
Clean up body generation code
1 parent 1822f6d commit e798afe

File tree

52 files changed

+212
-472
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+212
-472
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
default: major
3+
---
4+
5+
# Removed ability to set an array as a multipart body
6+
7+
Previously, when defining a request's body as `multipart/form-data`, the generator would attempt to generate code
8+
for both `object` schemas and `array` schemas. However, most arrays could not generate valid multipart bodies, as
9+
there would be no field names (required to set the `Content-Disposition` headers).
10+
11+
The code to generate any body for `multipart/form-data` where the schema is `array` has been removed, and any such
12+
bodies will be skipped. This is not _expected_ to be a breaking change in practice, since the code generated would
13+
probably never work.
14+
15+
If you have a use-case for `multipart/form-data` with an `array` schema, please [open a new discussion](https://github.com/openapi-generators/openapi-python-client/discussions) with an example schema and the desired functional Python code.

end_to_end_tests/baseline_openapi_3.0.json

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -431,51 +431,6 @@
431431
}
432432
}
433433
},
434-
"/tests/upload/multiple": {
435-
"post": {
436-
"tags": [
437-
"tests"
438-
],
439-
"summary": "Upload multiple files",
440-
"description": "Upload several files in the same request",
441-
"operationId": "upload_multiple_files_tests_upload_post",
442-
"parameters": [],
443-
"requestBody": {
444-
"content": {
445-
"multipart/form-data": {
446-
"schema": {
447-
"type": "array",
448-
"items": {
449-
"type": "string",
450-
"format": "binary"
451-
}
452-
}
453-
}
454-
},
455-
"required": true
456-
},
457-
"responses": {
458-
"200": {
459-
"description": "Successful Response",
460-
"content": {
461-
"application/json": {
462-
"schema": {}
463-
}
464-
}
465-
},
466-
"422": {
467-
"description": "Validation Error",
468-
"content": {
469-
"application/json": {
470-
"schema": {
471-
"$ref": "#/components/schemas/HTTPValidationError"
472-
}
473-
}
474-
}
475-
}
476-
}
477-
}
478-
},
479434
"/tests/json_body": {
480435
"post": {
481436
"tags": [

end_to_end_tests/baseline_openapi_3.1.yaml

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -418,51 +418,6 @@ info:
418418
}
419419
}
420420
},
421-
"/tests/upload/multiple": {
422-
"post": {
423-
"tags": [
424-
"tests"
425-
],
426-
"summary": "Upload multiple files",
427-
"description": "Upload several files in the same request",
428-
"operationId": "upload_multiple_files_tests_upload_post",
429-
"parameters": [ ],
430-
"requestBody": {
431-
"content": {
432-
"multipart/form-data": {
433-
"schema": {
434-
"type": "array",
435-
"items": {
436-
"type": "string",
437-
"format": "binary"
438-
}
439-
}
440-
}
441-
},
442-
"required": true
443-
},
444-
"responses": {
445-
"200": {
446-
"description": "Successful Response",
447-
"content": {
448-
"application/json": {
449-
"schema": { }
450-
}
451-
}
452-
},
453-
"422": {
454-
"description": "Validation Error",
455-
"content": {
456-
"application/json": {
457-
"schema": {
458-
"$ref": "#/components/schemas/HTTPValidationError"
459-
}
460-
}
461-
}
462-
}
463-
}
464-
}
465-
},
466421
"/tests/json_body": {
467422
"post": {
468423
"tags": [

end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/tests/__init__.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
token_with_cookie_auth_token_with_cookie_get,
2222
unsupported_content_tests_unsupported_content_get,
2323
upload_file_tests_upload_post,
24-
upload_multiple_files_tests_upload_post,
2524
)
2625

2726

@@ -82,13 +81,6 @@ def upload_file_tests_upload_post(cls) -> types.ModuleType:
8281
"""
8382
return upload_file_tests_upload_post
8483

85-
@classmethod
86-
def upload_multiple_files_tests_upload_post(cls) -> types.ModuleType:
87-
"""
88-
Upload several files in the same request
89-
"""
90-
return upload_multiple_files_tests_upload_post
91-
9284
@classmethod
9385
def json_body_tests_json_body_post(cls) -> types.ModuleType:
9486
"""

end_to_end_tests/docstrings-on-attributes-golden-record/my_test_api_client/types.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""Contains some shared types for properties"""
22

3-
from collections.abc import MutableMapping
3+
from collections.abc import Mapping, MutableMapping
44
from http import HTTPStatus
5-
from typing import BinaryIO, Generic, Literal, Optional, TypeVar
5+
from typing import IO, BinaryIO, Generic, Literal, Optional, TypeVar, Union
66

77
from attrs import define
88

@@ -14,7 +14,15 @@ def __bool__(self) -> Literal[False]:
1414

1515
UNSET: Unset = Unset()
1616

17-
FileJsonType = tuple[Optional[str], BinaryIO, Optional[str]]
17+
# The types that `httpx.Client(files=)` can accept, copied from that library.
18+
FileContent = Union[IO[bytes], bytes, str]
19+
FileTypes = Union[
20+
# (filename, file (or bytes), content_type)
21+
tuple[Optional[str], FileContent, Optional[str]],
22+
# (filename, file (or bytes), content_type, headers)
23+
tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]],
24+
]
25+
RequestFiles = list[tuple[str, FileTypes]]
1826

1927

2028
@define
@@ -25,7 +33,7 @@ class File:
2533
file_name: Optional[str] = None
2634
mime_type: Optional[str] = None
2735

28-
def to_tuple(self) -> FileJsonType:
36+
def to_tuple(self) -> FileTypes:
2937
"""Return a tuple representation that httpx will accept for multipart/form-data"""
3038
return self.file_name, self.payload, self.mime_type
3139

@@ -43,4 +51,4 @@ class Response(Generic[T]):
4351
parsed: Optional[T]
4452

4553

46-
__all__ = ["UNSET", "File", "FileJsonType", "Response", "Unset"]
54+
__all__ = ["UNSET", "File", "FileTypes", "RequestFiles", "Response", "Unset"]

end_to_end_tests/golden-record/my_test_api_client/api/bodies/json_like.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ def _get_kwargs(
2020
"url": "/bodies/json-like",
2121
}
2222

23-
_body = body.to_dict()
23+
_kwargs["json"] = body.to_dict()
2424

25-
_kwargs["json"] = _body
2625
headers["Content-Type"] = "application/vnd+json"
2726

2827
_kwargs["headers"] = headers

end_to_end_tests/golden-record/my_test_api_client/api/bodies/post_bodies_multiple.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,20 @@ def _get_kwargs(
2828
}
2929

3030
if isinstance(body, PostBodiesMultipleJsonBody):
31-
_json_body = body.to_dict()
31+
_kwargs["json"] = body.to_dict()
3232

33-
_kwargs["json"] = _json_body
3433
headers["Content-Type"] = "application/json"
3534
if isinstance(body, File):
36-
_content_body = body.payload
35+
_kwargs["content"] = body.payload
3736

38-
_kwargs["content"] = _content_body
3937
headers["Content-Type"] = "application/octet-stream"
4038
if isinstance(body, PostBodiesMultipleDataBody):
41-
_data_body = body.to_dict()
39+
_kwargs["data"] = body.to_dict()
4240

43-
_kwargs["data"] = _data_body
4441
headers["Content-Type"] = "application/x-www-form-urlencoded"
4542
if isinstance(body, PostBodiesMultipleFilesBody):
46-
_files_body = body.to_multipart()
43+
_kwargs["files"] = body.to_multipart()
4744

48-
_kwargs["files"] = _files_body
4945
headers["Content-Type"] = "multipart/form-data"
5046

5147
_kwargs["headers"] = headers

end_to_end_tests/golden-record/my_test_api_client/api/bodies/refs.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ def _get_kwargs(
2020
"url": "/bodies/refs",
2121
}
2222

23-
_body = body.to_dict()
23+
_kwargs["json"] = body.to_dict()
2424

25-
_kwargs["json"] = _body
2625
headers["Content-Type"] = "application/json"
2726

2827
_kwargs["headers"] = headers

end_to_end_tests/golden-record/my_test_api_client/api/config/content_type_override.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ def _get_kwargs(
1919
"url": "/config/content-type-override",
2020
}
2121

22-
_body = body
22+
_kwargs["json"] = body
2323

24-
_kwargs["json"] = _body
2524
headers["Content-Type"] = "openapi/python/client"
2625

2726
_kwargs["headers"] = headers

end_to_end_tests/golden-record/my_test_api_client/api/naming/post_naming_property_conflict_with_import.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ def _get_kwargs(
2323
"url": "/naming/property-conflict-with-import",
2424
}
2525

26-
_body = body.to_dict()
26+
_kwargs["json"] = body.to_dict()
2727

28-
_kwargs["json"] = _body
2928
headers["Content-Type"] = "application/json"
3029

3130
_kwargs["headers"] = headers

0 commit comments

Comments
 (0)