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

Commit 8f9b901

Browse files
authored
Merge pull request #20 from openapi-json-schema-tools/feat_improves_endpoint_type_hints
Improves endpoint response type hints, handles all error responses corner case
2 parents 7675015 + d03f07d commit 8f9b901

File tree

471 files changed

+12425
-19996
lines changed
  • modules/openapi-json-schema-generator/src
  • 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
    • request_body_post_additionalproperties_are_allowed_by_default_request_body
    • request_body_post_additionalproperties_can_exist_by_itself_request_body
    • request_body_post_additionalproperties_should_not_look_in_applicators_request_body
    • request_body_post_allof_combined_with_anyof_oneof_request_body
    • request_body_post_allof_request_body
    • request_body_post_allof_simple_types_request_body
    • request_body_post_allof_with_base_schema_request_body
    • request_body_post_allof_with_one_empty_schema_request_body
    • request_body_post_allof_with_the_first_empty_schema_request_body
    • request_body_post_allof_with_the_last_empty_schema_request_body
    • request_body_post_allof_with_two_empty_schemas_request_body
    • request_body_post_anyof_complex_types_request_body
    • request_body_post_anyof_request_body
    • request_body_post_anyof_with_base_schema_request_body
    • request_body_post_anyof_with_one_empty_schema_request_body
    • request_body_post_array_type_matches_arrays_request_body
    • request_body_post_boolean_type_matches_booleans_request_body
    • request_body_post_by_int_request_body
    • request_body_post_by_number_request_body
    • request_body_post_by_small_number_request_body
    • request_body_post_date_time_format_request_body
    • request_body_post_email_format_request_body
    • request_body_post_enum_with0_does_not_match_false_request_body
    • request_body_post_enum_with1_does_not_match_true_request_body
    • request_body_post_enum_with_escaped_characters_request_body
    • request_body_post_enum_with_false_does_not_match0_request_body
    • request_body_post_enum_with_true_does_not_match1_request_body
    • request_body_post_enums_in_properties_request_body
    • request_body_post_forbidden_property_request_body
    • request_body_post_hostname_format_request_body
    • request_body_post_integer_type_matches_integers_request_body
    • request_body_post_invalid_instance_should_not_raise_error_when_float_division_inf_request_body
    • request_body_post_invalid_string_value_for_default_request_body
    • request_body_post_ipv4_format_request_body
    • request_body_post_ipv6_format_request_body
    • request_body_post_json_pointer_format_request_body
    • request_body_post_maximum_validation_request_body
    • request_body_post_maximum_validation_with_unsigned_integer_request_body
    • request_body_post_maxitems_validation_request_body
    • request_body_post_maxlength_validation_request_body
    • request_body_post_maxproperties0_means_the_object_is_empty_request_body
    • request_body_post_maxproperties_validation_request_body
    • request_body_post_minimum_validation_request_body
    • request_body_post_minimum_validation_with_signed_integer_request_body
    • request_body_post_minitems_validation_request_body
    • request_body_post_minlength_validation_request_body
    • request_body_post_minproperties_validation_request_body
    • request_body_post_nested_allof_to_check_validation_semantics_request_body
    • request_body_post_nested_anyof_to_check_validation_semantics_request_body
    • request_body_post_nested_items_request_body
    • request_body_post_nested_oneof_to_check_validation_semantics_request_body
    • request_body_post_not_more_complex_schema_request_body
    • request_body_post_not_request_body
    • request_body_post_nul_characters_in_strings_request_body
    • request_body_post_null_type_matches_only_the_null_object_request_body
    • request_body_post_number_type_matches_numbers_request_body
    • request_body_post_object_properties_validation_request_body
    • request_body_post_object_type_matches_objects_request_body
    • request_body_post_oneof_complex_types_request_body
    • request_body_post_oneof_request_body
    • request_body_post_oneof_with_base_schema_request_body
    • request_body_post_oneof_with_empty_schema_request_body
    • request_body_post_oneof_with_required_request_body
    • request_body_post_pattern_is_not_anchored_request_body
    • request_body_post_pattern_validation_request_body
    • request_body_post_properties_with_escaped_characters_request_body
    • request_body_post_property_named_ref_that_is_not_a_reference_request_body
    • request_body_post_ref_in_additionalproperties_request_body
    • request_body_post_ref_in_allof_request_body
    • request_body_post_ref_in_anyof_request_body
    • request_body_post_ref_in_items_request_body
    • request_body_post_ref_in_not_request_body
    • request_body_post_ref_in_oneof_request_body
    • request_body_post_ref_in_property_request_body
    • request_body_post_required_default_validation_request_body
    • request_body_post_required_validation_request_body
    • request_body_post_required_with_empty_array_request_body
    • request_body_post_required_with_escaped_characters_request_body
    • request_body_post_simple_enum_validation_request_body
    • request_body_post_string_type_matches_strings_request_body
    • request_body_post_the_default_keyword_does_not_do_anything_if_the_property_is_missing_request_body
    • request_body_post_uniqueitems_false_validation_request_body
    • request_body_post_uniqueitems_validation_request_body
    • request_body_post_uri_format_request_body
    • request_body_post_uri_reference_format_request_body
    • request_body_post_uri_template_format_request_body
    • response_body_post_additionalproperties_allows_a_schema_which_should_validate_response_body_for_content_types
    • response_body_post_additionalproperties_are_allowed_by_default_response_body_for_content_types
    • response_body_post_additionalproperties_can_exist_by_itself_response_body_for_content_types
    • response_body_post_additionalproperties_should_not_look_in_applicators_response_body_for_content_types
    • response_body_post_allof_combined_with_anyof_oneof_response_body_for_content_types
    • response_body_post_allof_response_body_for_content_types
    • response_body_post_allof_simple_types_response_body_for_content_types
    • response_body_post_allof_with_base_schema_response_body_for_content_types
    • response_body_post_allof_with_one_empty_schema_response_body_for_content_types
    • response_body_post_allof_with_the_first_empty_schema_response_body_for_content_types
    • response_body_post_allof_with_the_last_empty_schema_response_body_for_content_types
    • response_body_post_allof_with_two_empty_schemas_response_body_for_content_types
    • response_body_post_anyof_complex_types_response_body_for_content_types
    • response_body_post_anyof_response_body_for_content_types
    • response_body_post_anyof_with_base_schema_response_body_for_content_types
    • response_body_post_anyof_with_one_empty_schema_response_body_for_content_types
    • response_body_post_array_type_matches_arrays_response_body_for_content_types
    • response_body_post_boolean_type_matches_booleans_response_body_for_content_types
    • response_body_post_by_int_response_body_for_content_types
    • response_body_post_by_number_response_body_for_content_types
    • response_body_post_by_small_number_response_body_for_content_types
    • response_body_post_date_time_format_response_body_for_content_types
    • response_body_post_email_format_response_body_for_content_types
    • response_body_post_enum_with0_does_not_match_false_response_body_for_content_types
    • response_body_post_enum_with1_does_not_match_true_response_body_for_content_types
    • response_body_post_enum_with_escaped_characters_response_body_for_content_types
    • response_body_post_enum_with_false_does_not_match0_response_body_for_content_types
    • response_body_post_enum_with_true_does_not_match1_response_body_for_content_types
    • response_body_post_enums_in_properties_response_body_for_content_types
    • response_body_post_forbidden_property_response_body_for_content_types
    • response_body_post_hostname_format_response_body_for_content_types
    • response_body_post_integer_type_matches_integers_response_body_for_content_types
    • response_body_post_invalid_instance_should_not_raise_error_when_float_division_inf_response_body_for_content_types
    • response_body_post_invalid_string_value_for_default_response_body_for_content_types
    • response_body_post_ipv4_format_response_body_for_content_types
    • response_body_post_ipv6_format_response_body_for_content_types
    • response_body_post_json_pointer_format_response_body_for_content_types
    • response_body_post_maximum_validation_response_body_for_content_types
    • response_body_post_maximum_validation_with_unsigned_integer_response_body_for_content_types
    • response_body_post_maxitems_validation_response_body_for_content_types
    • response_body_post_maxlength_validation_response_body_for_content_types
    • response_body_post_maxproperties0_means_the_object_is_empty_response_body_for_content_types
    • response_body_post_maxproperties_validation_response_body_for_content_types
    • response_body_post_minimum_validation_response_body_for_content_types
    • response_body_post_minimum_validation_with_signed_integer_response_body_for_content_types
    • response_body_post_minitems_validation_response_body_for_content_types
    • response_body_post_minlength_validation_response_body_for_content_types
    • response_body_post_minproperties_validation_response_body_for_content_types
    • response_body_post_nested_allof_to_check_validation_semantics_response_body_for_content_types
    • response_body_post_nested_anyof_to_check_validation_semantics_response_body_for_content_types
    • response_body_post_nested_items_response_body_for_content_types
    • response_body_post_nested_oneof_to_check_validation_semantics_response_body_for_content_types
    • response_body_post_not_more_complex_schema_response_body_for_content_types
    • response_body_post_not_response_body_for_content_types
    • response_body_post_nul_characters_in_strings_response_body_for_content_types
    • response_body_post_null_type_matches_only_the_null_object_response_body_for_content_types
    • response_body_post_number_type_matches_numbers_response_body_for_content_types
    • response_body_post_object_properties_validation_response_body_for_content_types
    • response_body_post_object_type_matches_objects_response_body_for_content_types
    • response_body_post_oneof_complex_types_response_body_for_content_types
    • response_body_post_oneof_response_body_for_content_types
    • response_body_post_oneof_with_base_schema_response_body_for_content_types

Some content is hidden

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

471 files changed

+12425
-19996
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ public boolean getHasDefaultResponse() {
193193
return responses.stream().anyMatch(response -> response.isDefault);
194194
}
195195

196+
public boolean getAllResponsesAreErrors() {
197+
return responses.stream().allMatch(response -> response.is4xx || response.is5xx);
198+
}
199+
196200
/**
197201
* Check if there's at least one vendor extension
198202
*
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
11
self,
22
{{#if bodyParam}}
3-
{{#with bodyParam}}
4-
body: typing.Union[{{#each content}}{{#with this.schema}}{{baseName}},{{> model_templates/schema_python_types }}{{/with}}{{/each}}{{#unless required}}schemas.Unset] = schemas.unset{{else}}]{{/unless}},
5-
{{/with}}
3+
{{#if bodyParam.required}}
4+
{{#with bodyParam}}
5+
body: typing.Union[{{#each content}}{{#with this.schema}}{{baseName}},{{> model_templates/schema_python_types }}{{/with}}{{/each}}],
6+
{{/with}}
7+
{{#if isOverload}}
8+
{{#eq skipDeserialization "True"}}
9+
skip_deserialization: typing_extensions.Literal[True],
10+
{{/eq}}
11+
{{/if}}
12+
{{else}}
13+
{{#if isOverload}}
14+
{{#eq skipDeserialization "True"}}
15+
skip_deserialization: typing_extensions.Literal[True],
16+
{{/eq}}
17+
{{/if}}
18+
{{#with bodyParam}}
19+
body: typing.Union[{{#each content}}{{#with this.schema}}{{baseName}}, {{> model_templates/schema_python_types }}{{/with}}{{/each}}schemas.Unset] = schemas.unset,
20+
{{/with}}
21+
{{/if}}
622
{{/if}}
723
{{#if queryParams}}
824
query_params: RequestQueryParams = frozendict.frozendict(),
@@ -32,54 +48,47 @@
3248
stream: bool = False,
3349
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
3450
{{#if isOverload}}
35-
{{#eq skipDeserialization "True"}}
36-
skip_deserialization: typing_extensions.Literal[True] = True,
37-
{{/eq}}
3851
{{#eq skipDeserialization "False"}}
39-
skip_deserialization: typing_extensions.Literal[False] = False,
52+
skip_deserialization: typing_extensions.Literal[False] = ...,
4053
{{/eq}}
4154
{{#eq skipDeserialization "null"}}
42-
skip_deserialization: bool = False,
55+
skip_deserialization: bool = ...,
4356
{{/eq}}
4457
{{else}}
4558
skip_deserialization: bool = False,
4659
{{/if}}
4760
{{#eq skipDeserialization "True"}}
48-
) -> api_client.ApiResponseWithoutDeserialization:
61+
) -> api_client.ApiResponseWithoutDeserialization: ...
4962
{{/eq}}
5063
{{#eq skipDeserialization "False"}}
51-
) -> typing.Union[{{#each responses}}{{#if isDefault}}ApiResponseForDefault,{{else}}{{#if is2xx}}ApiResponseFor{{code}},{{/if}}{{/if}}{{/each}}api_client.ApiResponse]:
64+
) -> {{#if getAllResponsesAreErrors}}api_client.ApiResponseWithoutDeserialization: ...{{else}}typing.Union[
65+
{{#each responses}}
66+
{{#if isDefault}}
67+
ApiResponseForDefault,
68+
{{else}}
69+
{{#if is2xx}}
70+
ApiResponseFor{{code}},
71+
{{/if}}
72+
{{/if}}
73+
{{/each}}
74+
]: ...
75+
{{/if}}
5276
{{/eq}}
5377
{{#eq skipDeserialization "null"}}
5478
{{#if isOverload}}
5579
) -> typing.Union[
56-
{{#each responses}}
57-
{{#if isDefault}}
80+
{{#each responses}}
81+
{{#if isDefault}}
5882
ApiResponseForDefault,
59-
{{else}}
60-
{{#if is2xx}}
83+
{{else}}
84+
{{#if is2xx}}
6185
ApiResponseFor{{code}},
62-
{{/if}}
6386
{{/if}}
64-
{{/each}}
87+
{{/if}}
88+
{{/each}}
6589
api_client.ApiResponseWithoutDeserialization,
66-
]:
90+
]: ...
6791
{{else}}
68-
) -> typing.Union[
69-
{{#each responses}}
70-
{{#if isDefault}}
71-
ApiResponseForDefault,
72-
{{else}}
73-
{{#if is2xx}}
74-
ApiResponseFor{{code}},
75-
{{/if}}
76-
{{/if}}
77-
{{/each}}
78-
api_client.ApiResponse,
79-
api_client.ApiResponseWithoutDeserialization,
80-
]:
92+
):
8193
{{/if}}
82-
{{/eq}}
83-
{{#if isOverload}}
84-
...
85-
{{/if}}
94+
{{/eq}}

modules/openapi-json-schema-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml

+8-8
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,8 @@ paths:
545545
schema:
546546
type: string
547547
responses:
548-
'400':
549-
description: Invalid username supplied
548+
'200':
549+
description: Success
550550
'404':
551551
description: User not found
552552
/fake_classname_test:
@@ -651,8 +651,8 @@ paths:
651651
- 1.1
652652
- -1.2
653653
responses:
654-
'400':
655-
description: Invalid request
654+
'200':
655+
description: Success
656656
'404':
657657
description: Not found
658658
requestBody:
@@ -693,8 +693,8 @@ paths:
693693
가짜 엔드 포인트
694694
operationId: EndpointParameters
695695
responses:
696-
'400':
697-
description: Invalid username supplied
696+
'200':
697+
description: Success
698698
'404':
699699
description: User not found
700700
security:
@@ -822,8 +822,8 @@ paths:
822822
type: integer
823823
format: int64
824824
responses:
825-
'400':
826-
description: Someting wrong
825+
'200':
826+
description: succeeded
827827
/fake/refs/number:
828828
post:
829829
tags:

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

+27-42
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,20 @@ def _post_additionalproperties_allows_a_schema_which_should_validate_request_bod
6666
content_type: str = 'application/json',
6767
stream: bool = False,
6868
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
69-
skip_deserialization: typing_extensions.Literal[False] = False,
70-
) -> typing.Union[ApiResponseFor200,api_client.ApiResponse]:
71-
...
69+
skip_deserialization: typing_extensions.Literal[False] = ...,
70+
) -> typing.Union[
71+
ApiResponseFor200,
72+
]: ...
7273

7374
@typing.overload
7475
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
7576
self,
7677
body: typing.Union[SchemaForRequestBodyApplicationJson,],
78+
skip_deserialization: typing_extensions.Literal[True],
7779
content_type: str = 'application/json',
7880
stream: bool = False,
7981
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
80-
skip_deserialization: typing_extensions.Literal[True] = True,
81-
) -> api_client.ApiResponseWithoutDeserialization:
82-
...
82+
) -> api_client.ApiResponseWithoutDeserialization: ...
8383

8484
@typing.overload
8585
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
@@ -88,12 +88,11 @@ def _post_additionalproperties_allows_a_schema_which_should_validate_request_bod
8888
content_type: str = 'application/json',
8989
stream: bool = False,
9090
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
91-
skip_deserialization: bool = False,
91+
skip_deserialization: bool = ...,
9292
) -> typing.Union[
9393
ApiResponseFor200,
9494
api_client.ApiResponseWithoutDeserialization,
95-
]:
96-
...
95+
]: ...
9796

9897
def _post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
9998
self,
@@ -102,11 +101,7 @@ def _post_additionalproperties_allows_a_schema_which_should_validate_request_bod
102101
stream: bool = False,
103102
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
104103
skip_deserialization: bool = False,
105-
) -> typing.Union[
106-
ApiResponseFor200,
107-
api_client.ApiResponse,
108-
api_client.ApiResponseWithoutDeserialization,
109-
]:
104+
):
110105
"""
111106
:param skip_deserialization: If true then api_response.response will be set but
112107
api_response.body and api_response.headers will not be deserialized into schema
@@ -163,20 +158,20 @@ def post_additionalproperties_allows_a_schema_which_should_validate_request_body
163158
content_type: str = 'application/json',
164159
stream: bool = False,
165160
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
166-
skip_deserialization: typing_extensions.Literal[False] = False,
167-
) -> typing.Union[ApiResponseFor200,api_client.ApiResponse]:
168-
...
161+
skip_deserialization: typing_extensions.Literal[False] = ...,
162+
) -> typing.Union[
163+
ApiResponseFor200,
164+
]: ...
169165

170166
@typing.overload
171167
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
172168
self,
173169
body: typing.Union[SchemaForRequestBodyApplicationJson,],
170+
skip_deserialization: typing_extensions.Literal[True],
174171
content_type: str = 'application/json',
175172
stream: bool = False,
176173
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
177-
skip_deserialization: typing_extensions.Literal[True] = True,
178-
) -> api_client.ApiResponseWithoutDeserialization:
179-
...
174+
) -> api_client.ApiResponseWithoutDeserialization: ...
180175

181176
@typing.overload
182177
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
@@ -185,12 +180,11 @@ def post_additionalproperties_allows_a_schema_which_should_validate_request_body
185180
content_type: str = 'application/json',
186181
stream: bool = False,
187182
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
188-
skip_deserialization: bool = False,
183+
skip_deserialization: bool = ...,
189184
) -> typing.Union[
190185
ApiResponseFor200,
191186
api_client.ApiResponseWithoutDeserialization,
192-
]:
193-
...
187+
]: ...
194188

195189
def post_additionalproperties_allows_a_schema_which_should_validate_request_body(
196190
self,
@@ -199,11 +193,7 @@ def post_additionalproperties_allows_a_schema_which_should_validate_request_body
199193
stream: bool = False,
200194
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
201195
skip_deserialization: bool = False,
202-
) -> typing.Union[
203-
ApiResponseFor200,
204-
api_client.ApiResponse,
205-
api_client.ApiResponseWithoutDeserialization,
206-
]:
196+
):
207197
return self._post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
208198
body=body,
209199
content_type=content_type,
@@ -223,20 +213,20 @@ def post(
223213
content_type: str = 'application/json',
224214
stream: bool = False,
225215
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
226-
skip_deserialization: typing_extensions.Literal[False] = False,
227-
) -> typing.Union[ApiResponseFor200,api_client.ApiResponse]:
228-
...
216+
skip_deserialization: typing_extensions.Literal[False] = ...,
217+
) -> typing.Union[
218+
ApiResponseFor200,
219+
]: ...
229220

230221
@typing.overload
231222
def post(
232223
self,
233224
body: typing.Union[SchemaForRequestBodyApplicationJson,],
225+
skip_deserialization: typing_extensions.Literal[True],
234226
content_type: str = 'application/json',
235227
stream: bool = False,
236228
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
237-
skip_deserialization: typing_extensions.Literal[True] = True,
238-
) -> api_client.ApiResponseWithoutDeserialization:
239-
...
229+
) -> api_client.ApiResponseWithoutDeserialization: ...
240230

241231
@typing.overload
242232
def post(
@@ -245,12 +235,11 @@ def post(
245235
content_type: str = 'application/json',
246236
stream: bool = False,
247237
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
248-
skip_deserialization: bool = False,
238+
skip_deserialization: bool = ...,
249239
) -> typing.Union[
250240
ApiResponseFor200,
251241
api_client.ApiResponseWithoutDeserialization,
252-
]:
253-
...
242+
]: ...
254243

255244
def post(
256245
self,
@@ -259,11 +248,7 @@ def post(
259248
stream: bool = False,
260249
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
261250
skip_deserialization: bool = False,
262-
) -> typing.Union[
263-
ApiResponseFor200,
264-
api_client.ApiResponse,
265-
api_client.ApiResponseWithoutDeserialization,
266-
]:
251+
):
267252
return self._post_additionalproperties_allows_a_schema_which_should_validate_request_body_oapg(
268253
body=body,
269254
content_type=content_type,

0 commit comments

Comments
 (0)