Skip to content

Commit 3757703

Browse files
bpo-46539: Pass status of special typeforms to forward references (GH-30926)
Previously this didn't matter because there weren't any valid code paths that could trigger a type check with a special form, but after the bug fix for `Annotated` wrapping special forms it's now possible to annotate something like `Annotated['ClassVar[int]', (3, 4)]`. This change would also be needed for proposed future changes, such as allowing `ClassVar` and `Final` to nest each other in dataclasses. (cherry picked from commit ced5005) Co-authored-by: Gregory Beauregard <greg@greg.red>
1 parent 8e98ccc commit 3757703

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

Lib/test/test_typing.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,20 @@ def foo(a: 'Callable[..., T]'):
26232623
self.assertEqual(get_type_hints(foo, globals(), locals()),
26242624
{'a': Callable[..., T]})
26252625

2626+
def test_special_forms_forward(self):
2627+
2628+
class C:
2629+
a: Annotated['ClassVar[int]', (3, 5)] = 4
2630+
b: Annotated['Final[int]', "const"] = 4
2631+
2632+
class CF:
2633+
b: List['Final[int]'] = 4
2634+
2635+
self.assertEqual(get_type_hints(C, globals())['a'], ClassVar[int])
2636+
self.assertEqual(get_type_hints(C, globals())['b'], Final[int])
2637+
with self.assertRaises(TypeError):
2638+
get_type_hints(CF, globals()),
2639+
26262640
def test_syntax_error(self):
26272641

26282642
with self.assertRaises(SyntaxError):

Lib/typing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@
125125
# legitimate imports of those modules.
126126

127127

128-
def _type_convert(arg, module=None):
128+
def _type_convert(arg, module=None, *, allow_special_forms=False):
129129
"""For converting None to type(None), and strings to ForwardRef."""
130130
if arg is None:
131131
return type(None)
132132
if isinstance(arg, str):
133-
return ForwardRef(arg, module=module)
133+
return ForwardRef(arg, module=module, is_class=allow_special_forms)
134134
return arg
135135

136136

@@ -152,7 +152,7 @@ def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms=
152152
if is_argument:
153153
invalid_generic_forms += (Final,)
154154

155-
arg = _type_convert(arg, module=module)
155+
arg = _type_convert(arg, module=module, allow_special_forms=allow_special_forms)
156156
if (isinstance(arg, _GenericAlias) and
157157
arg.__origin__ in invalid_generic_forms):
158158
raise TypeError(f"{arg} is not valid as type argument")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
In :func:`typing.get_type_hints`, support evaluating stringified ``ClassVar`` and ``Final`` annotations inside ``Annotated``. Patch by Gregory Beauregard.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy