Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions openapi_python_client/parser/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
property_from_data,
)
from .properties.schemas import parameter_from_reference
from .responses import HTTPStatusPattern, Responses, response_from_data
from .responses import HTTPStatusPattern, JSON_SOURCE, Responses, response_from_data, source_by_content_type

_PATH_PARAM_REGEX = re.compile("{([a-zA-Z_-][a-zA-Z0-9_-]*)}")

Expand Down Expand Up @@ -250,7 +250,20 @@ def add_parameters(
param = param_or_error # noqa: PLW2901

if param.param_schema is None:
continue
if param.content:
content_schemas = []
for content_type in param.content.keys():
if ((content := param.content.get(content_type)) is not None
and content.media_type_schema is not None
and source_by_content_type(content_type, config) is JSON_SOURCE
):
content_schemas.append(content.media_type_schema)
if len(content_schemas) == 1:
param.param_schema = content_schemas[0]
elif len(content_schemas) > 1:
param.param_schema = oai.Schema(oneOf=content_schemas)
else:
continue

unique_param = (param.name, param.param_in)
if unique_param in unique_parameters:
Expand Down
50 changes: 41 additions & 9 deletions openapi_python_client/parser/responses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
__all__ = ["HTTPStatusPattern", "Response", "Responses", "response_from_data"]
__all__ = [
"BYTES_SOURCE",
"HTTPStatusPattern",
"JSON_SOURCE",
"NONE_SOURCE",
"Response",
"response_from_data",
"Responses",
"source_by_content_type",
"TEXT_SOURCE",
]

from collections.abc import Iterator
from typing import TypedDict
Expand Down Expand Up @@ -128,7 +138,7 @@ def __lt__(self, other: "Response") -> bool:
return self.status_code < other.status_code


def _source_by_content_type(content_type: str, config: Config) -> _ResponseSource | None:
def source_by_content_type(content_type: str, config: Config) -> _ResponseSource | None:
parsed_content_type = utils.get_content_type(content_type, config)
if parsed_content_type is None:
return None
Expand Down Expand Up @@ -207,18 +217,35 @@ def response_from_data( # noqa: PLR0911
schemas,
)

schemas_ = []
source = None

for content_type, media_type in content.items():
source = _source_by_content_type(content_type, config)
if source is not None:
schema_data = media_type.media_type_schema
break
else:
source_ = source_by_content_type(content_type, config)

if source_ is None:
continue

if source is not None and source_ != source:
return (
ParseError(
data=data,
detail="Multiple response content types with different attributes are not supported",
),
schemas,
)
source = source_

if media_type.media_type_schema is not None:
schemas_.append(media_type.media_type_schema)

if source is None:
return (
ParseError(data=data, detail=f"Unsupported content_type {content}"),
ParseError(data=data, detail=f"Unsupported content_type(s) {content}"),
schemas,
)

if schema_data is None:
if not schemas_:
return (
empty_response(
status_code=status_code,
Expand All @@ -229,6 +256,11 @@ def response_from_data( # noqa: PLR0911
schemas,
)

if len(schemas_) == 1:
schema_data = schemas_[0]
else:
schema_data = oai.Schema(oneOf=schemas_)

prop, schemas = property_from_data(
name=response_name,
required=True,
Expand Down