-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
bpo-45897: Fix frozen-slotted dataclass bug #29895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
9c36be6
bpo-45897: Fix frozen-slotted dataclass bug
AlexWaygood e968679
Tweak test
AlexWaygood df2216b
Address review
AlexWaygood a71575f
Add further clarification
AlexWaygood eda3c7f
Add more comments
AlexWaygood 9af7074
Update Lib/test/test_dataclasses.py
AlexWaygood 9f8c91c
Update Lib/test/test_dataclasses.py
AlexWaygood ce675c5
Add comment
AlexWaygood 007a596
Use self.assertRaisesRegex, since Erlend insists ;)
AlexWaygood bea4c9d
79-character wrap
AlexWaygood c93c2be
Merge branch 'main' into dataclass-slots
AlexWaygood 34c66f3
Merge remote-tracking branch 'origin' into dataclass-slots
AlexWaygood a105c6e
Merge branch 'dataclass-slots' of https://github.com/AlexWaygood/cpyt…
AlexWaygood b7ef7b9
Fix trailing whitespace
AlexWaygood 3d04919
Merge branch 'main' into dataclass-slots
AlexWaygood d29551c
Merge branch 'main' into dataclass-slots
AlexWaygood File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -605,16 +605,25 @@ def _frozen_get_del_attr(cls, fields, globals): | |
else: | ||
# Special case for the zero-length tuple. | ||
fields_str = '()' | ||
|
||
# bpo-45897: Do not raise FrozenInstanceError | ||
# if the dataclass has slots & the attribute is not specified in __slots__. | ||
# Instead, let the standard __slots__ machinery raise AttributeError naturally | ||
# in the super(cls, self).__setattr__ call | ||
return (_create_fn('__setattr__', | ||
('self', 'name', 'value'), | ||
(f'if type(self) is cls or name in {fields_str}:', | ||
(f'if "__slots__" in cls.__dict__ and name not in cls.__slots__:', | ||
' pass', | ||
f'elif type(self) is cls or name in {fields_str}:', | ||
' raise FrozenInstanceError(f"cannot assign to field {name!r}")', | ||
f'super(cls, self).__setattr__(name, value)'), | ||
locals=locals, | ||
globals=globals), | ||
_create_fn('__delattr__', | ||
('self', 'name'), | ||
(f'if type(self) is cls or name in {fields_str}:', | ||
(f'if "__slots__" in cls.__dict__ and name not in cls.__slots__:', | ||
' pass', | ||
f'elif type(self) is cls or name in {fields_str}:', | ||
' raise FrozenInstanceError(f"cannot delete field {name!r}")', | ||
f'super(cls, self).__delattr__(name)'), | ||
locals=locals, | ||
|
@@ -1075,12 +1084,6 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, | |
f'in class {cls.__name__}. Consider using ' | ||
'functools.total_ordering') | ||
|
||
if frozen: | ||
for fn in _frozen_get_del_attr(cls, field_list, globals): | ||
if _set_new_attribute(cls, fn.__name__, fn): | ||
raise TypeError(f'Cannot overwrite attribute {fn.__name__} ' | ||
f'in class {cls.__name__}') | ||
|
||
# Decide if/how we're going to create a hash function. | ||
hash_action = _hash_action[bool(unsafe_hash), | ||
bool(eq), | ||
|
@@ -1107,6 +1110,14 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, | |
if slots: | ||
cls = _add_slots(cls, frozen, weakref_slot) | ||
|
||
# Frozen __setattr__/__delattr__ must be added after __slots__ | ||
# bpo-45897 | ||
if frozen: | ||
for fn in _frozen_get_del_attr(cls, field_list, globals): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this function ought to be named |
||
if _set_new_attribute(cls, fn.__name__, fn): | ||
raise TypeError(f'Cannot overwrite attribute {fn.__name__} ' | ||
f'in class {cls.__name__}') | ||
|
||
abc.update_abstractmethods(cls) | ||
|
||
return cls | ||
|
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
4 changes: 4 additions & 0 deletions
4
Misc/NEWS.d/next/Library/2021-12-01-21-45-43.bpo-45897.lAZPRy.rst
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Fix bug in dataclasses where a frozen dataclass with slots would raise | ||
``TypeError`` rather than ``AttributeError`` if a user attempted to | ||
set/delete an attribute that was not specified in ``__slots__``. Patch by | ||
Alex Waygood. |
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.
Uh oh!
There was an error while loading. Please reload this page.