diff --git a/mode/utils/objects.py b/mode/utils/objects.py index 70c73c3..8524841 100644 --- a/mode/utils/objects.py +++ b/mode/utils/objects.py @@ -472,6 +472,7 @@ def is_union(typ: Type) -> bool: name = typ.__class__.__name__ return any( [ + name == "UnionType", # 3.10 name == "_UnionGenericAlias", # 3.9 name == "_GenericAlias" and typ.__origin__ is typing.Union, # 3.7 name == "_Union", # 3.6 diff --git a/tests/unit/utils/test_objects.py b/tests/unit/utils/test_objects.py index 0e384af..119cfa7 100644 --- a/tests/unit/utils/test_objects.py +++ b/tests/unit/utils/test_objects.py @@ -1,6 +1,7 @@ import abc import collections.abc import pickle +import sys import typing from typing import ( AbstractSet, @@ -377,14 +378,17 @@ def test_label_pass(): assert label(s) is s -@pytest.mark.parametrize( - "input,expected", - [ - (str, False), - (int, False), - (Union[int, bytes], True), - (Optional[str], True), - ], -) +IS_UNION_CASES = [ + (str, False), + (int, False), + (Union[int, bytes], True), + (Optional[str], True), +] +if sys.version_info >= (3, 10): + # X | Y syntax is only usable at runtime on Python 3.10+ + IS_UNION_CASES.append((int | None, True)) + + +@pytest.mark.parametrize("input,expected", IS_UNION_CASES) def test_is_union(input, expected): assert is_union(input) == expected