|
17 | 17 | from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol, DefaultDict
|
18 | 18 | from typing import get_type_hints
|
19 | 19 | from collections import deque, OrderedDict, namedtuple, defaultdict
|
| 20 | +from copy import deepcopy |
20 | 21 | from functools import total_ordering
|
21 | 22 |
|
22 | 23 | import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation.
|
@@ -3071,6 +3072,48 @@ class C:
|
3071 | 3072 | with self.assertRaisesRegex(TypeError, 'unhashable type'):
|
3072 | 3073 | hash(C({}))
|
3073 | 3074 |
|
| 3075 | + def test_frozen_deepcopy_without_slots(self): |
| 3076 | + # see: https://github.com/python/cpython/issues/89683 |
| 3077 | + @dataclass(frozen=True, slots=False) |
| 3078 | + class C: |
| 3079 | + s: str |
| 3080 | + |
| 3081 | + c = C('hello') |
| 3082 | + self.assertEqual(deepcopy(c), c) |
| 3083 | + |
| 3084 | + def test_frozen_deepcopy_with_slots(self): |
| 3085 | + # see: https://github.com/python/cpython/issues/89683 |
| 3086 | + with self.subTest('generated __slots__'): |
| 3087 | + @dataclass(frozen=True, slots=True) |
| 3088 | + class C: |
| 3089 | + s: str |
| 3090 | + |
| 3091 | + c = C('hello') |
| 3092 | + self.assertEqual(deepcopy(c), c) |
| 3093 | + |
| 3094 | + with self.subTest('user-defined __slots__ and no __{get,set}state__'): |
| 3095 | + @dataclass(frozen=True, slots=False) |
| 3096 | + class C: |
| 3097 | + __slots__ = ('s',) |
| 3098 | + s: str |
| 3099 | + |
| 3100 | + # with user-defined slots, __getstate__ and __setstate__ are not |
| 3101 | + # automatically added, hence the error |
| 3102 | + err = r"^cannot\ assign\ to\ field\ 's'$" |
| 3103 | + self.assertRaisesRegex(FrozenInstanceError, err, deepcopy, C('')) |
| 3104 | + |
| 3105 | + with self.subTest('user-defined __slots__ and __{get,set}state__'): |
| 3106 | + @dataclass(frozen=True, slots=False) |
| 3107 | + class C: |
| 3108 | + __slots__ = ('s',) |
| 3109 | + __getstate__ = dataclasses._dataclass_getstate |
| 3110 | + __setstate__ = dataclasses._dataclass_setstate |
| 3111 | + |
| 3112 | + s: str |
| 3113 | + |
| 3114 | + c = C('hello') |
| 3115 | + self.assertEqual(deepcopy(c), c) |
| 3116 | + |
3074 | 3117 |
|
3075 | 3118 | class TestSlots(unittest.TestCase):
|
3076 | 3119 | def test_simple(self):
|
|
0 commit comments