Skip to content
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

allow __suppress_context__ and __notes__ to be mutated on frozen exceptions #1365

Merged
merged 10 commits into from
Oct 26, 2024
1 change: 1 addition & 0 deletions changelog.d/1365.change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow mutating `__suppress_context__` and `__notes__` on frozen exceptions.
6 changes: 6 additions & 0 deletions src/attr/_make.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ def _frozen_setattrs(self, name, value):
"__cause__",
"__context__",
"__traceback__",
"__suppress_context__",
"__notes__",
):
BaseException.__setattr__(self, name, value)
return
Expand All @@ -554,6 +556,10 @@ def _frozen_delattrs(self, name):
"""
Attached to frozen classes as __delattr__.
"""
if isinstance(self, BaseException) and name in ("__notes__",):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

from pep678 https://peps.python.org/pep-0678/#specification

Libraries may clear existing notes by modifying or deleting the notes list, if it has been created, including clearing all notes with del err.notes. This allows full control over the attached notes, without overly complicating the API or adding multiple names to BaseException.dict.

BaseException.__delattr__(self, name)
return

raise FrozenInstanceError


Expand Down
14 changes: 13 additions & 1 deletion tests/test_next_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import attr as _attr # don't use it by accident
import attrs

from attr._compat import PY_3_11_PLUS


@attrs.define
class C:
Expand Down Expand Up @@ -332,7 +334,7 @@ class MyException(Exception):
attrs.mutable,
],
)
def test_setting_traceback_on_exception(self, decorator):
def test_setting_exception_mutable_attributes(self, decorator):
"""
contextlib.contextlib (re-)sets __traceback__ on raised exceptions.

Expand All @@ -354,6 +356,16 @@ def do_nothing():

# this should not raise an exception either
ei.value.__traceback__ = ei.value.__traceback__
ei.value.__cause__ = ValueError("cause")
ei.value.__context__ = TypeError("context")
ei.value.__suppress_context__ = True
ei.value.__suppress_context__ = False
ei.value.__notes__ = []
del ei.value.__notes__

if PY_3_11_PLUS:
ei.value.add_note("note")
del ei.value.__notes__

def test_converts_and_validates_by_default(self):
"""
Expand Down