]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-89547: Support for nesting special forms like Final (#116096)
authorMehdi Drissi <mdrissi@hmc.edu>
Tue, 12 Mar 2024 06:11:56 +0000 (23:11 -0700)
committerGitHub <noreply@github.com>
Tue, 12 Mar 2024 06:11:56 +0000 (23:11 -0700)
Lib/test/test_typing.py
Lib/typing.py
Misc/ACKS
Misc/NEWS.d/next/Library/2024-02-28-17-50-42.gh-issue-89547.GetF38.rst [new file with mode: 0644]

index 912384ab6bfe84a0afd8d12cfb608b36d082ef0c..a9942b44f29ed962e213386e7accbb50e45c3100 100644 (file)
@@ -4655,8 +4655,6 @@ class GenericTests(BaseTestCase):
             List[Union]
         with self.assertRaises(TypeError):
             Tuple[Optional]
-        with self.assertRaises(TypeError):
-            ClassVar[ClassVar[int]]
         with self.assertRaises(TypeError):
             List[ClassVar[int]]
 
@@ -6014,16 +6012,6 @@ class ForwardRefTests(BaseTestCase):
         for clazz in [C, D, E, F]:
             self.assertEqual(get_type_hints(clazz), expected_result)
 
-    def test_nested_classvar_fails_forward_ref_check(self):
-        class E:
-            foo: 'typing.ClassVar[typing.ClassVar[int]]' = 7
-        class F:
-            foo: ClassVar['ClassVar[int]'] = 7
-
-        for clazz in [E, F]:
-            with self.assertRaises(TypeError):
-                get_type_hints(clazz)
-
     def test_meta_no_type_check(self):
         depr_msg = (
             "'typing.no_type_check_decorator' is deprecated "
@@ -8716,6 +8704,34 @@ class AnnotatedTests(BaseTestCase):
         self.assertEqual(get_type_hints(C, globals())['classvar'], ClassVar[int])
         self.assertEqual(get_type_hints(C, globals())['const'], Final[int])
 
+    def test_special_forms_nesting(self):
+        # These are uncommon types and are to ensure runtime
+        # is lax on validation. See gh-89547 for more context.
+        class CF:
+            x: ClassVar[Final[int]]
+
+        class FC:
+            x: Final[ClassVar[int]]
+
+        class ACF:
+            x: Annotated[ClassVar[Final[int]], "a decoration"]
+
+        class CAF:
+            x: ClassVar[Annotated[Final[int], "a decoration"]]
+
+        class AFC:
+            x: Annotated[Final[ClassVar[int]], "a decoration"]
+
+        class FAC:
+            x: Final[Annotated[ClassVar[int], "a decoration"]]
+
+        self.assertEqual(get_type_hints(CF, globals())['x'], ClassVar[Final[int]])
+        self.assertEqual(get_type_hints(FC, globals())['x'], Final[ClassVar[int]])
+        self.assertEqual(get_type_hints(ACF, globals())['x'], ClassVar[Final[int]])
+        self.assertEqual(get_type_hints(CAF, globals())['x'], ClassVar[Final[int]])
+        self.assertEqual(get_type_hints(AFC, globals())['x'], Final[ClassVar[int]])
+        self.assertEqual(get_type_hints(FAC, globals())['x'], Final[ClassVar[int]])
+
     def test_cannot_subclass(self):
         with self.assertRaisesRegex(TypeError, "Cannot subclass .*Annotated"):
             class C(Annotated):
index cca9525d632ea5f9d729034d46e19baa4901e942..b2350433953ccddc7e86b3826c89387dbd18eb91 100644 (file)
@@ -653,7 +653,7 @@ def ClassVar(self, parameters):
     Note that ClassVar is not a class itself, and should not
     be used with isinstance() or issubclass().
     """
-    item = _type_check(parameters, f'{self} accepts only single type.')
+    item = _type_check(parameters, f'{self} accepts only single type.', allow_special_forms=True)
     return _GenericAlias(self, (item,))
 
 @_SpecialForm
@@ -675,7 +675,7 @@ def Final(self, parameters):
 
     There is no runtime checking of these properties.
     """
-    item = _type_check(parameters, f'{self} accepts only single type.')
+    item = _type_check(parameters, f'{self} accepts only single type.', allow_special_forms=True)
     return _GenericAlias(self, (item,))
 
 @_SpecialForm
index f01c7a70a65dc521ede67a8e16a034e0ba452527..03e458d170d2b83c5ad8fb034102f41816d532b6 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -470,6 +470,7 @@ Allen Downey
 Cesar Douady
 Dean Draayer
 Fred L. Drake, Jr.
+Mehdi Drissi
 Derk Drukker
 John DuBois
 Paul Dubois
diff --git a/Misc/NEWS.d/next/Library/2024-02-28-17-50-42.gh-issue-89547.GetF38.rst b/Misc/NEWS.d/next/Library/2024-02-28-17-50-42.gh-issue-89547.GetF38.rst
new file mode 100644 (file)
index 0000000..7be4591
--- /dev/null
@@ -0,0 +1 @@
+Add support for nested typing special forms like Final[ClassVar[int]].