Skip to content

Conversation

@dawdameet
Copy link

Fixed Misleading "Not an instance or subtype" error when assigning to property of frozen, slotted dataclass.

Fix a crash in frozen dataclasses with slots where the generated
setattr and delattr methods used super(cls, self).

When slots rebuild the class, the captured cls no longer matches the
instance type, causing a TypeError at runtime.

Use object.setattr and object.delattr instead to preserve frozen
semantics safely.

gh-143969

@dawdameet dawdameet requested a review from ericvsmith as a code owner January 17, 2026 17:27
@python-cla-bot
Copy link

python-cla-bot bot commented Jan 17, 2026

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app
Copy link

bedevere-app bot commented Jan 17, 2026

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add a test case. And please, do not change lines that are just changed because of the formatting. Only change lines that are directly related to your change :)

Thanks for the PR!

@dawdameet dawdameet force-pushed the fix-frozen-slots-setattr branch from 3d83ed6 to 9f63ad5 Compare January 17, 2026 19:40
' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
f' super(cls, self).__setattr__(name, value)'),
' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
' object.__setattr__(self, name, value)'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this fix is correct, because it ignores parent's __setattr__ method.

The root cause of the bug might be something related to the __closure__ cell of the property? See https://github.com/python-attrs/attrs/blob/28526a872ec882c69d5d30932c1a520ef2520309/src/attr/_make.py#L959-L990 for the context.

Or it might be not :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am really sorry, I pushed the object.setattr change just before seeing your comment!

You are right, bypassing super breaks inheritance for any parent classes that override setattr. I will revert the object change locally and look into the closure / class cell solution you linked. I'll update the PR once I have a fix that respects the MRO. Thank you for the heads up! I'm learning a lot from this!

@dawdameet dawdameet force-pushed the fix-frozen-slots-setattr branch from 9f63ad5 to 1c3e0c9 Compare January 17, 2026 20:09
…osure cells

When a dataclass is frozen and uses slots, the class object is replaced.
This causes generated methods using super() to fail because their
closure cells point to the old class. This fix updates the closure
cells in the generated methods to point to the new class.
@dawdameet dawdameet force-pushed the fix-frozen-slots-setattr branch from 1c3e0c9 to 34cfdda Compare January 17, 2026 20:41
@@ -0,0 +1,2 @@
Fixed a crash in frozen slotted dataclasses where assigning to an attribute
could raise an internal TypeError instead of failing cleanly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
could raise an internal TypeError instead of failing cleanly.
could raise an internal :exc:`TypeError` instead of failing cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants