diff options
author | Eric V. Smith <ericvsmith@users.noreply.github.com> | 2021-05-01 17:27:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-01 17:27:30 (GMT) |
commit | 823fbf4e0eb66cbef0eacb7e8dbfb5dc8ea83b40 (patch) | |
tree | cdbfea3d509837970384db1c0db0141014419c7a /Lib/dataclasses.py | |
parent | f82fd77717b58c97a16c05e25c72388b35860459 (diff) | |
download | cpython-823fbf4e0eb66cbef0eacb7e8dbfb5dc8ea83b40.zip cpython-823fbf4e0eb66cbef0eacb7e8dbfb5dc8ea83b40.tar.gz cpython-823fbf4e0eb66cbef0eacb7e8dbfb5dc8ea83b40.tar.bz2 |
If using a frozen class with slots, add __getstate__ and __setstate__ to set the instance values. (GH-25786)
Diffstat (limited to 'Lib/dataclasses.py')
-rw-r--r-- | Lib/dataclasses.py | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 5e57163..363d0b6 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1087,14 +1087,28 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, tuple(f.name for f in std_init_fields)) if slots: - cls = _add_slots(cls) + cls = _add_slots(cls, frozen) abc.update_abstractmethods(cls) return cls -def _add_slots(cls): +# _dataclass_getstate and _dataclass_setstate are needed for pickling frozen +# classes with slots. These could be slighly more performant if we generated +# the code instead of iterating over fields. But that can be a project for +# another day, if performance becomes an issue. +def _dataclass_getstate(self): + return [getattr(self, f.name) for f in fields(self)] + + +def _dataclass_setstate(self, state): + for field, value in zip(fields(self), state): + # use setattr because dataclass may be frozen + object.__setattr__(self, field.name, value) + + +def _add_slots(cls, is_frozen): # Need to create a new class, since we can't set __slots__ # after a class has been created. @@ -1120,6 +1134,11 @@ def _add_slots(cls): if qualname is not None: cls.__qualname__ = qualname + if is_frozen: + # Need this for pickling frozen classes with slots. + cls.__getstate__ = _dataclass_getstate + cls.__setstate__ = _dataclass_setstate + return cls |