Skip to content

Commit bf575fb

Browse files
dbantyp1-ra
andauthoredApr 5, 2021
fix: Prevent duplicate return types in generated api functions (#365)
* template / macro: return_type / correct duplicate * e2e tests / update golden records * refactor: Simplify response type generation by moving logic to Python * test: Regen golden-record post merge Co-authored-by: p1-ra <aurelien.roose@p1sec.com>
1 parent a4e3e6a commit bf575fb

12 files changed

+106
-184
lines changed
 

‎end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def _get_kwargs(
131131
}
132132

133133

134-
def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]:
134+
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, None]]:
135135
if response.status_code == 200:
136136
response_200 = None
137137

@@ -143,7 +143,7 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPVal
143143
return None
144144

145145

146-
def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]:
146+
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, None]]:
147147
return Response(
148148
status_code=response.status_code,
149149
content=response.content,
@@ -172,7 +172,7 @@ def sync_detailed(
172172
required_model_prop: ModelWithUnionProperty,
173173
nullable_model_prop: Union[Unset, None, ModelWithUnionProperty] = UNSET,
174174
nullable_required_model_prop: Optional[ModelWithUnionProperty],
175-
) -> Response[Union[None, HTTPValidationError]]:
175+
) -> Response[Union[HTTPValidationError, None]]:
176176
kwargs = _get_kwargs(
177177
client=client,
178178
string_prop=string_prop,
@@ -221,7 +221,7 @@ def sync(
221221
required_model_prop: ModelWithUnionProperty,
222222
nullable_model_prop: Union[Unset, None, ModelWithUnionProperty] = UNSET,
223223
nullable_required_model_prop: Optional[ModelWithUnionProperty],
224-
) -> Optional[Union[None, HTTPValidationError]]:
224+
) -> Optional[Union[HTTPValidationError, None]]:
225225
""" """
226226

227227
return sync_detailed(
@@ -266,7 +266,7 @@ async def asyncio_detailed(
266266
required_model_prop: ModelWithUnionProperty,
267267
nullable_model_prop: Union[Unset, None, ModelWithUnionProperty] = UNSET,
268268
nullable_required_model_prop: Optional[ModelWithUnionProperty],
269-
) -> Response[Union[None, HTTPValidationError]]:
269+
) -> Response[Union[HTTPValidationError, None]]:
270270
kwargs = _get_kwargs(
271271
client=client,
272272
string_prop=string_prop,
@@ -314,7 +314,7 @@ async def asyncio(
314314
required_model_prop: ModelWithUnionProperty,
315315
nullable_model_prop: Union[Unset, None, ModelWithUnionProperty] = UNSET,
316316
nullable_required_model_prop: Optional[ModelWithUnionProperty],
317-
) -> Optional[Union[None, HTTPValidationError]]:
317+
) -> Optional[Union[HTTPValidationError, None]]:
318318
""" """
319319

320320
return (

‎end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def _get_kwargs(
4747
}
4848

4949

50-
def _parse_response(*, response: httpx.Response) -> Optional[Union[List[AModel], HTTPValidationError]]:
50+
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, List[AModel]]]:
5151
if response.status_code == 200:
5252
response_200 = []
5353
_response_200 = response.json()
@@ -61,10 +61,14 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[List[AModel],
6161
response_422 = HTTPValidationError.from_dict(response.json())
6262

6363
return response_422
64+
if response.status_code == 423:
65+
response_423 = HTTPValidationError.from_dict(response.json())
66+
67+
return response_423
6468
return None
6569

6670

67-
def _build_response(*, response: httpx.Response) -> Response[Union[List[AModel], HTTPValidationError]]:
71+
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, List[AModel]]]:
6872
return Response(
6973
status_code=response.status_code,
7074
content=response.content,
@@ -78,7 +82,7 @@ def sync_detailed(
7882
client: Client,
7983
an_enum_value: List[AnEnum],
8084
some_date: Union[datetime.date, datetime.datetime],
81-
) -> Response[Union[List[AModel], HTTPValidationError]]:
85+
) -> Response[Union[HTTPValidationError, List[AModel]]]:
8286
kwargs = _get_kwargs(
8387
client=client,
8488
an_enum_value=an_enum_value,
@@ -97,7 +101,7 @@ def sync(
97101
client: Client,
98102
an_enum_value: List[AnEnum],
99103
some_date: Union[datetime.date, datetime.datetime],
100-
) -> Optional[Union[List[AModel], HTTPValidationError]]:
104+
) -> Optional[Union[HTTPValidationError, List[AModel]]]:
101105
""" Get a list of things """
102106

103107
return sync_detailed(
@@ -112,7 +116,7 @@ async def asyncio_detailed(
112116
client: Client,
113117
an_enum_value: List[AnEnum],
114118
some_date: Union[datetime.date, datetime.datetime],
115-
) -> Response[Union[List[AModel], HTTPValidationError]]:
119+
) -> Response[Union[HTTPValidationError, List[AModel]]]:
116120
kwargs = _get_kwargs(
117121
client=client,
118122
an_enum_value=an_enum_value,
@@ -130,7 +134,7 @@ async def asyncio(
130134
client: Client,
131135
an_enum_value: List[AnEnum],
132136
some_date: Union[datetime.date, datetime.datetime],
133-
) -> Optional[Union[List[AModel], HTTPValidationError]]:
137+
) -> Optional[Union[HTTPValidationError, List[AModel]]]:
134138
""" Get a list of things """
135139

136140
return (

‎end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def _get_kwargs(
3434
}
3535

3636

37-
def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]:
37+
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, None]]:
3838
if response.status_code == 200:
3939
response_200 = None
4040

@@ -46,7 +46,7 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPVal
4646
return None
4747

4848

49-
def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]:
49+
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, None]]:
5050
return Response(
5151
status_code=response.status_code,
5252
content=response.content,
@@ -59,7 +59,7 @@ def sync_detailed(
5959
*,
6060
client: Client,
6161
int_enum: AnIntEnum,
62-
) -> Response[Union[None, HTTPValidationError]]:
62+
) -> Response[Union[HTTPValidationError, None]]:
6363
kwargs = _get_kwargs(
6464
client=client,
6565
int_enum=int_enum,
@@ -76,7 +76,7 @@ def sync(
7676
*,
7777
client: Client,
7878
int_enum: AnIntEnum,
79-
) -> Optional[Union[None, HTTPValidationError]]:
79+
) -> Optional[Union[HTTPValidationError, None]]:
8080
""" """
8181

8282
return sync_detailed(
@@ -89,7 +89,7 @@ async def asyncio_detailed(
8989
*,
9090
client: Client,
9191
int_enum: AnIntEnum,
92-
) -> Response[Union[None, HTTPValidationError]]:
92+
) -> Response[Union[HTTPValidationError, None]]:
9393
kwargs = _get_kwargs(
9494
client=client,
9595
int_enum=int_enum,
@@ -105,7 +105,7 @@ async def asyncio(
105105
*,
106106
client: Client,
107107
int_enum: AnIntEnum,
108-
) -> Optional[Union[None, HTTPValidationError]]:
108+
) -> Optional[Union[HTTPValidationError, None]]:
109109
""" """
110110

111111
return (

‎end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def _get_kwargs(
2929
}
3030

3131

32-
def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]:
32+
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, None]]:
3333
if response.status_code == 200:
3434
response_200 = None
3535

@@ -41,7 +41,7 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPVal
4141
return None
4242

4343

44-
def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]:
44+
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, None]]:
4545
return Response(
4646
status_code=response.status_code,
4747
content=response.content,
@@ -54,7 +54,7 @@ def sync_detailed(
5454
*,
5555
client: Client,
5656
json_body: AModel,
57-
) -> Response[Union[None, HTTPValidationError]]:
57+
) -> Response[Union[HTTPValidationError, None]]:
5858
kwargs = _get_kwargs(
5959
client=client,
6060
json_body=json_body,
@@ -71,7 +71,7 @@ def sync(
7171
*,
7272
client: Client,
7373
json_body: AModel,
74-
) -> Optional[Union[None, HTTPValidationError]]:
74+
) -> Optional[Union[HTTPValidationError, None]]:
7575
""" Try sending a JSON body """
7676

7777
return sync_detailed(
@@ -84,7 +84,7 @@ async def asyncio_detailed(
8484
*,
8585
client: Client,
8686
json_body: AModel,
87-
) -> Response[Union[None, HTTPValidationError]]:
87+
) -> Response[Union[HTTPValidationError, None]]:
8888
kwargs = _get_kwargs(
8989
client=client,
9090
json_body=json_body,
@@ -100,7 +100,7 @@ async def asyncio(
100100
*,
101101
client: Client,
102102
json_body: AModel,
103-
) -> Optional[Union[None, HTTPValidationError]]:
103+
) -> Optional[Union[HTTPValidationError, None]]:
104104
""" Try sending a JSON body """
105105

106106
return (

‎end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def _get_kwargs(
3535
}
3636

3737

38-
def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]:
38+
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, None]]:
3939
if response.status_code == 200:
4040
response_200 = None
4141

@@ -47,7 +47,7 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPVal
4747
return None
4848

4949

50-
def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]:
50+
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, None]]:
5151
return Response(
5252
status_code=response.status_code,
5353
content=response.content,
@@ -60,7 +60,7 @@ def sync_detailed(
6060
*,
6161
client: Client,
6262
query_param: Union[Unset, List[str]] = UNSET,
63-
) -> Response[Union[None, HTTPValidationError]]:
63+
) -> Response[Union[HTTPValidationError, None]]:
6464
kwargs = _get_kwargs(
6565
client=client,
6666
query_param=query_param,
@@ -77,7 +77,7 @@ def sync(
7777
*,
7878
client: Client,
7979
query_param: Union[Unset, List[str]] = UNSET,
80-
) -> Optional[Union[None, HTTPValidationError]]:
80+
) -> Optional[Union[HTTPValidationError, None]]:
8181
""" Test optional query parameters """
8282

8383
return sync_detailed(
@@ -90,7 +90,7 @@ async def asyncio_detailed(
9090
*,
9191
client: Client,
9292
query_param: Union[Unset, List[str]] = UNSET,
93-
) -> Response[Union[None, HTTPValidationError]]:
93+
) -> Response[Union[HTTPValidationError, None]]:
9494
kwargs = _get_kwargs(
9595
client=client,
9696
query_param=query_param,
@@ -106,7 +106,7 @@ async def asyncio(
106106
*,
107107
client: Client,
108108
query_param: Union[Unset, List[str]] = UNSET,
109-
) -> Optional[Union[None, HTTPValidationError]]:
109+
) -> Optional[Union[HTTPValidationError, None]]:
110110
""" Test optional query parameters """
111111

112112
return (
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, Optional, Union
1+
from typing import Any, Dict
22

33
import httpx
44

@@ -26,32 +26,20 @@ def _get_kwargs(
2626
}
2727

2828

29-
def _parse_response(*, response: httpx.Response) -> Optional[Union[None, None]]:
30-
if response.status_code == 200:
31-
response_200 = None
32-
33-
return response_200
34-
if response.status_code == 401:
35-
response_401 = None
36-
37-
return response_401
38-
return None
39-
40-
41-
def _build_response(*, response: httpx.Response) -> Response[Union[None, None]]:
29+
def _build_response(*, response: httpx.Response) -> Response[None]:
4230
return Response(
4331
status_code=response.status_code,
4432
content=response.content,
4533
headers=response.headers,
46-
parsed=_parse_response(response=response),
34+
parsed=None,
4735
)
4836

4937

5038
def sync_detailed(
5139
*,
5240
client: Client,
5341
my_token: str,
54-
) -> Response[Union[None, None]]:
42+
) -> Response[None]:
5543
kwargs = _get_kwargs(
5644
client=client,
5745
my_token=my_token,
@@ -64,24 +52,11 @@ def sync_detailed(
6452
return _build_response(response=response)
6553

6654

67-
def sync(
68-
*,
69-
client: Client,
70-
my_token: str,
71-
) -> Optional[Union[None, None]]:
72-
""" Test optional cookie parameters """
73-
74-
return sync_detailed(
75-
client=client,
76-
my_token=my_token,
77-
).parsed
78-
79-
8055
async def asyncio_detailed(
8156
*,
8257
client: Client,
8358
my_token: str,
84-
) -> Response[Union[None, None]]:
59+
) -> Response[None]:
8560
kwargs = _get_kwargs(
8661
client=client,
8762
my_token=my_token,
@@ -91,18 +66,3 @@ async def asyncio_detailed(
9166
response = await _client.get(**kwargs)
9267

9368
return _build_response(response=response)
94-
95-
96-
async def asyncio(
97-
*,
98-
client: Client,
99-
my_token: str,
100-
) -> Optional[Union[None, None]]:
101-
""" Test optional cookie parameters """
102-
103-
return (
104-
await asyncio_detailed(
105-
client=client,
106-
my_token=my_token,
107-
)
108-
).parsed

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def _get_kwargs(
4040
}
4141

4242

43-
def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]:
43+
def _parse_response(*, response: httpx.Response) -> Optional[Union[HTTPValidationError, None]]:
4444
if response.status_code == 200:
4545
response_200 = None
4646

@@ -52,7 +52,7 @@ def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPVal
5252
return None
5353

5454

55-
def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]:
55+
def _build_response(*, response: httpx.Response) -> Response[Union[HTTPValidationError, None]]:
5656
return Response(
5757
status_code=response.status_code,
5858
content=response.content,
@@ -66,7 +66,7 @@ def sync_detailed(
6666
client: Client,
6767
multipart_data: BodyUploadFileTestsUploadPost,
6868
keep_alive: Union[Unset, bool] = UNSET,
69-
) -> Response[Union[None, HTTPValidationError]]:
69+
) -> Response[Union[HTTPValidationError, None]]:
7070
kwargs = _get_kwargs(
7171
client=client,
7272
multipart_data=multipart_data,
@@ -85,7 +85,7 @@ def sync(
8585
client: Client,
8686
multipart_data: BodyUploadFileTestsUploadPost,
8787
keep_alive: Union[Unset, bool] = UNSET,
88-
) -> Optional[Union[None, HTTPValidationError]]:
88+
) -> Optional[Union[HTTPValidationError, None]]:
8989
""" Upload a file """
9090

9191
return sync_detailed(
@@ -100,7 +100,7 @@ async def asyncio_detailed(
100100
client: Client,
101101
multipart_data: BodyUploadFileTestsUploadPost,
102102
keep_alive: Union[Unset, bool] = UNSET,
103-
) -> Response[Union[None, HTTPValidationError]]:
103+
) -> Response[Union[HTTPValidationError, None]]:
104104
kwargs = _get_kwargs(
105105
client=client,
106106
multipart_data=multipart_data,
@@ -118,7 +118,7 @@ async def asyncio(
118118
client: Client,
119119
multipart_data: BodyUploadFileTestsUploadPost,
120120
keep_alive: Union[Unset, bool] = UNSET,
121-
) -> Optional[Union[None, HTTPValidationError]]:
121+
) -> Optional[Union[HTTPValidationError, None]]:
122122
""" Upload a file """
123123

124124
return (

‎end_to_end_tests/openapi.json

+10
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@
7070
}
7171
}
7272
}
73+
},
74+
"423": {
75+
"description": "Validation Error",
76+
"content": {
77+
"application/json": {
78+
"schema": {
79+
"$ref": "#/components/schemas/HTTPValidationError"
80+
}
81+
}
82+
}
7383
}
7484
}
7585
}

‎openapi_python_client/parser/openapi.py

+9
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,15 @@ def from_data(
265265

266266
return result, schemas
267267

268+
def response_type(self) -> str:
269+
""" Get the Python type of any response from this endpoint """
270+
types = sorted({response.prop.get_type_string() for response in self.responses})
271+
if len(types) == 0:
272+
return "None"
273+
if len(types) == 1:
274+
return self.responses[0].prop.get_type_string()
275+
return f"Union[{', '.join(types)}]"
276+
268277

269278
@dataclass
270279
class GeneratorData:

‎openapi_python_client/templates/endpoint_macros.py.jinja

-14
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,6 @@ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
7171
{% endif %}
7272
{% endmacro %}
7373

74-
{% macro return_type(endpoint) %}
75-
{% if endpoint.responses | length == 0 %}
76-
None
77-
{%- elif endpoint.responses | length == 1 %}
78-
{{ endpoint.responses[0].prop.get_type_string() }}
79-
{%- else %}
80-
Union[
81-
{% for response in endpoint.responses %}
82-
{{ response.prop.get_type_string() }}{{ "," if not loop.last }}
83-
{% endfor %}
84-
]
85-
{%- endif %}
86-
{% endmacro %}
87-
8874
{# The all the kwargs passed into an endpoint (and variants thereof)) #}
8975
{% macro arguments(endpoint) %}
9076
*,

‎openapi_python_client/templates/endpoint_module.py.jinja

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ from ...types import Response, UNSET{% if endpoint.multipart_body_reference %},
1010
{{ relative }}
1111
{% endfor %}
1212

13-
{% from "endpoint_macros.py.jinja" import header_params, cookie_params, query_params, json_body, return_type, arguments, client, kwargs, parse_response %}
13+
{% from "endpoint_macros.py.jinja" import header_params, cookie_params, query_params, json_body, arguments, client, kwargs, parse_response %}
1414

15-
{% set return_string = return_type(endpoint) %}
15+
{% set return_string = endpoint.response_type() %}
1616
{% set parsed_responses = (endpoint.responses | length > 0) and return_string != "None" %}
1717

1818
def _get_kwargs(

‎tests/test_parser/test_openapi.py

+40-87
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from unittest.mock import MagicMock
2+
3+
import pytest
4+
15
import openapi_python_client.schema as oai
26
from openapi_python_client import GeneratorError
37
from openapi_python_client.parser.errors import ParseError
@@ -114,6 +118,19 @@ def test_from_dict_invalid_version(self, mocker):
114118

115119

116120
class TestEndpoint:
121+
def make_endpoint(self):
122+
from openapi_python_client.parser.openapi import Endpoint
123+
124+
return Endpoint(
125+
path="path",
126+
method="method",
127+
description=None,
128+
name="name",
129+
requires_security=False,
130+
tag="tag",
131+
relative_imports={"import_3"},
132+
)
133+
117134
def test_parse_request_form_body(self, mocker):
118135
ref = mocker.MagicMock()
119136
body = oai.RequestBody.construct(
@@ -195,15 +212,7 @@ def test_add_body_no_data(self, mocker):
195212
from openapi_python_client.parser.openapi import Endpoint, Schemas
196213

197214
parse_request_form_body = mocker.patch.object(Endpoint, "parse_request_form_body")
198-
endpoint = Endpoint(
199-
path="path",
200-
method="method",
201-
description=None,
202-
name="name",
203-
requires_security=False,
204-
tag="tag",
205-
relative_imports={"import_3"},
206-
)
215+
endpoint = self.make_endpoint()
207216
schemas = Schemas()
208217

209218
Endpoint._add_body(endpoint=endpoint, data=oai.Operation.construct(), schemas=schemas)
@@ -217,15 +226,7 @@ def test_add_body_bad_data(self, mocker):
217226
parse_error = ParseError(data=mocker.MagicMock())
218227
other_schemas = mocker.MagicMock()
219228
mocker.patch.object(Endpoint, "parse_request_json_body", return_value=(parse_error, other_schemas))
220-
endpoint = Endpoint(
221-
path="path",
222-
method="method",
223-
description=None,
224-
name="name",
225-
requires_security=False,
226-
tag="tag",
227-
relative_imports={"import_3"},
228-
)
229+
endpoint = self.make_endpoint()
229230
request_body = mocker.MagicMock()
230231
schemas = Schemas()
231232

@@ -263,15 +264,7 @@ def test_add_body_happy(self, mocker):
263264
f"{MODULE_NAME}.import_string_from_reference", side_effect=["import_1", "import_2"]
264265
)
265266

266-
endpoint = Endpoint(
267-
path="path",
268-
method="method",
269-
description=None,
270-
name="name",
271-
requires_security=False,
272-
tag="tag",
273-
relative_imports={"import_3"},
274-
)
267+
endpoint = self.make_endpoint()
275268
initial_schemas = mocker.MagicMock()
276269

277270
(endpoint, response_schemas) = Endpoint._add_body(
@@ -303,15 +296,7 @@ def test__add_responses_status_code_error(self, mocker):
303296
data = {
304297
"not_a_number": response_1_data,
305298
}
306-
endpoint = Endpoint(
307-
path="path",
308-
method="method",
309-
description=None,
310-
name="name",
311-
requires_security=False,
312-
tag="tag",
313-
relative_imports={"import_3"},
314-
)
299+
endpoint = self.make_endpoint()
315300
parse_error = ParseError(data=mocker.MagicMock())
316301
response_from_data = mocker.patch(f"{MODULE_NAME}.response_from_data", return_value=(parse_error, schemas))
317302

@@ -333,15 +318,7 @@ def test__add_responses_error(self, mocker):
333318
"200": response_1_data,
334319
"404": response_2_data,
335320
}
336-
endpoint = Endpoint(
337-
path="path",
338-
method="method",
339-
description=None,
340-
name="name",
341-
requires_security=False,
342-
tag="tag",
343-
relative_imports={"import_3"},
344-
)
321+
endpoint = self.make_endpoint()
345322
parse_error = ParseError(data=mocker.MagicMock())
346323
response_from_data = mocker.patch(f"{MODULE_NAME}.response_from_data", return_value=(parse_error, schemas))
347324

@@ -374,15 +351,7 @@ def test__add_responses(self, mocker):
374351
"200": response_1_data,
375352
"404": response_2_data,
376353
}
377-
endpoint = Endpoint(
378-
path="path",
379-
method="method",
380-
description=None,
381-
name="name",
382-
requires_security=False,
383-
tag="tag",
384-
relative_imports={"import_3"},
385-
)
354+
endpoint = self.make_endpoint()
386355
schemas = mocker.MagicMock()
387356
schemas_1 = mocker.MagicMock()
388357
schemas_2 = mocker.MagicMock()
@@ -420,14 +389,7 @@ def test__add_responses(self, mocker):
420389
def test__add_parameters_handles_no_params(self):
421390
from openapi_python_client.parser.openapi import Endpoint, Schemas
422391

423-
endpoint = Endpoint(
424-
path="path",
425-
method="method",
426-
description=None,
427-
name="name",
428-
requires_security=False,
429-
tag="tag",
430-
)
392+
endpoint = self.make_endpoint()
431393
schemas = Schemas()
432394
# Just checking there's no exception here
433395
assert Endpoint._add_parameters(endpoint=endpoint, data=oai.Operation.construct(), schemas=schemas) == (
@@ -438,14 +400,7 @@ def test__add_parameters_handles_no_params(self):
438400
def test__add_parameters_parse_error(self, mocker):
439401
from openapi_python_client.parser.openapi import Endpoint
440402

441-
endpoint = Endpoint(
442-
path="path",
443-
method="method",
444-
description=None,
445-
name="name",
446-
requires_security=False,
447-
tag="tag",
448-
)
403+
endpoint = self.make_endpoint()
449404
initial_schemas = mocker.MagicMock()
450405
parse_error = ParseError(data=mocker.MagicMock())
451406
property_schemas = mocker.MagicMock()
@@ -463,14 +418,7 @@ def test__add_parameters_parse_error(self, mocker):
463418
def test__add_parameters_fail_loudly_when_location_not_supported(self, mocker):
464419
from openapi_python_client.parser.openapi import Endpoint, Schemas
465420

466-
endpoint = Endpoint(
467-
path="path",
468-
method="method",
469-
description=None,
470-
name="name",
471-
requires_security=False,
472-
tag="tag",
473-
)
421+
endpoint = self.make_endpoint()
474422
parsed_schemas = mocker.MagicMock()
475423
mocker.patch(f"{MODULE_NAME}.property_from_data", return_value=(mocker.MagicMock(), parsed_schemas))
476424
param = oai.Parameter.construct(
@@ -487,15 +435,7 @@ def test__add_parameters_happy(self, mocker):
487435
from openapi_python_client.parser.openapi import Endpoint
488436
from openapi_python_client.parser.properties import Property
489437

490-
endpoint = Endpoint(
491-
path="path",
492-
method="method",
493-
description=None,
494-
name="name",
495-
requires_security=False,
496-
tag="tag",
497-
relative_imports={"import_3"},
498-
)
438+
endpoint = self.make_endpoint()
499439
path_prop = mocker.MagicMock(autospec=Property)
500440
path_prop_import = mocker.MagicMock()
501441
path_prop.get_imports = mocker.MagicMock(return_value={path_prop_import})
@@ -731,6 +671,19 @@ def test_from_data_no_security(self, mocker):
731671
endpoint=_add_responses.return_value[0], data=data, schemas=_add_responses.return_value[1]
732672
)
733673

674+
@pytest.mark.parametrize(
675+
"response_types, expected",
676+
(([], "None"), (["Something"], "Something"), (["First", "Second", "Second"], "Union[First, Second]")),
677+
)
678+
def test_response_type(self, response_types, expected):
679+
endpoint = self.make_endpoint()
680+
for response_type in response_types:
681+
mock_response = MagicMock()
682+
mock_response.prop.get_type_string.return_value = response_type
683+
endpoint.responses.append(mock_response)
684+
685+
assert endpoint.response_type() == expected
686+
734687

735688
class TestImportStringFromReference:
736689
def test_import_string_from_reference_no_prefix(self, mocker):

0 commit comments

Comments
 (0)
Please sign in to comment.