@@ -85,6 +85,7 @@ def complete_dataclass(
85
85
cls : type [Any ],
86
86
config_wrapper : _config .ConfigWrapper ,
87
87
* ,
88
+ slots : bool ,
88
89
raise_errors : bool = True ,
89
90
ns_resolver : NsResolver | None = None ,
90
91
_force_build : bool = False ,
@@ -98,6 +99,7 @@ def complete_dataclass(
98
99
Args:
99
100
cls: The class.
100
101
config_wrapper: The config wrapper instance.
102
+ slots: Whether slots was set on the class.
101
103
raise_errors: Whether to raise errors, defaults to `True`.
102
104
ns_resolver: The namespace resolver instance to use when collecting dataclass fields
103
105
and during schema building.
@@ -194,6 +196,27 @@ def validated_setattr(instance: Any, field: str, value: str, /) -> None:
194
196
195
197
cls .__setattr__ = validated_setattr .__get__ (None , cls ) # type: ignore
196
198
199
+ if slots and not hasattr (cls , '__setstate__' ):
200
+ # If slots is set, `pickle` (relied on by `copy.copy()`) will use
201
+ # `__setattr__()` to reconstruct the dataclass. However, the custom
202
+ # `__setattr__()` set above relies on `validate_assignment()`, which
203
+ # in turn excepts all the field values to be already present on the
204
+ # instance, resulting in attribute errors.
205
+ # As such, we make use of `object.__setattr__()` instead.
206
+ # Note that we do so only if `__setstate__()` isn't already set (this is the
207
+ # case if on top of `slots`, `frozen` is used).
208
+
209
+ # Taken from `dataclasses._dataclass_get/setstate()`:
210
+ def _dataclass_getstate (self : Any ) -> list [Any ]:
211
+ return [getattr (self , f .name ) for f in dataclasses .fields (self )]
212
+
213
+ def _dataclass_setstate (self : Any , state : list [Any ]) -> None :
214
+ for field , value in zip (dataclasses .fields (self ), state ):
215
+ object .__setattr__ (self , field .name , value )
216
+
217
+ cls .__getstate__ = _dataclass_getstate # pyright: ignore[reportAttributeAccessIssue]
218
+ cls .__setstate__ = _dataclass_setstate
219
+
197
220
cls .__pydantic_complete__ = True
198
221
return True
199
222
0 commit comments