mirror of
https://github.com/python/cpython.git
synced 2025-07-19 01:05:26 +00:00
gh-91330: Tests and docs for dataclass descriptor-typed fields (GH-94424) (GH-94576)
Co-authored-by: Erik De Bonte <erikd@microsoft.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
(cherry picked from commit 5f319308a8
)
This commit is contained in:
parent
d49c99f10d
commit
552fc9a9ac
3 changed files with 167 additions and 0 deletions
|
@ -3229,6 +3229,115 @@ class TestDescriptors(unittest.TestCase):
|
|||
|
||||
self.assertEqual(D.__set_name__.call_count, 1)
|
||||
|
||||
def test_init_calls_set(self):
|
||||
class D:
|
||||
pass
|
||||
|
||||
D.__set__ = Mock()
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
i: D = D()
|
||||
|
||||
# Make sure D.__set__ is called.
|
||||
D.__set__.reset_mock()
|
||||
c = C(5)
|
||||
self.assertEqual(D.__set__.call_count, 1)
|
||||
|
||||
def test_getting_field_calls_get(self):
|
||||
class D:
|
||||
pass
|
||||
|
||||
D.__set__ = Mock()
|
||||
D.__get__ = Mock()
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
i: D = D()
|
||||
|
||||
c = C(5)
|
||||
|
||||
# Make sure D.__get__ is called.
|
||||
D.__get__.reset_mock()
|
||||
value = c.i
|
||||
self.assertEqual(D.__get__.call_count, 1)
|
||||
|
||||
def test_setting_field_calls_set(self):
|
||||
class D:
|
||||
pass
|
||||
|
||||
D.__set__ = Mock()
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
i: D = D()
|
||||
|
||||
c = C(5)
|
||||
|
||||
# Make sure D.__set__ is called.
|
||||
D.__set__.reset_mock()
|
||||
c.i = 10
|
||||
self.assertEqual(D.__set__.call_count, 1)
|
||||
|
||||
def test_setting_uninitialized_descriptor_field(self):
|
||||
class D:
|
||||
pass
|
||||
|
||||
D.__set__ = Mock()
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
i: D
|
||||
|
||||
# D.__set__ is not called because there's no D instance to call it on
|
||||
D.__set__.reset_mock()
|
||||
c = C(5)
|
||||
self.assertEqual(D.__set__.call_count, 0)
|
||||
|
||||
# D.__set__ still isn't called after setting i to an instance of D
|
||||
# because descriptors don't behave like that when stored as instance vars
|
||||
c.i = D()
|
||||
c.i = 5
|
||||
self.assertEqual(D.__set__.call_count, 0)
|
||||
|
||||
def test_default_value(self):
|
||||
class D:
|
||||
def __get__(self, instance: Any, owner: object) -> int:
|
||||
if instance is None:
|
||||
return 100
|
||||
|
||||
return instance._x
|
||||
|
||||
def __set__(self, instance: Any, value: int) -> None:
|
||||
instance._x = value
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
i: D = D()
|
||||
|
||||
c = C()
|
||||
self.assertEqual(c.i, 100)
|
||||
|
||||
c = C(5)
|
||||
self.assertEqual(c.i, 5)
|
||||
|
||||
def test_no_default_value(self):
|
||||
class D:
|
||||
def __get__(self, instance: Any, owner: object) -> int:
|
||||
if instance is None:
|
||||
raise AttributeError()
|
||||
|
||||
return instance._x
|
||||
|
||||
def __set__(self, instance: Any, value: int) -> None:
|
||||
instance._x = value
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
i: D = D()
|
||||
|
||||
with self.assertRaisesRegex(TypeError, 'missing 1 required positional argument'):
|
||||
c = C()
|
||||
|
||||
class TestStringAnnotations(unittest.TestCase):
|
||||
def test_classvar(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue