Skip to content

fix: skip redundant isinstance dispatch for homogeneous model unions - #1487

Open
AndersBennedsgaard wants to merge 1 commit into
openapi-generators:mainfrom
AndersBennedsgaard:fix/redundant-isinstance-union-model-dispatch
Open

fix: skip redundant isinstance dispatch for homogeneous model unions#1487
AndersBennedsgaard wants to merge 1 commit into
openapi-generators:mainfrom
AndersBennedsgaard:fix/redundant-isinstance-union-model-dispatch

Conversation

@AndersBennedsgaard

Copy link
Copy Markdown

When a property is a union of schemas that are all object/model types (e.g. oneOf: [ModelA, ModelB]), union_property.py.jinja's transform macro generated a per-member isinstance dispatch in to_dict(), even though every branch does the exact same thing (.to_dict()). The check never affects the outcome, since every generated model class converts identically.

Detect when every union member is model-shaped and skip the per-member dispatch:

  • required: unconditional dest = source.to_dict(), no isinstance at all
  • optional: else: dest = source.to_dict() after the existing Unset guard
  • optional request bodies (skip_unset=True, no Unset guard emitted yet): guard with if not isinstance(source, Unset) instead of the previous single-member isinstance(source, ModelX) check

Mixed unions (model + primitive/enum/None/Any members) are unaffected and keep their existing per-member dispatch, since those branches genuinely differ in behavior.

pdm run check run succesfully.

Discussion: #1486


Full disclosure: I used Claude Sonnet to help with the development. Feel free to point our any AI slop, happy to fix it

When a property is a union of schemas that are all object/model types
(e.g. `oneOf: [ModelA, ModelB]`), `union_property.py.jinja`'s `transform`
macro generated a per-member `isinstance` dispatch in `to_dict()`, even
though every branch does the exact same thing (`.to_dict()`). The check
never affects the outcome, since every generated model class converts
identically.

Detect when every union member is model-shaped and skip the per-member
dispatch:

- required: unconditional `dest = source.to_dict()`, no isinstance at all
- optional: `else: dest = source.to_dict()` after the existing Unset guard
- optional request bodies (`skip_unset=True`, no Unset guard emitted
  yet): guard with `if not isinstance(source, Unset)` instead of the
  previous single-member `isinstance(source, ModelX)` check

Mixed unions (model + primitive/enum/None/Any members) are unaffected
and keep their existing per-member dispatch, since those branches
genuinely differ in behavior.

Discussion: openapi-generators#1486
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant