https://github.com/python/cpython/commit/753f82db2fed38bf725ded2b333ea3749c81fe82
commit: 753f82db2fed38bf725ded2b333ea3749c81fe82
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-07-02T12:48:47Z
summary:
gh-150069: Test frozen dataclass and properties interaction (#150070)
files:
M Lib/test/test_dataclasses/__init__.py
diff --git a/Lib/test/test_dataclasses/__init__.py
b/Lib/test/test_dataclasses/__init__.py
index 423247c92ce3c2..a89999bb97938c 100644
--- a/Lib/test/test_dataclasses/__init__.py
+++ b/Lib/test/test_dataclasses/__init__.py
@@ -3377,6 +3377,47 @@ def test_non_frozen_normal_derived(self):
class D:
x: int
y: int = 10
+ z: int = 1
+
+ @property
+ def readonly(self) -> int:
+ return self.x
+
+ @property
+ def prop(self) -> int:
+ return self.z
+
+ @prop.setter
+ def prop(self, val: int) -> None:
+ object.__setattr__(self, 'z', val)
+
+ @prop.deleter
+ def prop(self) -> None:
+ object.__setattr__(self, 'z', 0)
+
+ d = D(5)
+ self.assertEqual(d.x, 5)
+ self.assertEqual(d.y, 10)
+ self.assertEqual(d.z, 1)
+ self.assertEqual(d.readonly, 5)
+ self.assertEqual(d.prop, 1)
+
+ with self.assertRaises(FrozenInstanceError):
+ d.x = 5
+ with self.assertRaises(FrozenInstanceError):
+ d.readonly = 5
+ with self.assertRaises(FrozenInstanceError):
+ d.z = 5
+ with self.assertRaises(FrozenInstanceError):
+ d.prop = 5
+ with self.assertRaises(FrozenInstanceError):
+ del d.prop
+
+ self.assertEqual(d.x, 5)
+ self.assertEqual(d.y, 10)
+ self.assertEqual(d.z, 1)
+ self.assertEqual(d.readonly, 5)
+ self.assertEqual(d.prop, 1)
class S(D):
pass
@@ -3384,16 +3425,40 @@ class S(D):
s = S(3)
self.assertEqual(s.x, 3)
self.assertEqual(s.y, 10)
+ self.assertEqual(s.z, 1)
+ self.assertEqual(s.readonly, 3)
+ self.assertEqual(s.prop, 1)
+ # Can set new attrs:
s.cached = True
+ self.assertTrue(s.cached)
+ # Can mutate them:
+ s.cached = False
+ self.assertFalse(s.cached)
+
+ # Can also change writable properties:
+ with self.assertRaisesRegex(
+ AttributeError,
+ 'object has no setter',
+ ) as cm:
+ s.readonly = 5
+ self.assertNotIsInstance(cm.exception, FrozenInstanceError)
+ s.prop = 2
+ self.assertEqual(s.x, 3)
+ self.assertEqual(s.readonly, 3)
+ self.assertEqual(s.prop, 2)
+ self.assertEqual(s.z, 2)
# But can't change the frozen attributes.
with self.assertRaises(FrozenInstanceError):
s.x = 5
with self.assertRaises(FrozenInstanceError):
s.y = 5
+ with self.assertRaises(FrozenInstanceError):
+ s.z = 5
self.assertEqual(s.x, 3)
self.assertEqual(s.y, 10)
- self.assertEqual(s.cached, True)
+ self.assertEqual(s.z, 2)
+ self.assertIs(s.cached, False)
with self.assertRaises(FrozenInstanceError):
del s.x
@@ -3401,11 +3466,26 @@ class S(D):
with self.assertRaises(FrozenInstanceError):
del s.y
self.assertEqual(s.y, 10)
+ with self.assertRaisesRegex(
+ AttributeError,
+ 'object has no deleter',
+ ) as cm:
+ del s.readonly
+ self.assertNotIsInstance(cm.exception, FrozenInstanceError)
+ self.assertEqual(s.x, 3)
+ self.assertEqual(s.readonly, 3)
del s.cached
self.assertNotHasAttr(s, 'cached')
- with self.assertRaises(AttributeError) as cm:
+ with self.assertRaisesRegex(
+ AttributeError,
+ "object has no attribute 'cached'",
+ ) as cm:
del s.cached
self.assertNotIsInstance(cm.exception, FrozenInstanceError)
+ del s.prop
+ self.assertEqual(s.z, 0)
+ self.assertEqual(s.prop, 0)
+ del s.prop
def test_non_frozen_normal_derived_from_empty_frozen(self):
@dataclass(frozen=True)
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]