Skip to content

Commit 6caec60

Browse files
committed
- Fixed body param handling (supporting lists)
- Pushed back to 100% code cov
1 parent dedf6ba commit 6caec60

File tree

5 files changed

+80
-11
lines changed

5 files changed

+80
-11
lines changed

src/openapi_python_generator/language_converters/python/service_generator.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,34 @@ def generate_body_param(operation: Operation) -> Union[str, None]:
3131
if operation.requestBody is None:
3232
return None
3333
else:
34-
return "data"
34+
if isinstance(operation.requestBody, Reference):
35+
return "data.dict()"
36+
37+
if operation.requestBody.content is None:
38+
return None # pragma: no cover
39+
40+
if operation.requestBody.content.get("application/json") is None:
41+
return None # pragma: no cover
42+
43+
media_type = operation.requestBody.content.get("application/json")
44+
45+
if media_type is None:
46+
return None # pragma: no cover
47+
48+
if isinstance(media_type.media_type_schema, Reference):
49+
return "data.dict()"
50+
elif isinstance(media_type.media_type_schema, Schema):
51+
schema = media_type.media_type_schema
52+
if schema.type == "array":
53+
return "[i.dict() for i in data]"
54+
else:
55+
raise Exception(
56+
f"Unsupported schema type for request body: {schema.type}"
57+
) # pragma: no cover
58+
else:
59+
raise Exception(
60+
f"Unsupported schema type for request body: {type(media_type.media_type_schema)}"
61+
) # pragma: no cover
3562

3663

3764
def generate_params(operation: Operation) -> str:
@@ -49,7 +76,7 @@ def _generate_params_from_content(content: Union[Reference, Schema]):
4976
if operation.parameters is not None:
5077
for param in operation.parameters:
5178
if not isinstance(param, Parameter):
52-
continue
79+
continue # pragma: no cover
5380
converted_result = ""
5481
required = False
5582

@@ -90,7 +117,9 @@ def _generate_params_from_content(content: Union[Reference, Schema]):
90117
f"{_generate_params_from_content(content.media_type_schema)}, "
91118
)
92119
else:
93-
raise Exception(f"Unsupported media type schema for {str(operation)}")
120+
raise Exception(
121+
f"Unsupported media type schema for {str(operation)}"
122+
) # pragma: no cover
94123
else:
95124
raise Exception(
96125
f"Unsupported request body type: {type(operation.requestBody)}"
@@ -103,7 +132,7 @@ def generate_operation_id(operation: Operation, http_op: str) -> str:
103132
if operation.operationId is not None:
104133
return f"{operation.operationId.replace('-', '_')}"
105134
else:
106-
raise Exception(f"OperationId is not defined for {http_op}")
135+
raise Exception(f"OperationId is not defined for {http_op}") # pragma: no cover
107136

108137

109138
def generate_query_params(operation: Operation) -> List[str]:
@@ -135,7 +164,9 @@ def generate_return_type(operation: Operation) -> OpReturnType:
135164
if isinstance(chosen_response, Response) and chosen_response.content is not None:
136165
media_type_schema = chosen_response.content.get("application/json")
137166
elif isinstance(chosen_response, Reference):
138-
media_type_schema = MediaType(media_type_schema=chosen_response)
167+
media_type_schema = MediaType(
168+
media_type_schema=chosen_response
169+
) # pragma: no cover
139170
else:
140171
return OpReturnType(
141172
type=None, status_code=good_responses[0][0], complex_type=False

src/openapi_python_generator/language_converters/python/templates/httpx.jinja2

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
'Accept': 'application/json',
77
'Authorization': f'Bearer { APIConfig.get_access_token() }',
88
}
9-
query_params = {
9+
query_params : Dict[str,Any] = {
1010
{% if query_params|length > 0 %}
1111
{{ query_params | join(',\n') | safe }}
1212
{% endif %}
1313
}
1414

1515
{% if async_client %}
16-
with httpx.AsyncClient(base_url=base_path) as client:
16+
async with httpx.AsyncClient(base_url=base_path) as client:
1717
response = await client.request(
1818
{% else %}
1919
with httpx.Client(base_url=base_path) as client:
@@ -24,7 +24,7 @@ with httpx.Client(base_url=base_path) as client:
2424
headers=headers,
2525
params=query_params,
2626
{% if body_param %}
27-
json = json.dumps({{ body_param }}.dict())
27+
json = json.dumps({{ body_param }})
2828
{% endif %}
2929
)
3030

src/openapi_python_generator/language_converters/python/templates/requests.jinja2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def {{ operation_id }}({{ params }}) -> {% if return_type.type is none or return
66
'Accept': 'application/json',
77
'Authorization': f'Bearer { APIConfig.get_access_token() }',
88
}
9-
query_params = {
9+
query_params : Dict[str,Any] = {
1010
{% if query_params|length > 0 %}
1111
{{ query_params | join(',\n') | safe }}
1212
{% endif %}
@@ -18,7 +18,7 @@ def {{ operation_id }}({{ params }}) -> {% if return_type.type is none or return
1818
headers=headers,
1919
params=query_params,
2020
{% if body_params|length > 0 %}
21-
json=json.dumps({{ body_param }}.dict())
21+
json=json.dumps({{ body_param }})
2222
{% endif %}
2323
)
2424
if response.status_code != {{ return_type.status_code }}:

tests/test_model_generator.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ def test_type_converter_simple(test_openapi_types, expected_python_types):
7373
)
7474

7575

76+
def test_type_converter_all_of_reference():
77+
schema = Schema(
78+
allOf=[Reference(ref="#/components/schemas/test_name"), Schema(type="string")]
79+
)
80+
assert type_converter(schema, True).converted_type == "Tuple[test_name,str]"
81+
82+
schema = Schema(
83+
oneOf=[Reference(ref="#/components/schemas/test_name"), Schema(type="string")]
84+
)
85+
assert type_converter(schema, True).converted_type == "Union[test_name,str]"
86+
87+
7688
@pytest.mark.parametrize(
7789
"test_openapi_types,expected_python_types",
7890
[
@@ -222,3 +234,10 @@ def test_model_generation(model_data: OpenAPI):
222234
assert i.content is not None
223235

224236
compile(i.content, "<string>", "exec")
237+
238+
model_data_copy = model_data.copy()
239+
model_data_copy.components.schemas = None # type: ignore
240+
241+
result = generate_models(model_data_copy.components) # type: ignore
242+
243+
assert len(result) == 0

tests/test_service_generator.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,26 @@
4646
}
4747
)
4848
),
49-
"data",
49+
"data.dict()",
50+
),
51+
(
52+
Operation(requestBody=Reference(ref="#/components/schemas/TestModel")),
53+
"data.dict()",
54+
),
55+
(
56+
Operation(
57+
requestBody=RequestBody(
58+
content={
59+
"application/json": MediaType(
60+
media_type_schema=Schema(
61+
type="array",
62+
items=Reference(ref="#/components/schemas/TestModel"),
63+
)
64+
)
65+
}
66+
)
67+
),
68+
"[i.dict() for i in data]",
5069
),
5170
(Operation(requestBody=None), None),
5271
],

0 commit comments

Comments
 (0)