Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

Commit 15b7307

Browse files
authored
Merge pull request #25 from openapi-json-schema-tools/feat_makes_body_type_hint_depend_upon_content_type
Endpoint type hint for body uses content_type
2 parents 8f9b901 + 9806f43 commit 15b7307

File tree

469 files changed

+12317
-2618
lines changed

Some content is hidden

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

469 files changed

+12317
-2618
lines changed

modules/openapi-json-schema-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,23 @@ public boolean getAllResponsesAreErrors() {
197197
return responses.stream().allMatch(response -> response.is4xx || response.is5xx);
198198
}
199199

200+
/**
201+
* @return contentTypeToOperation
202+
* returns a map where the key is the request body content type and the value is the current CodegenOperation
203+
* this is needed by templates when a different signature is needed for each request body content type
204+
*/
205+
public Map<String, CodegenOperation> getContentTypeToOperation() {
206+
LinkedHashMap<String, CodegenOperation> contentTypeToOperation = new LinkedHashMap<>();
207+
if (bodyParam == null) {
208+
return null;
209+
}
210+
LinkedHashMap<String, CodegenMediaType> content = bodyParam.getContent();
211+
for (String contentType: content.keySet()) {
212+
contentTypeToOperation.put(contentType, this);
213+
}
214+
return contentTypeToOperation;
215+
}
216+
200217
/**
201218
* Check if there's at least one vendor extension
202219
*

modules/openapi-json-schema-generator/src/main/resources/python/endpoint.handlebars

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -373,21 +373,29 @@ _all_accept_content_types = (
373373

374374

375375
class BaseApi(api_client.Api):
376+
{{#if bodyParam}}
377+
{{#each getContentTypeToOperation}}
378+
{{> endpoint_args_baseapi_wrapper contentType=@key this=this}}
376379

380+
{{/each}}
381+
{{> endpoint_args_baseapi_wrapper contentType="null" this=this}}
382+
383+
{{else}}
377384
@typing.overload
378385
def _{{operationId}}_oapg(
379-
{{> endpoint_args isOverload=true skipDeserialization="False"}}
386+
{{> endpoint_args isOverload=true skipDeserialization="False" contentType="null"}}
387+
{{/if}}
380388

381389
@typing.overload
382390
def _{{operationId}}_oapg(
383-
{{> endpoint_args isOverload=true skipDeserialization="True"}}
391+
{{> endpoint_args isOverload=true skipDeserialization="True" contentType="null"}}
384392

385393
@typing.overload
386394
def _{{operationId}}_oapg(
387-
{{> endpoint_args isOverload=true skipDeserialization="null"}}
395+
{{> endpoint_args isOverload=true skipDeserialization="null" contentType="null"}}
388396

389397
def _{{operationId}}_oapg(
390-
{{> endpoint_args isOverload=false skipDeserialization="null"}}
398+
{{> endpoint_args isOverload=false skipDeserialization="null" contentType="null"}}
391399
"""
392400
{{#if summary}}
393401
{{summary}}
@@ -533,20 +541,29 @@ class BaseApi(api_client.Api):
533541
class {{operationIdCamelCase}}(BaseApi):
534542
# this class is used by api classes that refer to endpoints with operationId fn names
535543

544+
{{#if bodyParam}}
545+
{{#each getContentTypeToOperation}}
546+
{{> endpoint_args_operationid_wrapper contentType=@key this=this}}
547+
548+
{{/each}}
549+
{{> endpoint_args_operationid_wrapper contentType="null" this=this}}
550+
551+
{{else}}
536552
@typing.overload
537553
def {{operationId}}(
538-
{{> endpoint_args isOverload=true skipDeserialization="False"}}
554+
{{> endpoint_args isOverload=true skipDeserialization="False" contentType="null"}}
555+
{{/if}}
539556

540557
@typing.overload
541558
def {{operationId}}(
542-
{{> endpoint_args isOverload=true skipDeserialization="True"}}
559+
{{> endpoint_args isOverload=true skipDeserialization="True" contentType="null"}}
543560

544561
@typing.overload
545562
def {{operationId}}(
546-
{{> endpoint_args isOverload=true skipDeserialization="null"}}
563+
{{> endpoint_args isOverload=true skipDeserialization="null" contentType="null"}}
547564

548565
def {{operationId}}(
549-
{{> endpoint_args isOverload=false skipDeserialization="null"}}
566+
{{> endpoint_args isOverload=false skipDeserialization="null" contentType="null"}}
550567
return self._{{operationId}}_oapg(
551568
{{> endpoint_args_passed }}
552569
)
@@ -555,20 +572,29 @@ class {{operationIdCamelCase}}(BaseApi):
555572
class ApiFor{{httpMethod}}(BaseApi):
556573
# this class is used by api classes that refer to endpoints by path and http method names
557574

575+
{{#if bodyParam}}
576+
{{#each getContentTypeToOperation}}
577+
{{> endpoint_args_httpmethod_wrapper contentType=@key this=this}}
578+
579+
{{/each}}
580+
{{> endpoint_args_httpmethod_wrapper contentType="null" this=this}}
581+
582+
{{else}}
558583
@typing.overload
559584
def {{httpMethod}}(
560-
{{> endpoint_args isOverload=true skipDeserialization="False"}}
585+
{{> endpoint_args isOverload=true skipDeserialization="False" contentType="null"}}
586+
{{/if}}
561587

562588
@typing.overload
563589
def {{httpMethod}}(
564-
{{> endpoint_args isOverload=true skipDeserialization="True"}}
590+
{{> endpoint_args isOverload=true skipDeserialization="True" contentType="null"}}
565591

566592
@typing.overload
567593
def {{httpMethod}}(
568-
{{> endpoint_args isOverload=true skipDeserialization="null"}}
594+
{{> endpoint_args isOverload=true skipDeserialization="null" contentType="null"}}
569595

570596
def {{httpMethod}}(
571-
{{> endpoint_args isOverload=false skipDeserialization="null"}}
597+
{{> endpoint_args isOverload=false skipDeserialization="null" contentType="null"}}
572598
return self._{{operationId}}_oapg(
573599
{{> endpoint_args_passed }}
574600
)

modules/openapi-json-schema-generator/src/main/resources/python/endpoint_args.handlebars

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,75 @@
22
{{#if bodyParam}}
33
{{#if bodyParam.required}}
44
{{#with bodyParam}}
5-
body: typing.Union[{{#each content}}{{#with this.schema}}{{baseName}},{{> model_templates/schema_python_types }}{{/with}}{{/each}}],
5+
{{#eq ../contentType "null"}}
6+
body: typing.Union[{{#each getContent}}{{#with this.schema}}{{baseName}},{{> model_templates/schema_python_types }}{{/with}}{{/each}}],
7+
{{else}}
8+
body: typing.Union[{{#each getContent}}{{#eq @key ../../contentType }}{{#with this.schema}}{{baseName}},{{> model_templates/schema_python_types }}{{/with}}{{/eq}}{{/each}}],
9+
{{/eq}}
610
{{/with}}
711
{{#if isOverload}}
812
{{#eq skipDeserialization "True"}}
913
skip_deserialization: typing_extensions.Literal[True],
1014
{{/eq}}
15+
{{#neq contentType "null"}}
16+
{{#with bodyParam}}
17+
{{#each content}}
18+
{{#eq @key ../../contentType}}
19+
{{#if @first}}
20+
content_type: typing_extensions.Literal["{{{@key}}}"] = ...,
21+
{{else}}
22+
content_type: typing_extensions.Literal["{{{@key}}}"],
23+
{{/if}}
24+
{{/eq}}
25+
{{/each}}
26+
{{/with}}
27+
{{else}}
28+
content_type: str = ...,
29+
{{/neq}}
30+
{{else}}
31+
{{#with bodyParam}}
32+
{{#each getContent}}
33+
{{#if @first}}
34+
content_type: str = '{{{@key}}}',
35+
{{/if}}
36+
{{/each}}
37+
{{/with}}
1138
{{/if}}
1239
{{else}}
1340
{{#if isOverload}}
1441
{{#eq skipDeserialization "True"}}
1542
skip_deserialization: typing_extensions.Literal[True],
1643
{{/eq}}
44+
{{#neq contentType "null"}}
45+
{{#with bodyParam}}
46+
{{#each getContent}}
47+
{{#eq @key ../../contentType}}
48+
{{#if @first}}
49+
content_type: typing_extensions.Literal["{{{@key}}}"] = ...,
50+
{{else}}
51+
content_type: typing_extensions.Literal["{{{@key}}}"],
52+
{{/if}}
53+
{{/eq}}
54+
{{/each}}
55+
{{/with}}
56+
{{else}}
57+
content_type: str = ...,
58+
{{/neq}}
59+
{{else}}
60+
{{#with bodyParam}}
61+
{{#each getContent}}
62+
{{#if @first}}
63+
content_type: str = '{{{@key}}}',
64+
{{/if}}
65+
{{/each}}
66+
{{/with}}
1767
{{/if}}
1868
{{#with bodyParam}}
19-
body: typing.Union[{{#each content}}{{#with this.schema}}{{baseName}}, {{> model_templates/schema_python_types }}{{/with}}{{/each}}schemas.Unset] = schemas.unset,
69+
{{#eq ../contentType "null"}}
70+
body: typing.Union[{{#each getContent}}{{#with this.schema}}{{baseName}}, {{> model_templates/schema_python_types }}{{/with}}{{/each}}schemas.Unset] = schemas.unset,
71+
{{else}}
72+
body: typing.Union[{{#each getContent}}{{#eq @key ../../contentType }}{{#with this.schema}}{{baseName}}, {{> model_templates/schema_python_types }}{{/with}}{{/eq}}{{/each}}schemas.Unset] = schemas.unset,
73+
{{/eq}}
2074
{{/with}}
2175
{{/if}}
2276
{{/if}}
@@ -32,13 +86,6 @@
3286
{{#if cookieParams}}
3387
cookie_params: RequestCookieParams = frozendict.frozendict(),
3488
{{/if}}
35-
{{#with bodyParam}}
36-
{{#each content}}
37-
{{#if @first}}
38-
content_type: str = '{{{@key}}}',
39-
{{/if}}
40-
{{/each}}
41-
{{/with}}
4289
{{#if produces}}
4390
accept_content_types: typing.Tuple[str] = _all_accept_content_types,
4491
{{/if}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@typing.overload
2+
{{#with this}}
3+
def _{{operationId}}_oapg(
4+
{{> endpoint_args isOverload=true skipDeserialization="False" contentType=contentType}}
5+
{{/with}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@typing.overload
2+
{{#with this}}
3+
def {{httpMethod}}(
4+
{{> endpoint_args isOverload=true skipDeserialization="False" contentType=contentType}}
5+
{{/with}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@typing.overload
2+
{{#with this}}
3+
def {{operationId}}(
4+
{{> endpoint_args isOverload=true skipDeserialization="False" contentType=contentType}}
5+
{{/with}}

samples/openapi3/client/3_0_3_unit_test/python/unit_test_api/paths/request_body_post_additionalproperties_allows_a_schema_which_should_validate_request_body/post.py

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,37 @@ class ApiResponseFor200(api_client.ApiResponse):
5858

5959

6060
class BaseApi(api_client.Api):
61+
@typing.overload
62+
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
63+
self,
64+
body: typing.Union[SchemaForRequestBodyApplicationJson,],
65+
content_type: typing_extensions.Literal["application/json"] = ...,
66+
stream: bool = False,
67+
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
68+
skip_deserialization: typing_extensions.Literal[False] = ...,
69+
) -> typing.Union[
70+
ApiResponseFor200,
71+
]: ...
6172

6273
@typing.overload
6374
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
6475
self,
6576
body: typing.Union[SchemaForRequestBodyApplicationJson,],
66-
content_type: str = 'application/json',
77+
content_type: str = ...,
6778
stream: bool = False,
6879
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
6980
skip_deserialization: typing_extensions.Literal[False] = ...,
7081
) -> typing.Union[
7182
ApiResponseFor200,
7283
]: ...
7384

85+
7486
@typing.overload
7587
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
7688
self,
7789
body: typing.Union[SchemaForRequestBodyApplicationJson,],
7890
skip_deserialization: typing_extensions.Literal[True],
79-
content_type: str = 'application/json',
91+
content_type: str = ...,
8092
stream: bool = False,
8193
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
8294
) -> api_client.ApiResponseWithoutDeserialization: ...
@@ -85,7 +97,7 @@ def _post_additionalproperties_allows_a_schema_which_should_validate_request_bod
8597
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
8698
self,
8799
body: typing.Union[SchemaForRequestBodyApplicationJson,],
88-
content_type: str = 'application/json',
100+
content_type: str = ...,
89101
stream: bool = False,
90102
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
91103
skip_deserialization: bool = ...,
@@ -155,20 +167,33 @@ class PostAdditionalpropertiesAllowsASchemaWhichShouldValidateRequestBody(BaseAp
155167
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
156168
self,
157169
body: typing.Union[SchemaForRequestBodyApplicationJson,],
158-
content_type: str = 'application/json',
170+
content_type: typing_extensions.Literal["application/json"] = ...,
171+
stream: bool = False,
172+
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
173+
skip_deserialization: typing_extensions.Literal[False] = ...,
174+
) -> typing.Union[
175+
ApiResponseFor200,
176+
]: ...
177+
178+
@typing.overload
179+
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
180+
self,
181+
body: typing.Union[SchemaForRequestBodyApplicationJson,],
182+
content_type: str = ...,
159183
stream: bool = False,
160184
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
161185
skip_deserialization: typing_extensions.Literal[False] = ...,
162186
) -> typing.Union[
163187
ApiResponseFor200,
164188
]: ...
165189

190+
166191
@typing.overload
167192
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
168193
self,
169194
body: typing.Union[SchemaForRequestBodyApplicationJson,],
170195
skip_deserialization: typing_extensions.Literal[True],
171-
content_type: str = 'application/json',
196+
content_type: str = ...,
172197
stream: bool = False,
173198
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
174199
) -> api_client.ApiResponseWithoutDeserialization: ...
@@ -177,7 +202,7 @@ def post_additionalproperties_allows_a_schema_which_should_validate_request_body
177202
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
178203
self,
179204
body: typing.Union[SchemaForRequestBodyApplicationJson,],
180-
content_type: str = 'application/json',
205+
content_type: str = ...,
181206
stream: bool = False,
182207
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
183208
skip_deserialization: bool = ...,
@@ -210,20 +235,33 @@ class ApiForpost(BaseApi):
210235
def post(
211236
self,
212237
body: typing.Union[SchemaForRequestBodyApplicationJson,],
213-
content_type: str = 'application/json',
238+
content_type: typing_extensions.Literal["application/json"] = ...,
239+
stream: bool = False,
240+
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
241+
skip_deserialization: typing_extensions.Literal[False] = ...,
242+
) -> typing.Union[
243+
ApiResponseFor200,
244+
]: ...
245+
246+
@typing.overload
247+
def post(
248+
self,
249+
body: typing.Union[SchemaForRequestBodyApplicationJson,],
250+
content_type: str = ...,
214251
stream: bool = False,
215252
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
216253
skip_deserialization: typing_extensions.Literal[False] = ...,
217254
) -> typing.Union[
218255
ApiResponseFor200,
219256
]: ...
220257

258+
221259
@typing.overload
222260
def post(
223261
self,
224262
body: typing.Union[SchemaForRequestBodyApplicationJson,],
225263
skip_deserialization: typing_extensions.Literal[True],
226-
content_type: str = 'application/json',
264+
content_type: str = ...,
227265
stream: bool = False,
228266
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
229267
) -> api_client.ApiResponseWithoutDeserialization: ...
@@ -232,7 +270,7 @@ def post(
232270
def post(
233271
self,
234272
body: typing.Union[SchemaForRequestBodyApplicationJson,],
235-
content_type: str = 'application/json',
273+
content_type: str = ...,
236274
stream: bool = False,
237275
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
238276
skip_deserialization: bool = ...,

0 commit comments

Comments
 (0)