Skip to content

Commit d594cbc

Browse files
committed
complete Final, Generic cases
1 parent aebc55c commit d594cbc

File tree

2 files changed

+58
-37
lines changed

2 files changed

+58
-37
lines changed

src/test_typing_extensions.py

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8300,20 +8300,29 @@ class Y(Generic[T_in_G], _EasyStr):
83008300
Format.FORWARDREF: TypeError,
83018301
Format.STRING: "Protocol",
83028302
},
8303-
Final: [ # plain usage of Final
8304-
{
8305-
"skip_if": {"is_class": False},
8306-
Format.VALUE: Final,
8307-
Format.FORWARDREF: Final,
8308-
Format.STRING: Final,
8309-
},
8310-
{
8311-
"skip_if": {"is_class": True},
8312-
Format.VALUE: TypeError,
8313-
Format.FORWARDREF: TypeError,
8314-
Format.STRING: Final,
8315-
},
8316-
],
8303+
Final: (
8304+
[ # plain usage of Final
8305+
{
8306+
"skip_if": {"is_class": False},
8307+
Format.VALUE: Final,
8308+
Format.FORWARDREF: Final,
8309+
Format.STRING: str(Final),
8310+
},
8311+
{
8312+
"skip_if": {"is_class": True},
8313+
Format.VALUE: TypeError,
8314+
Format.FORWARDREF: TypeError,
8315+
Format.STRING: str(Final),
8316+
},
8317+
]
8318+
if _FORWARD_REF_HAS_CLASS
8319+
else Final # no errors here
8320+
),
8321+
Generic: {
8322+
Format.VALUE: TypeError,
8323+
Format.FORWARDREF: TypeError,
8324+
Format.STRING: "Generic",
8325+
},
83178326
Union[str, None, "str"]: {
83188327
Format.VALUE: Optional[str],
83198328
Format.FORWARDREF: Optional[str],
@@ -8340,6 +8349,8 @@ def _unroll_subcase(
83408349
):
83418350
type_params = expected.get("type_params", None)
83428351
skip_if = expected.get("skip_if", False)
8352+
if format not in expected:
8353+
return
83438354
if skip_if:
83448355
L = locals()
83458356
skip = all(
@@ -8411,17 +8422,17 @@ def unroll_cases(cases, outer_locals):
84118422
),
84128423
)
84138424
else:
8425+
# NOTE: only for non-dict inputs
84148426
# Change expected to TypeError if it will fail typing._type_check
8415-
if not inspect.isclass(expected):
8427+
if format != Format.STRING and not inspect.isclass(expected):
84168428
invalid_generic_forms = (Generic, Protocol)
8417-
if not is_class:
8429+
if is_class is False:
84188430
invalid_generic_forms += (ClassVar,)
84198431
if is_argument:
84208432
invalid_generic_forms += (Final,)
8421-
if (
8422-
format != Format.STRING
8423-
and get_origin(expected) in invalid_generic_forms
8424-
):
8433+
elif not _FORWARD_REF_HAS_CLASS and is_argument:
8434+
invalid_generic_forms += (ClassVar, Final,)
8435+
if get_origin(expected) in invalid_generic_forms:
84258436
expected = TypeError
84268437
type_params = None
84278438
yield (
@@ -8450,12 +8461,6 @@ def unroll_cases(cases, outer_locals):
84508461
ref = typing.ForwardRef(annot, is_argument=is_argument, is_class=is_class)
84518462
else:
84528463
ref = typing.ForwardRef(annot, is_argument=is_argument)
8453-
expected_orig = expected
8454-
orig_globalns = globalns
8455-
orig_localns = localns
8456-
expected = expected_orig
8457-
globalns = orig_globalns
8458-
localns = orig_localns
84598464
with self.subTest(
84608465
format=format,
84618466
ref=ref,

src/typing_extensions.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4065,24 +4065,28 @@ def _lax_type_check(
40654065
type_ = typing._type_convert(value)
40664066
else:
40674067
if value is None:
4068-
type_ = type(None)
4069-
elif isinstance(value, str):
4070-
type_ = ForwardRef(value)
4071-
else:
4072-
type_ = value
4068+
return type(None)
4069+
if isinstance(value, str):
4070+
return ForwardRef(value)
4071+
type_ = value
4072+
if type(type_) is tuple: # early versions raise with callable here
4073+
raise exec
40734074
invalid_generic_forms = (Generic, Protocol)
40744075
if not allow_special_forms:
40754076
invalid_generic_forms += (ClassVar,)
40764077
if is_argument:
40774078
invalid_generic_forms += (Final,)
4078-
if type(type_) is tuple:
4079-
raise exec
40804079
if (
40814080
isinstance(type_, typing._GenericAlias)
4082-
and type_.__origin__ in invalid_generic_forms
4081+
and get_origin(type_) in invalid_generic_forms
40834082
):
40844083
raise TypeError(f"{type_} is not valid as type argument") from None
4085-
if isinstance(type_, (_SpecialForm, typing._SpecialForm)) or type_ in (Generic, Protocol):
4084+
if allow_special_forms is not None and type_ in (ClassVar, Final):
4085+
return type_
4086+
if (
4087+
isinstance(type_, (_SpecialForm, typing._SpecialForm))
4088+
or type_ in (Generic, Protocol)
4089+
):
40864090
raise TypeError(f"Plain {type_} is not valid as type argument") from None
40874091
return type_
40884092

@@ -4160,9 +4164,21 @@ def evaluate_forward_ref(
41604164
msg,
41614165
is_argument=forward_ref.__forward_is_argument__,
41624166
allow_special_forms=(
4163-
_FORWARD_REF_HAS_CLASS and forward_ref.__forward_is_class__
4164-
)
4167+
(_FORWARD_REF_HAS_CLASS and forward_ref.__forward_is_class__)
4168+
or
4169+
( _FORWARD_REF_HAS_CLASS and None) # pass None in this case
4170+
),
41654171
)
4172+
else:
4173+
# ClassVar/Final could pass _type_check but should error
4174+
if sys.version_info < (3, 11) and (
4175+
_FORWARD_REF_HAS_CLASS
4176+
and not forward_ref.__forward_is_class__
4177+
and value in (ClassVar, Final)
4178+
):
4179+
raise TypeError(f"Plain {type_} is not valid as type argument")
4180+
4181+
del value
41664182

41674183
# Check if evaluation is possible
41684184
if isinstance(type_, ForwardRef):

0 commit comments

Comments
 (0)