summaryrefslogtreecommitdiffstats
path: root/Lib/dataclasses.py
diff options
context:
space:
mode:
authorEric V. Smith <ericvsmith@users.noreply.github.com>2021-05-01 17:27:30 (GMT)
committerGitHub <noreply@github.com>2021-05-01 17:27:30 (GMT)
commit823fbf4e0eb66cbef0eacb7e8dbfb5dc8ea83b40 (patch)
treecdbfea3d509837970384db1c0db0141014419c7a /Lib/dataclasses.py
parentf82fd77717b58c97a16c05e25c72388b35860459 (diff)
downloadcpython-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.py23
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