Skip to content

Commit 358620d

Browse files
committed
[3.13] gh-150069: Test frozen dataclass and properties interaction (GH-150070)
(cherry picked from commit 753f82d) Co-authored-by: sobolevn <mail@sobolevn.me>
1 parent f7431eb commit 358620d

1 file changed

Lines changed: 82 additions & 2 deletions

File tree

Lib/test/test_dataclasses/__init__.py

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,35 +3152,115 @@ def test_non_frozen_normal_derived(self):
31523152
class D:
31533153
x: int
31543154
y: int = 10
3155+
z: int = 1
3156+
3157+
@property
3158+
def readonly(self) -> int:
3159+
return self.x
3160+
3161+
@property
3162+
def prop(self) -> int:
3163+
return self.z
3164+
3165+
@prop.setter
3166+
def prop(self, val: int) -> None:
3167+
object.__setattr__(self, 'z', val)
3168+
3169+
@prop.deleter
3170+
def prop(self) -> None:
3171+
object.__setattr__(self, 'z', 0)
3172+
3173+
d = D(5)
3174+
self.assertEqual(d.x, 5)
3175+
self.assertEqual(d.y, 10)
3176+
self.assertEqual(d.z, 1)
3177+
self.assertEqual(d.readonly, 5)
3178+
self.assertEqual(d.prop, 1)
3179+
3180+
with self.assertRaises(FrozenInstanceError):
3181+
d.x = 5
3182+
with self.assertRaises(FrozenInstanceError):
3183+
d.readonly = 5
3184+
with self.assertRaises(FrozenInstanceError):
3185+
d.z = 5
3186+
with self.assertRaises(FrozenInstanceError):
3187+
d.prop = 5
3188+
with self.assertRaises(FrozenInstanceError):
3189+
del d.prop
3190+
3191+
self.assertEqual(d.x, 5)
3192+
self.assertEqual(d.y, 10)
3193+
self.assertEqual(d.z, 1)
3194+
self.assertEqual(d.readonly, 5)
3195+
self.assertEqual(d.prop, 1)
31553196

31563197
class S(D):
31573198
pass
31583199

31593200
s = S(3)
31603201
self.assertEqual(s.x, 3)
31613202
self.assertEqual(s.y, 10)
3203+
self.assertEqual(s.z, 1)
3204+
self.assertEqual(s.readonly, 3)
3205+
self.assertEqual(s.prop, 1)
3206+
# Can set new attrs:
31623207
s.cached = True
3208+
self.assertTrue(s.cached)
3209+
# Can mutate them:
3210+
s.cached = False
3211+
self.assertFalse(s.cached)
3212+
3213+
# Can also change writable properties:
3214+
with self.assertRaisesRegex(
3215+
AttributeError,
3216+
'object has no setter',
3217+
) as cm:
3218+
s.readonly = 5
3219+
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
3220+
s.prop = 2
3221+
self.assertEqual(s.x, 3)
3222+
self.assertEqual(s.readonly, 3)
3223+
self.assertEqual(s.prop, 2)
3224+
self.assertEqual(s.z, 2)
31633225

31643226
# But can't change the frozen attributes.
31653227
with self.assertRaises(FrozenInstanceError):
31663228
s.x = 5
31673229
with self.assertRaises(FrozenInstanceError):
31683230
s.y = 5
3231+
with self.assertRaises(FrozenInstanceError):
3232+
s.z = 5
31693233
self.assertEqual(s.x, 3)
31703234
self.assertEqual(s.y, 10)
3171-
self.assertEqual(s.cached, True)
3235+
self.assertEqual(s.z, 2)
3236+
self.assertIs(s.cached, False)
31723237

31733238
with self.assertRaises(FrozenInstanceError):
31743239
del s.x
31753240
self.assertEqual(s.x, 3)
31763241
with self.assertRaises(FrozenInstanceError):
31773242
del s.y
31783243
self.assertEqual(s.y, 10)
3244+
with self.assertRaisesRegex(
3245+
AttributeError,
3246+
'object has no deleter',
3247+
) as cm:
3248+
del s.readonly
3249+
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
3250+
self.assertEqual(s.x, 3)
3251+
self.assertEqual(s.readonly, 3)
31793252
del s.cached
31803253
self.assertFalse(hasattr(s, 'cached'))
3181-
with self.assertRaises(AttributeError) as cm:
3254+
with self.assertRaisesRegex(
3255+
AttributeError,
3256+
"object has no attribute 'cached'",
3257+
) as cm:
31823258
del s.cached
31833259
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
3260+
del s.prop
3261+
self.assertEqual(s.z, 0)
3262+
self.assertEqual(s.prop, 0)
3263+
del s.prop
31843264

31853265
def test_non_frozen_normal_derived_from_empty_frozen(self):
31863266
@dataclass(frozen=True)

0 commit comments

Comments
 (0)