-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
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
contextlib.contextmanager
raises dataclasses.FrozenInstanceError
when handling a frozen dataclass exception
#99856
Comments
A similar thing happens when trying to raise Thrift exceptions, since they are also immutable. |
Shouldn’t we just document that exceptions must allow attribute assignment? That is, they can’t be “frozen”. |
Is there a reason not to use this? object.__setattr__(exc, '__traceback__', traceback) Instead of the existing: exc.__traceback__ = traceback |
I don't think we want to change all assignments to look like that. Where else in the stdlib would we need this, if we wanted to support frozen dataclasses everywhere? This also might break hashing assumptions. I'd rather just document that the classes must be mutable. |
@ericvsmith I only see 4 of those assignments in https://github.com/python/cpython/blob/main/Lib/contextlib.py -- was there something else you were referring to? As for hashing, at least the default hash implementation should be safe, since it is based on the dataclass fields. |
My concern is the precedent. I presume there are plenty of places in the stdlib where assignments are done to attributes on user-defined classes. I don't want to change every one of them to use this pattern of working around "frozen-ness". Why is it so important that exception subclasses be frozen? And why wouldn't that argument apply to other user-defined classes used by the stdlib? |
Would it make more sense for dataclasses to allow changing
It worked until 3.11. This seemed to be an unintentional side-effect of the change.
User-defined classes could allow changing |
Wouldn't removing |
No, because of the The intent of the design is that a frozen dataclass freezes all attributes, including inherited ones, but a mutable subclass of a frozen dataclass can add new mutable attributes. There is something a bit strange in this design, though. A frozen dataclass inheriting a mutable type will make the base type's attributes immutable, but if you have a mutable subclass of the frozen dataclass, suddenly the base class attributes become writable again (because there's no way to tell apart a mutable attribute from a non-dataclass base, vs a mutable attribute added by a mutable subclass.) This inconsistency is enough to convince me that ideally we should just remove the |
FWIW: |
@yilei : Do you know if they also exclude it from a hash calculation? |
@ericvsmith Not 100% sure, but I think it's excluded from hash. By default, with the new
When auto_exc is off and frozen, neither eq nor hash considers |
I thought I might chime in with another voice, because I've also stumbled on various problems with frozen dataclass exceptions, for example here. Incidentally, that thread includes an additional use case for where frozen instances (or rather, their hashing behavior) is particularly useful. Something I mentioned in that thread, which might be relevant in response to this bit:
What about adding an additional parameter to For what it's worth, when I first started using dataclasses, I assumed this to be the actual behavior. If your primary motivation for freezing the dataclass is to provide hashability based on the dataclass fields, then it makes intuitive sense that only the fields themselves would enforce immutability -- because the hash is only calculated on the fields, and therefore only the fields need to be frozen to provide a safe and stable hash function. It was kind of a big surprise to find out that this wasn't the case; it felt like a huge collateral impact for just a simple 11-character Additionally, because that isn't the case, there's a huge gigantic asterisk on inheritance when it comes to dataclasses, or even things as docile as caching things as private instance attributes. I find myself needing the |
#117211 was closed as a duplicate of this issue. The context was a test failing. It was agreed that some doc that exceptions must remain mutable should be added somewhere, to be discussed here. |
Bug report
In Python 3.11, raising a frozen dataclass as an exception inside a
contextlib.contextmanager
context will raise adataclasses.FrozenInstanceError
exception. This issue does not occur in Python 3.10.This is a result of the changes made in #92202
Reproducer
Expected Result
Actual Result
Your environment
The text was updated successfully, but these errors were encountered: