Skip to content

Commit

Permalink
Dataclass deepcopy 1.10 (#4963)
Browse files Browse the repository at this point in the history
* add test to reproduce #4949

* fix infinitely recursive deepcopy

* add test for shallow copy of wrapped dataclass

* fix infinitely recursive copy of wrapped dataclass

---------

Co-authored-by: Martin Billinger-Finke <2392396+mbillingr@users.noreply.github.com>
  • Loading branch information
mbillingr and mbillingr authored Feb 7, 2023
1 parent a699707 commit 0558af4
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
1 change: 1 addition & 0 deletions changes/4949-mbillingr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix `RecursionError` when deep-copying dataclass types wrapped by pydantic.
7 changes: 7 additions & 0 deletions pydantic/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class M:
The trick is to create a wrapper around `M` that will act as a proxy to trigger
validation without altering default `M` behaviour.
"""
import copy
import sys
from contextlib import contextmanager
from functools import wraps
Expand Down Expand Up @@ -260,6 +261,12 @@ def __setattr__(self, __name: str, __value: Any) -> None:
def __instancecheck__(self, instance: Any) -> bool:
return isinstance(instance, self.__dataclass__)

def __copy__(self) -> 'DataclassProxy':
return DataclassProxy(copy.copy(self.__dataclass__))

def __deepcopy__(self, memo: Any) -> 'DataclassProxy':
return DataclassProxy(copy.deepcopy(self.__dataclass__, memo))


def _add_pydantic_validation_attributes( # noqa: C901 (ignore complexity)
dc_cls: Type['Dataclass'],
Expand Down
23 changes: 23 additions & 0 deletions tests/test_dataclasses.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import copy
import dataclasses
import pickle
import re
Expand Down Expand Up @@ -1608,3 +1609,25 @@ def check_b(cls, v):
assert m1.a == m2.a == 3
assert m1.b == m2.b == 'b'
assert m1.c == m2.c == 3.0


def test_can_copy_wrapped_dataclass_type():
@pydantic.dataclasses.dataclass
@dataclasses.dataclass
class A:
name: int

B = copy.copy(A)
assert B is not A
assert B(1) == A(1)


def test_can_deepcopy_wrapped_dataclass_type():
@pydantic.dataclasses.dataclass
@dataclasses.dataclass
class A:
name: int

B = copy.deepcopy(A)
assert B is not A
assert B(1) == A(1)

0 comments on commit 0558af4

Please sign in to comment.