feat: Support responses with multiple media types in `content`
This PR modifies openapi-python-client to recognize multiple media types in OpenAPI response objects and to differentially parse HTTP responses based on their Content-Type header values. (Today, it generates code for a single content media type of the ones it encounters in the OpenAPI document.) This is useful eg for modeling services where a load balancer can send a 429 with plain text but the service behind it might send one with a schematized JSON response type.
Feedback is welcome, especially on the overall approach.
This PR adds unit tests and one end-to-end test, the latter of which includes sample generated code in the end_to_end_tests/multiple-media-types-golden-record/ subdirectory.
To maintain backward compatibility and minimize impact on existing callers, unexpected response content types raise the existing UnexpectedStatus error, rather than introducing a new error class
This uses exact string matching to compare returned content types with the media types from the schema. This offers only a subset of the available OpenAPI functionality: this PR does not provide support for wildcards, case insensitivity, or parameters. To add proper range matching (wildcard) support, we'd need something like the logic in python-mimeparse
Uncovered diff lines:
-
openapi_python_client/parser/openapi.py:204: This is a "belt-and-suspenders" check to avoid accessing an optional field if it is null. However, responses.py will not actually populate anyMediaTypeinstances with a nullprop.
for media_type in response.content:
if not media_type.prop: # pragma: no cover
continue
endpoint.relative_imports |= media_type.prop.get_lazy_imports(prefix=models_relative_prefix)
endpoint.relative_imports |= media_type.prop.get_imports(prefix=models_relative_prefix)
endpoint.responses.append(response)
C.f. #1248