diff options
author | Jelle Zijlstra <jelle.zijlstra@gmail.com> | 2024-05-22 02:38:12 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-22 02:38:12 (GMT) |
commit | e9875ecb5dd3a9c44a184c71cc562ce1fea6e03b (patch) | |
tree | 9b8aca9a11a3c8e1e1278cbe0293a0eab5f622a2 /Lib | |
parent | 73ab83b27f105a4509046ce26e35f20d66625195 (diff) | |
download | cpython-e9875ecb5dd3a9c44a184c71cc562ce1fea6e03b.zip cpython-e9875ecb5dd3a9c44a184c71cc562ce1fea6e03b.tar.gz cpython-e9875ecb5dd3a9c44a184c71cc562ce1fea6e03b.tar.bz2 |
gh-119180: PEP 649: Add __annotate__ attributes (#119209)
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_sys.py | 2 | ||||
-rw-r--r-- | Lib/test/test_type_annotations.py | 44 | ||||
-rw-r--r-- | Lib/test/test_typing.py | 2 | ||||
-rw-r--r-- | Lib/typing.py | 1 |
4 files changed, 47 insertions, 2 deletions
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index ee3bd00..8fe1d77 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -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(): diff --git a/Lib/test/test_type_annotations.py b/Lib/test/test_type_annotations.py index 3dbb35a..5e3c334 100644 --- a/Lib/test/test_type_annotations.py +++ b/Lib/test/test_type_annotations.py @@ -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) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 64c4c49..dac55ce 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -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( diff --git a/Lib/typing.py b/Lib/typing.py index 4345745..be49aa6 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -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. |