Skip to content

Commit a1777f3

Browse files
committed
Assure UnionType stays UnionType; check repr only
+ updated comments
1 parent 52c93e9 commit a1777f3

File tree

2 files changed

+14
-6
lines changed

2 files changed

+14
-6
lines changed

src/test_typing_extensions.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,7 +1679,7 @@ def test_annotation_and_optional_default(self):
16791679
Union["annotation", T_default] : Union[annotation, T_default],
16801680
Annotated["annotation", "nested"] : Annotated[Union[int, None], "data", "nested"],
16811681
}
1682-
if TYPING_3_10_0: # cannot construct UnionTypes
1682+
if TYPING_3_10_0: # cannot construct UnionTypes before 3.10
16831683
do_not_stringify_cases["str | NoneAlias | StrAlias"] = str | None
16841684
cases[str | None] = Optional[str]
16851685
cases.update(do_not_stringify_cases)
@@ -1690,7 +1690,7 @@ def test_annotation_and_optional_default(self):
16901690
skip_reason = None
16911691
annot_unchanged = annot
16921692
if sys.version_info[:2] == (3, 10) and annot == "str | NoneAlias | StrAlias" and none_default:
1693-
# different repr here as Optional[str | None] -> Optional[str] not a UnionType
1693+
# In 3.10 converts Optional[str | None] to Optional[str] which has a different repr
16941694
skip_reason = "UnionType not preserved in 3.10"
16951695
if wrap_optional:
16961696
if annot_unchanged == ():
@@ -1726,11 +1726,13 @@ def func(x: annot): pass
17261726
# Hash
17271727
for k in type_hints.keys():
17281728
self.assertEqual(hash(type_hints[k]), hash(expected[k]))
1729+
# Test if UnionTypes are preserved
1730+
self.assertEqual(isinstance(type_hints[k], type(expected[k])), True)
17291731
# Repr
17301732
with self.subTest("Check str and repr"):
17311733
if skip_reason == "UnionType not preserved in 3.10":
17321734
self.skipTest(skip_reason)
1733-
self.assertEqual(str(type_hints) + repr(type_hints), str(expected) + repr(expected))
1735+
self.assertEqual(repr(type_hints), repr(expected))
17341736

17351737

17361738
class GetUtilitiesTestCase(TestCase):

src/typing_extensions.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ def _clean_optional(obj, hints, globalns=None, localns=None):
12821282
):
12831283
continue
12841284
original_value = original_hints[name]
1285-
if original_value is None: # should not happen
1285+
if original_value is None: # should be NoneType already; check just in case
12861286
original_value = _NoneType
12871287
# Forward reference
12881288
if isinstance(original_value, str):
@@ -1310,8 +1310,14 @@ def _clean_optional(obj, hints, globalns=None, localns=None):
13101310
if sys.version_info < (3, 9) and get_origin(original_evaluated) is Union:
13111311
# Union[str, None, "str"] is not reduced to Union[str, None]
13121312
original_evaluated = Union[original_evaluated.__args__]
1313-
# Compare if values differ
1314-
if original_evaluated != value:
1313+
# Compare if values differ. Note that even if equal
1314+
# value might be cached by typing._tp_cache contrary to original_evaluated
1315+
if original_evaluated != value or (
1316+
# 3.10: ForwardRefs of UnionType might be turned into _UnionGenericAlias
1317+
hasattr(_types, "UnionType")
1318+
and isinstance(original_evaluated, _types.UnionType)
1319+
and not isinstance(value, _types.UnionType)
1320+
):
13151321
hints[name] = original_evaluated
13161322

13171323
# Python 3.9+ has PEP 593 (Annotated)

0 commit comments

Comments
 (0)