Skip to content

fix: avoid variable-shadowing collision in model from_dict - #1485

Open
AndersBennedsgaard wants to merge 1 commit into
openapi-generators:mainfrom
AndersBennedsgaard:fix/1117-model-property-name-collision
Open

fix: avoid variable-shadowing collision in model from_dict#1485
AndersBennedsgaard wants to merge 1 commit into
openapi-generators:mainfrom
AndersBennedsgaard:fix/1117-model-property-name-collision

Conversation

@AndersBennedsgaard

@AndersBennedsgaard AndersBennedsgaard commented Sep 10, 2026

Copy link
Copy Markdown

Fixes #1117


from_dict used to bind the constructed instance to a local variable named after the class's snake_case module name (e.g. email = cls(...)). If any property snake_cased to that same name, the earlier email = d.pop("email") assignment got reassigned to a different type, which breaks static type checkers like mypy/pyright even though the generated code works fine at runtime.

Instead of picking a "hopefully unique" temporary name, from_dict now always returns cls(...) directly with no intermediate variable, so the collision is structurally impossible rather than merely unlikely. This requires additional_properties to be settable via the constructor, so init=False was dropped from that attrs field; as a side effect, additional_properties is now also usable with attrs.evolve() and the constructor directly.

Golden records and integration-tests fixtures regenerated accordingly. Added ModelWithSelfNamedProperty to the baseline specs as a regression test: a property whose snake_case name collides with its class's module name, verified via the existing mypy --strict check in the e2e suite.

pdm run check run succesfully.


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

…enerators#1117)

`from_dict` used to bind the constructed instance to a local variable
named after the class's snake_case module name (e.g. `email = cls(...)`).
If any property snake_cased to that same name, the earlier
`email = d.pop("email")` assignment got reassigned to a different type,
which breaks static type checkers like mypy/pyright even though the
generated code works fine at runtime.

Instead of picking a "hopefully unique" temporary name, `from_dict` now
always returns `cls(...)` directly with no intermediate variable, so the
collision is structurally impossible rather than merely unlikely. This
requires `additional_properties` to be settable via the constructor, so
`init=False` was dropped from that attrs field; as a side effect,
`additional_properties` is now also usable with `attrs.evolve()` and the
constructor directly.

Golden records and integration-tests fixtures regenerated accordingly.
Added `ModelWithSelfNamedProperty` to the baseline specs as a regression
test: a property whose snake_case name collides with its class's module
name, verified via the existing `mypy --strict` check in the e2e suite.
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.

Linting error when class has a property with the same name after snake case

1 participant