Skip to content

Commit 753f82d

Browse files
authored
gh-150069: Test frozen dataclass and properties interaction (#150070)
1 parent ddb6539 commit 753f82d

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
@@ -3377,35 +3377,115 @@ def test_non_frozen_normal_derived(self):
33773377
class D:
33783378
x: int
33793379
y: int = 10
3380+
z: int = 1
3381+
3382+
@property
3383+
def readonly(self) -> int:
3384+
return self.x
3385+
3386+
@property
3387+
def prop(self) -> int:
3388+
return self.z
3389+
3390+
@prop.setter
3391+
def prop(self, val: int) -> None:
3392+
object.__setattr__(self, 'z', val)
3393+
3394+
@prop.deleter
3395+
def prop(self) -> None:
3396+
object.__setattr__(self, 'z', 0)
3397+
3398+
d = D(5)
3399+
self.assertEqual(d.x, 5)
3400+
self.assertEqual(d.y, 10)
3401+
self.assertEqual(d.z, 1)
3402+
self.assertEqual(d.readonly, 5)
3403+
self.assertEqual(d.prop, 1)
3404+
3405+
with self.assertRaises(FrozenInstanceError):
3406+
d.x = 5
3407+
with self.assertRaises(FrozenInstanceError):
3408+
d.readonly = 5
3409+
with self.assertRaises(FrozenInstanceError):
3410+
d.z = 5
3411+
with self.assertRaises(FrozenInstanceError):
3412+
d.prop = 5
3413+
with self.assertRaises(FrozenInstanceError):
3414+
del d.prop
3415+
3416+
self.assertEqual(d.x, 5)
3417+
self.assertEqual(d.y, 10)
3418+
self.assertEqual(d.z, 1)
3419+
self.assertEqual(d.readonly, 5)
3420+
self.assertEqual(d.prop, 1)
33803421

33813422
class S(D):
33823423
pass
33833424

33843425
s = S(3)
33853426
self.assertEqual(s.x, 3)
33863427
self.assertEqual(s.y, 10)
3428+
self.assertEqual(s.z, 1)
3429+
self.assertEqual(s.readonly, 3)
3430+
self.assertEqual(s.prop, 1)
3431+
# Can set new attrs:
33873432
s.cached = True
3433+
self.assertTrue(s.cached)
3434+
# Can mutate them:
3435+
s.cached = False
3436+
self.assertFalse(s.cached)
3437+
3438+
# Can also change writable properties:
3439+
with self.assertRaisesRegex(
3440+
AttributeError,
3441+
'object has no setter',
3442+
) as cm:
3443+
s.readonly = 5
3444+
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
3445+
s.prop = 2
3446+
self.assertEqual(s.x, 3)
3447+
self.assertEqual(s.readonly, 3)
3448+
self.assertEqual(s.prop, 2)
3449+
self.assertEqual(s.z, 2)
33883450

33893451
# But can't change the frozen attributes.
33903452
with self.assertRaises(FrozenInstanceError):
33913453
s.x = 5
33923454
with self.assertRaises(FrozenInstanceError):
33933455
s.y = 5
3456+
with self.assertRaises(FrozenInstanceError):
3457+
s.z = 5
33943458
self.assertEqual(s.x, 3)
33953459
self.assertEqual(s.y, 10)
3396-
self.assertEqual(s.cached, True)
3460+
self.assertEqual(s.z, 2)
3461+
self.assertIs(s.cached, False)
33973462

33983463
with self.assertRaises(FrozenInstanceError):
33993464
del s.x
34003465
self.assertEqual(s.x, 3)
34013466
with self.assertRaises(FrozenInstanceError):
34023467
del s.y
34033468
self.assertEqual(s.y, 10)
3469+
with self.assertRaisesRegex(
3470+
AttributeError,
3471+
'object has no deleter',
3472+
) as cm:
3473+
del s.readonly
3474+
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
3475+
self.assertEqual(s.x, 3)
3476+
self.assertEqual(s.readonly, 3)
34043477
del s.cached
34053478
self.assertNotHasAttr(s, 'cached')
3406-
with self.assertRaises(AttributeError) as cm:
3479+
with self.assertRaisesRegex(
3480+
AttributeError,
3481+
"object has no attribute 'cached'",
3482+
) as cm:
34073483
del s.cached
34083484
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
3485+
del s.prop
3486+
self.assertEqual(s.z, 0)
3487+
self.assertEqual(s.prop, 0)
3488+
del s.prop
34093489

34103490
def test_non_frozen_normal_derived_from_empty_frozen(self):
34113491
@dataclass(frozen=True)

0 commit comments

Comments
 (0)