-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
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
dataclasses should allow frozendict default value #88840
Comments
Using a frozendict as a default value should not cause an error in dataclasses. The check for mutability is: isinstance(f.default, (list, dict, set)) It appears frozendict has been changed to have a dict base class and it now raises an exception. There should be a way to indicate object mutability as the purpose of the isinstance(f.default, (list, dict, set)) check is for mutable default values. Using default_factory to work around this issue is cumbersome. |
I agree that would be an improvement. |
Which frozendict does your message concern? I found this in some test: cpython/Lib/test/test_builtin.py Line 741 in bb3e0c2
I'm not sure indicating that an object should be immutable to dataclasses will be less cumbersome than default_factory. Currently, you have to do this:
But, indicating mutability would be something like this:
|
When I originally read this, I read it as frozenset. I agree that there's no good way of telling if an arbitrary class is immutable, so I'm not sure we can do anything here. So I think we should close this as a rejected idea. |
@arjun - this is about default values (See the bug description - Using a frozendict as a default value) Try this: from frozendict import frozendict
from dataclasses import dataclass
@dataclass
class A:
a: frozendict = frozendict(a=1) This used to work until frozendict became a subclass of dict. Perhaps another fix is to convert any dict to a frozendict? Maybe not. How would you handle this case? The only thing I figured was: AD=frozendict(a=1)
@dataclass
class A:
a: frozendict = field(default_factory=lambda:AD) Which imho is cumbersome. |
[Eric]
Consider using non-hashability as a proxy indicator for immutability.
While this is imperfect, it would be more reliable than what we have now. |
That's a good idea, Raymond. >>> [x.__hash__ is None for x in (list, dict, set, frozenset)]
[True, True, True, False] I don't think this change would cause any backward compatibility issues, except it would now allow a default of something bad like: >>> class BadList(list):
... def __hash__(self): return 0
...
>>> isinstance(BadList(), list), BadList.__hash__ is None
(True, False) I can't say I care too much about now allowing things that didn't used to be allowed, especially if they're poorly designed like BadList. I'll put together a PR. |
Excellent. Thanks! |
@gianni: can you verify that your use case works in 3.11? |
When trying to import hydra in Python 3.11, it throws following error: ```python File "/home/user/projects/iterative/hydra/hydra/conf/__init__.py", line 75, in JobConf @DataClass ^^^^^^^^^ File "/home/user/.pyenv/versions/3.11-dev/lib/python3.11/dataclasses.py", line 1221, in dataclass return wrap(cls) ^^^^^^^^^ File "/home/user/.pyenv/versions/3.11-dev/lib/python3.11/dataclasses.py", line 1211, in wrap return _process_class(cls, init, repr, eq, order, unsafe_hash, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/user/.pyenv/versions/3.11-dev/lib/python3.11/dataclasses.py", line 959, in _process_class cls_fields.append(_get_field(cls, name, type, kw_only)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/user/.pyenv/versions/3.11-dev/lib/python3.11/dataclasses.py", line 816, in _get_field raise ValueError(f'mutable default {type(f.default)} for field ' ValueError: mutable default <class 'hydra.conf.JobConf.JobConfig.OverrideDirname'> for field override_dirname is not allowed: use default_factory ``` This is due to a recent change in dataclasses in Python 3.11 that disallows mutable to be set as a default value. This is done via check for hashability. See python/cpython#88840. Note that I am trying to add support for Python 3.11 to hydra. This seems like a major blocker. For reproducibility, I used the following command to search for these: ```console rg ".*: .* = [A-Z].*\(.*\)" ```
Is there a more precise alternative? For example, JAX arrays are immutable but unhashable. The current mutability "check" causes errors like these (and the ones linked above). |
At least, perhaps the error message could be changed to say
since that's what's actually being checked, to avoid confusion? |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: