Skip to content
Prev Previous commit
Next Next commit
Test that cls.__annotations__ descriptor works.
Added a test to ensure that the new C getsetdef for
__annotations__ doesn't interfere with classes
(or metaclasses!) redefining __annotations__
using the descriptor protocol.
  • Loading branch information
larryhastings committed Apr 27, 2021
commit f36d27c6830dacd97a6bff296d6601edaaa4dc52
54 changes: 54 additions & 0 deletions Lib/test/test_type_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,57 @@ class C:
self.assertTrue("__annotations__" in C.__dict__)
del C.__annotations__
self.assertFalse("__annotations__" in C.__dict__)

def test_descriptor_still_works(self):
class C:
def __init__(self, name=None, bases=None, d=None):
self.my_annotations = None

@property
def __annotations__(self):
if not hasattr(self, 'my_annotations'):
self.my_annotations = {}
if not isinstance(self.my_annotations, dict):
self.my_annotations = {}
return self.my_annotations

@__annotations__.setter
def __annotations__(self, value):
if not isinstance(value, dict):
raise ValueError("can only set __annotations__ to a dict")
self.my_annotations = value

@__annotations__.deleter
def __annotations__(self):
if hasattr(self, 'my_annotations') and self.my_annotations == None:
raise AttributeError('__annotations__')
self.my_annotations = None

c = C()
self.assertEqual(c.__annotations__, {})
d = {'a':'int'}
c.__annotations__ = d
self.assertEqual(c.__annotations__, d)
with self.assertRaises(ValueError):
c.__annotations__ = 123
del c.__annotations__
with self.assertRaises(AttributeError):
del c.__annotations__
self.assertEqual(c.__annotations__, {})


class D(metaclass=C):
pass

self.assertEqual(D.__annotations__, {})
d = {'a':'int'}
D.__annotations__ = d
self.assertEqual(D.__annotations__, d)
with self.assertRaises(ValueError):
D.__annotations__ = 123
del D.__annotations__
with self.assertRaises(AttributeError):
del D.__annotations__
self.assertEqual(D.__annotations__, {})