summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMehdi Drissi <mdrissi@hmc.edu>2024-03-12 06:11:56 (GMT)
committerGitHub <noreply@github.com>2024-03-12 06:11:56 (GMT)
commitd308d33e098d8e176f1e5169225d3cf800ed6aa1 (patch)
tree89f467abc8454891d68959a349e7cbbee0c23449
parent4fa95c6ec392b9fc80ad720cc4a8bd2786fc2835 (diff)
downloadcpython-d308d33e098d8e176f1e5169225d3cf800ed6aa1.zip
cpython-d308d33e098d8e176f1e5169225d3cf800ed6aa1.tar.gz
cpython-d308d33e098d8e176f1e5169225d3cf800ed6aa1.tar.bz2
gh-89547: Support for nesting special forms like Final (#116096)
-rw-r--r--Lib/test/test_typing.py40
-rw-r--r--Lib/typing.py4
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS.d/next/Library/2024-02-28-17-50-42.gh-issue-89547.GetF38.rst1
4 files changed, 32 insertions, 14 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 912384a..a9942b4 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -4656,8 +4656,6 @@ class GenericTests(BaseTestCase):
with self.assertRaises(TypeError):
Tuple[Optional]
with self.assertRaises(TypeError):
- ClassVar[ClassVar[int]]
- with self.assertRaises(TypeError):
List[ClassVar[int]]
def test_fail_with_bare_generic(self):
@@ -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):
diff --git a/Lib/typing.py b/Lib/typing.py
index cca9525..b235043 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -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
diff --git a/Misc/ACKS b/Misc/ACKS
index f01c7a7..03e458d 100644
--- 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
index 0000000..7be4591
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-02-28-17-50-42.gh-issue-89547.GetF38.rst
@@ -0,0 +1 @@
+Add support for nested typing special forms like Final[ClassVar[int]].