]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-124206: Fix calling get_annotate_function() on static types (#124208)
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Wed, 18 Sep 2024 15:39:22 +0000 (08:39 -0700)
committerGitHub <noreply@github.com>
Wed, 18 Sep 2024 15:39:22 +0000 (08:39 -0700)
Fixes #124206. No news entry because the bug this fixes was never
released.

Lib/annotationlib.py
Lib/test/test_annotationlib.py
Lib/test/test_typing.py

index 9d1943b27e8e9cff78b31254619327470ae0f3c6..09a844ddb56f062bca96054fda21d0c94eeeae9f 100644 (file)
@@ -575,7 +575,11 @@ def get_annotate_function(obj):
     Returns the __annotate__ function or None.
     """
     if isinstance(obj, type):
-        return _BASE_GET_ANNOTATE(obj)
+        try:
+            return _BASE_GET_ANNOTATE(obj)
+        except AttributeError:
+            # AttributeError is raised for static types.
+            return None
     return getattr(obj, "__annotate__", None)
 
 
index ce4f92624d9036f3693101367ab392f55eef70d2..309f6d2120109a9972b8e54454b7d0471627a661 100644 (file)
@@ -928,6 +928,27 @@ class MetaclassTests(unittest.TestCase):
                             self.assertIs(annotate_func, None)
 
 
+class TestGetAnnotateFunction(unittest.TestCase):
+    def test_static_class(self):
+        self.assertIsNone(get_annotate_function(object))
+        self.assertIsNone(get_annotate_function(int))
+
+    def test_unannotated_class(self):
+        class C:
+            pass
+
+        self.assertIsNone(get_annotate_function(C))
+
+        D = type("D", (), {})
+        self.assertIsNone(get_annotate_function(D))
+
+    def test_annotated_class(self):
+        class C:
+            a: int
+
+        self.assertEqual(get_annotate_function(C)(Format.VALUE), {"a": int})
+
+
 class TestAnnotationLib(unittest.TestCase):
     def test__all__(self):
         support.check__all__(self, annotationlib)
index 6e036b600330c17cdf1e56f296163ec8e244739e..3ac6b97383fceffb770536cc352adab2a9670aa3 100644 (file)
@@ -7043,6 +7043,25 @@ class GetTypeHintTests(BaseTestCase):
         self.assertEqual(get_type_hints(g), {'x': collections.abc.Callable[..., int]})
         self.assertEqual(get_type_hints(h), {'x': collections.abc.Callable[P, int]})
 
+    def test_get_type_hints_format(self):
+        class C:
+            x: undefined
+
+        with self.assertRaises(NameError):
+            get_type_hints(C)
+
+        with self.assertRaises(NameError):
+            get_type_hints(C, format=annotationlib.Format.VALUE)
+
+        annos = get_type_hints(C, format=annotationlib.Format.FORWARDREF)
+        self.assertIsInstance(annos, dict)
+        self.assertEqual(list(annos), ['x'])
+        self.assertIsInstance(annos['x'], annotationlib.ForwardRef)
+        self.assertEqual(annos['x'].__arg__, 'undefined')
+
+        self.assertEqual(get_type_hints(C, format=annotationlib.Format.SOURCE),
+                         {'x': 'undefined'})
+
 
 class GetUtilitiesTestCase(TestCase):
     def test_get_origin(self):