fix: const variants in anyOf/oneOf unions fall through to later variants by Mohith26 · Pull Request #1508 · openapi-generators/openapi-python-client · GitHub
When a union had a const member that wasn't the last option, the generated parser ran the const check with no type check or try/except around it, so it returned (or raised) before trying the other variants. That shows up in a few places:
Model properties like anyOf: [{const: "auto"}, {type: integer}]: from_dict({"sizeOrAuto": 5}) raises ValueError.
prefixItems with a const prefix (already in the 3.1 golden record): any other string in the array raised ValueError.
to_multipart() on a model with a const inside a union generated isinstance(x, Literal["auto"]), which raises TypeError: Subscripted generics cannot be used with class and instance checks.
The change gives ConstProperty a get_instance_type_string() (the runtime type of the const value: str, int, float or bool) and a check_type_for_construct macro, so consts take the same try / type check / fallthrough path in union_property.py.jinja as every other member, and the multipart isinstance check uses a real type.
One behavior note: for oneOf: [{type: "null"}, {const: "x"}], a non-matching string now falls through to the final cast(...) like other union members already do (e.g. oneOf: [null, date]), instead of raising. The two golden-record diffs show exactly that.
Tests:
New functional tests in test_unions.py for model properties (const first, mixed str/int consts with a boolean, const plus $ref), a response union using a mocked httpx client, and to_multipart(). All but the type-hint test fail on main.
Unit test for ConstProperty.get_instance_type_string().
Regenerated golden records, then ruff check ., ruff format --check ., mypy openapi_python_client fuzz, and pytest --cov openapi_python_client tests end_to_end_tests (475 passed, 100% coverage).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1263
When a union had a const member that wasn't the last option, the generated parser ran the const check with no type check or try/except around it, so it returned (or raised) before trying the other variants. That shows up in a few places:
The change gives ConstProperty a get_instance_type_string() (the runtime type of the const value: str, int, float or bool) and a check_type_for_construct macro, so consts take the same try / type check / fallthrough path in union_property.py.jinja as every other member, and the multipart isinstance check uses a real type.
One behavior note: for oneOf: [{type: "null"}, {const: "x"}], a non-matching string now falls through to the final cast(...) like other union members already do (e.g. oneOf: [null, date]), instead of raising. The two golden-record diffs show exactly that.
Tests: