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

* allow __suppress_context__ to be mutated on frozen exceptions

* add changelog

* and __notes__! lets' not forget that.

* add notes to news

* add tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix improt

* fix test

* fix tests again

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Thomas Grainger 2024-10-26 12:20:44 +01:00 committed by GitHub
parent 58cd3ae112
commit 1921da6eac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 20 additions and 1 deletions

View File

@ -0,0 +1 @@
Allow mutating `__suppress_context__` and `__notes__` on frozen exceptions.

View File

@ -543,6 +543,8 @@ def _frozen_setattrs(self, name, value):
"__cause__",
"__context__",
"__traceback__",
"__suppress_context__",
"__notes__",
):
BaseException.__setattr__(self, name, value)
return
@ -554,6 +556,10 @@ def _frozen_delattrs(self, name):
"""
Attached to frozen classes as __delattr__.
"""
if isinstance(self, BaseException) and name in ("__notes__",):
BaseException.__delattr__(self, name)
return
raise FrozenInstanceError

View File

@ -14,6 +14,8 @@ import pytest
import attr as _attr # don't use it by accident
import attrs
from attr._compat import PY_3_11_PLUS
@attrs.define
class C:
@ -332,7 +334,7 @@ class TestNextGen:
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.
@ -354,6 +356,16 @@ class TestNextGen:
# 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):
"""