gh-119180: PEP 649: Add __annotate__ attributes (#119209)

This commit is contained in:
Jelle Zijlstra 2024-05-21 22:38:12 -04:00 committed by GitHub
parent 73ab83b27f
commit e9875ecb5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 324 additions and 18 deletions

View file

@ -1564,7 +1564,7 @@ class SizeofTest(unittest.TestCase):
check(x, size('3Pi2cP7P2ic??2P'))
# function
def func(): pass
check(func, size('15Pi'))
check(func, size('16Pi'))
class c():
@staticmethod
def foo():

View file

@ -1,4 +1,5 @@
import textwrap
import types
import unittest
from test.support import run_code
@ -212,3 +213,46 @@ class TestSetupAnnotations(unittest.TestCase):
case 0:
x: int = 1
""")
class AnnotateTests(unittest.TestCase):
"""See PEP 649."""
def test_manual_annotate(self):
def f():
pass
mod = types.ModuleType("mod")
class X:
pass
for obj in (f, mod, X):
with self.subTest(obj=obj):
self.check_annotations(obj)
def check_annotations(self, f):
self.assertEqual(f.__annotations__, {})
self.assertIs(f.__annotate__, None)
with self.assertRaisesRegex(TypeError, "__annotate__ must be callable or None"):
f.__annotate__ = 42
f.__annotate__ = lambda: 42
with self.assertRaisesRegex(TypeError, r"takes 0 positional arguments but 1 was given"):
print(f.__annotations__)
f.__annotate__ = lambda x: 42
with self.assertRaisesRegex(TypeError, r"__annotate__ returned non-dict of type 'int'"):
print(f.__annotations__)
f.__annotate__ = lambda x: {"x": x}
self.assertEqual(f.__annotations__, {"x": 1})
# Setting annotate to None does not invalidate the cached __annotations__
f.__annotate__ = None
self.assertEqual(f.__annotations__, {"x": 1})
# But setting it to a new callable does
f.__annotate__ = lambda x: {"y": x}
self.assertEqual(f.__annotations__, {"y": 1})
# Setting f.__annotations__ also clears __annotate__
f.__annotations__ = {"z": 43}
self.assertIs(f.__annotate__, None)

View file

@ -3723,7 +3723,7 @@ class ProtocolTests(BaseTestCase):
acceptable_extra_attrs = {
'_is_protocol', '_is_runtime_protocol', '__parameters__',
'__init__', '__annotations__', '__subclasshook__',
'__init__', '__annotations__', '__subclasshook__', '__annotate__',
}
self.assertLessEqual(vars(NonP).keys(), vars(C).keys() | acceptable_extra_attrs)
self.assertLessEqual(

View file

@ -1889,6 +1889,7 @@ _SPECIAL_NAMES = frozenset({
'__init__', '__module__', '__new__', '__slots__',
'__subclasshook__', '__weakref__', '__class_getitem__',
'__match_args__', '__static_attributes__', '__firstlineno__',
'__annotate__',
})
# These special attributes will be not collected as protocol members.