acme.messages.Error: add mutability (#9546)

* acme.messages.Error: add mutability

As of Python 3.11, an exception caught within a `with` statement will
update the __traceback__ attribute. Because acme.messages.Error was
immutable, this was causing a knock-on exception, causing certbot to
exit abnormally. This commit hacks in mutability for acme.messages.Error

Fixes #9539

* Add CHANGELOG entry
This commit is contained in:
Will Greenberg
2023-01-25 09:06:53 +11:00
committed by GitHub
parent 613e698199
commit 81ff6fcc0d
3 changed files with 25 additions and 1 deletions
+7
View File
@@ -123,6 +123,9 @@ class Error(jose.JSONObjectWithFields, errors.Error):
https://datatracker.ietf.org/doc/html/rfc7807 https://datatracker.ietf.org/doc/html/rfc7807
Note: Although Error inherits from JSONObjectWithFields, which is immutable,
we add mutability for Error to comply with the Python exception API.
:ivar str typ: :ivar str typ:
:ivar str title: :ivar str title:
:ivar str detail: :ivar str detail:
@@ -185,6 +188,10 @@ class Error(jose.JSONObjectWithFields, errors.Error):
return code return code
return None return None
# Hack to allow mutability on Errors (see GH #9539)
def __setattr__(self, name: str, value: Any) -> None:
return object.__setattr__(self, name, value)
def __str__(self) -> str: def __str__(self) -> str:
result = b' :: '.join( result = b' :: '.join(
part.encode('ascii', 'backslashreplace') for part in part.encode('ascii', 'backslashreplace') for part in
+17
View File
@@ -1,6 +1,7 @@
"""Tests for acme.messages.""" """Tests for acme.messages."""
from typing import Dict from typing import Dict
import unittest import unittest
import contextlib
from unittest import mock from unittest import mock
import warnings import warnings
@@ -91,6 +92,22 @@ class ErrorTest(unittest.TestCase):
u"Problem for {1.identifier.value}: {1.typ} :: {1.description} :: {1.detail} :: {1.title}").format( u"Problem for {1.identifier.value}: {1.typ} :: {1.description} :: {1.detail} :: {1.title}").format(
self.error_with_subproblems, self.subproblem)) self.error_with_subproblems, self.subproblem))
# this test is based on a minimal reproduction of a contextmanager/immutable
# exception related error: https://github.com/python/cpython/issues/99856
def test_with_context_manager(self):
from acme.messages import Error
@contextlib.contextmanager
def context():
yield
try:
with context():
raise self.error_custom
except Error as e:
self.assertIsNotNone(self.error_custom.__traceback__)
class ConstantTest(unittest.TestCase): class ConstantTest(unittest.TestCase):
"""Tests for acme.messages._Constant.""" """Tests for acme.messages._Constant."""
+1 -1
View File
@@ -17,7 +17,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
### Fixed ### Fixed
* * Fixed a bug where Certbot would crash with `AttributeError: can't set attribute` on ACME server errors in Python 3.11. See [GH #9539](https://github.com/certbot/certbot/issues/9539).
More details about these changes can be found on our GitHub repo. More details about these changes can be found on our GitHub repo.