@@ -151,7 +151,7 @@ def _type_convert(arg, module=None):
151
151
return arg
152
152
153
153
154
- def _type_check (arg , msg , is_argument = True , module = None ):
154
+ def _type_check (arg , msg , is_argument = True , module = None , * , is_class = False ):
155
155
"""Check that the argument is a type, and return it (internal helper).
156
156
157
157
As a special case, accept None and return type(None) instead. Also wrap strings
@@ -164,14 +164,16 @@ def _type_check(arg, msg, is_argument=True, module=None):
164
164
We append the repr() of the actual value (truncated to 100 chars).
165
165
"""
166
166
invalid_generic_forms = (Generic , Protocol )
167
- if is_argument :
168
- invalid_generic_forms = invalid_generic_forms + (ClassVar , Final )
167
+ if not is_class :
168
+ invalid_generic_forms += (ClassVar ,)
169
+ if is_argument :
170
+ invalid_generic_forms += (Final ,)
169
171
170
172
arg = _type_convert (arg , module = module )
171
173
if (isinstance (arg , _GenericAlias ) and
172
174
arg .__origin__ in invalid_generic_forms ):
173
175
raise TypeError (f"{ arg } is not valid as type argument" )
174
- if arg in (Any , NoReturn ):
176
+ if arg in (Any , NoReturn , Final ):
175
177
return arg
176
178
if isinstance (arg , _SpecialForm ) or arg in (Generic , Protocol ):
177
179
raise TypeError (f"Plain { arg } is not valid as type argument" )
@@ -662,9 +664,10 @@ class ForwardRef(_Final, _root=True):
662
664
663
665
__slots__ = ('__forward_arg__' , '__forward_code__' ,
664
666
'__forward_evaluated__' , '__forward_value__' ,
665
- '__forward_is_argument__' , '__forward_module__' )
667
+ '__forward_is_argument__' , '__forward_is_class__' ,
668
+ '__forward_module__' )
666
669
667
- def __init__ (self , arg , is_argument = True , module = None ):
670
+ def __init__ (self , arg , is_argument = True , module = None , * , is_class = False ):
668
671
if not isinstance (arg , str ):
669
672
raise TypeError (f"Forward reference must be a string -- got { arg !r} " )
670
673
try :
@@ -676,6 +679,7 @@ def __init__(self, arg, is_argument=True, module=None):
676
679
self .__forward_evaluated__ = False
677
680
self .__forward_value__ = None
678
681
self .__forward_is_argument__ = is_argument
682
+ self .__forward_is_class__ = is_class
679
683
self .__forward_module__ = module
680
684
681
685
def _evaluate (self , globalns , localns , recursive_guard ):
@@ -692,10 +696,11 @@ def _evaluate(self, globalns, localns, recursive_guard):
692
696
globalns = getattr (
693
697
sys .modules .get (self .__forward_module__ , None ), '__dict__' , globalns
694
698
)
695
- type_ = _type_check (
699
+ type_ = _type_check (
696
700
eval (self .__forward_code__ , globalns , localns ),
697
701
"Forward references must evaluate to types." ,
698
702
is_argument = self .__forward_is_argument__ ,
703
+ is_class = self .__forward_is_class__ ,
699
704
)
700
705
self .__forward_value__ = _eval_type (
701
706
type_ , globalns , localns , recursive_guard | {self .__forward_arg__ }
@@ -1799,7 +1804,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False):
1799
1804
if value is None :
1800
1805
value = type (None )
1801
1806
if isinstance (value , str ):
1802
- value = ForwardRef (value , is_argument = False )
1807
+ value = ForwardRef (value , is_argument = False , is_class = True )
1803
1808
value = _eval_type (value , base_globals , base_locals )
1804
1809
hints [name ] = value
1805
1810
return hints if include_extras else {k : _strip_annotations (t ) for k , t in hints .items ()}
@@ -1831,7 +1836,13 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False):
1831
1836
if value is None :
1832
1837
value = type (None )
1833
1838
if isinstance (value , str ):
1834
- value = ForwardRef (value )
1839
+ # class-level forward refs were handled above, this must be either
1840
+ # a module-level annotation or a function argument annotation
1841
+ value = ForwardRef (
1842
+ value ,
1843
+ is_argument = not isinstance (obj , types .ModuleType ),
1844
+ is_class = False ,
1845
+ )
1835
1846
value = _eval_type (value , globalns , localns )
1836
1847
if name in defaults and defaults [name ] is None :
1837
1848
value = Optional [value ]
0 commit comments