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:
Miss Islington (bot) 2022-07-05 11:44:31 -07:00 committed by GitHub
parent d49c99f10d
commit 552fc9a9ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 167 additions and 0 deletions

View file

@ -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):