New submission from David Hagen <da...@drhagen.com>:

If a dataclass is `frozen` and has `__slots__`, then unpickling an instance of 
it fails because the default behavior is to use `setattr` which `frozen` does 
not allow.

```
import pickle
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
  __slots__ = ('a',)
  a: int

b = pickle.dumps(A(5))
pickle.loads(b)
```

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'a'
```

This has a straightforward workaround, namely to use `object.setattr`.

```
import pickle
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
    __slots__ = ('a',)
    a: int

    def __getstate__(self):
        return dict(
            (slot, getattr(self, slot))
            for slot in self.__slots__
            if hasattr(self, slot)
        )

    def __setstate__(self, state):
        for slot, value in state.items():
            object.__setattr__(self, slot, value)


b = pickle.dumps(A(5))
pickle.loads(b)
```

It would be nice if this was fixed for all frozen, slotted dataclasses.

Originally report on SO: 
https://stackoverflow.com/questions/55307017/pickle-a-frozen-dataclass-that-has-slots

----------
messages: 338803
nosy: drhagen
priority: normal
severity: normal
status: open
title: Pickle fails on frozen dataclass that has slots
type: behavior
versions: Python 3.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue36424>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to