diff options
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_dataclasses/__init__.py | 2 | ||||
-rw-r--r-- | Lib/test/test_functools.py | 2 | ||||
-rw-r--r-- | Lib/test/test_inspect/test_inspect.py | 4 | ||||
-rw-r--r-- | Lib/test/test_pydoc/test_pydoc.py | 16 | ||||
-rw-r--r-- | Lib/test/test_types.py | 50 | ||||
-rw-r--r-- | Lib/test/test_typing.py | 96 |
6 files changed, 111 insertions, 59 deletions
diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 8209374c36b..869a043211b 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -2314,7 +2314,7 @@ class TestDocString(unittest.TestCase): class C: x: Union[int, type(None)] = None - self.assertDocStrEqual(C.__doc__, "C(x:Optional[int]=None)") + self.assertDocStrEqual(C.__doc__, "C(x:int|None=None)") def test_docstring_list_field(self): @dataclass diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index d7404a81c23..ef85664cb78 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -3083,7 +3083,7 @@ class TestSingleDispatch(unittest.TestCase): "Invalid annotation for 'arg'." ) self.assertEndsWith(str(exc.exception), - 'typing.Union[int, typing.Iterable[str]] not all arguments are classes.' + 'int | typing.Iterable[str] not all arguments are classes.' ) def test_invalid_positional_argument(self): diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 03f2bacb3a4..73cf5ac64ee 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -1750,8 +1750,8 @@ class TestClassesAndFunctions(unittest.TestCase): class TestFormatAnnotation(unittest.TestCase): def test_typing_replacement(self): from test.typinganndata.ann_module9 import ann, ann1 - self.assertEqual(inspect.formatannotation(ann), 'Union[List[str], int]') - self.assertEqual(inspect.formatannotation(ann1), 'Union[List[testModule.typing.A], int]') + self.assertEqual(inspect.formatannotation(ann), 'List[str] | int') + self.assertEqual(inspect.formatannotation(ann1), 'List[testModule.typing.A] | int') def test_forwardref(self): fwdref = ForwardRef('fwdref') diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 0abd36c5e07..2b1a4484c68 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -133,7 +133,7 @@ DATA c_alias = test.test_pydoc.pydoc_mod.C[int] list_alias1 = typing.List[int] list_alias2 = list[int] - type_union1 = typing.Union[int, str] + type_union1 = int | str type_union2 = int | str VERSION @@ -223,7 +223,7 @@ Data c_alias = test.test_pydoc.pydoc_mod.C[int] list_alias1 = typing.List[int] list_alias2 = list[int] - type_union1 = typing.Union[int, str] + type_union1 = int | str type_union2 = int | str Author @@ -1447,17 +1447,17 @@ class TestDescriptions(unittest.TestCase): self.assertIn(list.__doc__.strip().splitlines()[0], doc) def test_union_type(self): - self.assertEqual(pydoc.describe(typing.Union[int, str]), '_UnionGenericAlias') + self.assertEqual(pydoc.describe(typing.Union[int, str]), 'Union') doc = pydoc.render_doc(typing.Union[int, str], renderer=pydoc.plaintext) - self.assertIn('_UnionGenericAlias in module typing', doc) - self.assertIn('Union = typing.Union', doc) + self.assertIn('Union in module typing', doc) + self.assertIn('class Union(builtins.object)', doc) if typing.Union.__doc__: self.assertIn(typing.Union.__doc__.strip().splitlines()[0], doc) - self.assertEqual(pydoc.describe(int | str), 'UnionType') + self.assertEqual(pydoc.describe(int | str), 'Union') doc = pydoc.render_doc(int | str, renderer=pydoc.plaintext) - self.assertIn('UnionType in module types object', doc) - self.assertIn('\nclass UnionType(builtins.object)', doc) + self.assertIn('Union in module typing', doc) + self.assertIn('class Union(builtins.object)', doc) if not MISSING_C_DOCSTRINGS: self.assertIn(types.UnionType.__doc__.strip().splitlines()[0], doc) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index d1161719d98..5a65b5dacaf 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -709,10 +709,6 @@ class UnionTests(unittest.TestCase): y = int | bool with self.assertRaises(TypeError): x < y - # Check that we don't crash if typing.Union does not have a tuple in __args__ - y = typing.Union[str, int] - y.__args__ = [str, int] - self.assertEqual(x, y) def test_hash(self): self.assertEqual(hash(int | str), hash(str | int)) @@ -727,17 +723,40 @@ class UnionTests(unittest.TestCase): self.assertEqual((A | B).__args__, (A, B)) union1 = A | B - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, "unhashable type: 'UnhashableMeta'"): hash(union1) union2 = int | B - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, "unhashable type: 'UnhashableMeta'"): hash(union2) union3 = A | int - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, "unhashable type: 'UnhashableMeta'"): hash(union3) + def test_unhashable_becomes_hashable(self): + is_hashable = False + class UnhashableMeta(type): + def __hash__(self): + if is_hashable: + return 1 + else: + raise TypeError("not hashable") + + class A(metaclass=UnhashableMeta): ... + class B(metaclass=UnhashableMeta): ... + + union = A | B + self.assertEqual(union.__args__, (A, B)) + + with self.assertRaisesRegex(TypeError, "not hashable"): + hash(union) + + is_hashable = True + + with self.assertRaisesRegex(TypeError, "union contains 2 unhashable elements"): + hash(union) + def test_instancecheck_and_subclasscheck(self): for x in (int | str, typing.Union[int, str]): with self.subTest(x=x): @@ -921,7 +940,7 @@ class UnionTests(unittest.TestCase): self.assertEqual(typing.get_args(typing.get_type_hints(forward_after)['x']), (int, Forward)) self.assertEqual(typing.get_args(typing.get_type_hints(forward_before)['x']), - (int, Forward)) + (Forward, int)) def test_or_type_operator_with_Protocol(self): class Proto(typing.Protocol): @@ -1015,9 +1034,14 @@ class UnionTests(unittest.TestCase): return 1 / 0 bt = BadType('bt', (), {}) + bt2 = BadType('bt2', (), {}) # Comparison should fail and errors should propagate out for bad types. + union1 = int | bt + union2 = int | bt2 + with self.assertRaises(ZeroDivisionError): + union1 == union2 with self.assertRaises(ZeroDivisionError): - list[int] | list[bt] + bt | bt2 union_ga = (list[str] | int, collections.abc.Callable[..., str] | int, d | int) @@ -1060,6 +1084,14 @@ class UnionTests(unittest.TestCase): self.assertLessEqual(sys.gettotalrefcount() - before, leeway, msg='Check for union reference leak.') + def test_instantiation(self): + with self.assertRaises(TypeError): + types.UnionType() + self.assertIs(int, types.UnionType[int]) + self.assertIs(int, types.UnionType[int, int]) + self.assertEqual(int | str, types.UnionType[int, str]) + self.assertEqual(int | typing.ForwardRef("str"), types.UnionType[int, "str"]) + class MappingProxyTests(unittest.TestCase): mappingproxy = types.MappingProxyType diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 591fb860eee..e88c811bfca 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -502,7 +502,7 @@ class TypeVarTests(BaseTestCase): def test_bound_errors(self): with self.assertRaises(TypeError): - TypeVar('X', bound=Union) + TypeVar('X', bound=Optional) with self.assertRaises(TypeError): TypeVar('X', str, float, bound=Employee) with self.assertRaisesRegex(TypeError, @@ -542,7 +542,7 @@ class TypeVarTests(BaseTestCase): def test_bad_var_substitution(self): T = TypeVar('T') bad_args = ( - (), (int, str), Union, + (), (int, str), Optional, Generic, Generic[T], Protocol, Protocol[T], Final, Final[int], ClassVar, ClassVar[int], ) @@ -2044,10 +2044,6 @@ class UnionTests(BaseTestCase): def test_union_issubclass_type_error(self): with self.assertRaises(TypeError): - issubclass(int, Union) - with self.assertRaises(TypeError): - issubclass(Union, int) - with self.assertRaises(TypeError): issubclass(Union[int, str], int) with self.assertRaises(TypeError): issubclass(int, Union[str, list[int]]) @@ -2121,41 +2117,40 @@ class UnionTests(BaseTestCase): self.assertEqual(Union[A, B].__args__, (A, B)) union1 = Union[A, B] - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, "unhashable type: 'UnhashableMeta'"): hash(union1) union2 = Union[int, B] - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, "unhashable type: 'UnhashableMeta'"): hash(union2) union3 = Union[A, int] - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, "unhashable type: 'UnhashableMeta'"): hash(union3) def test_repr(self): - self.assertEqual(repr(Union), 'typing.Union') u = Union[Employee, int] - self.assertEqual(repr(u), 'typing.Union[%s.Employee, int]' % __name__) + self.assertEqual(repr(u), f'{__name__}.Employee | int') u = Union[int, Employee] - self.assertEqual(repr(u), 'typing.Union[int, %s.Employee]' % __name__) + self.assertEqual(repr(u), f'int | {__name__}.Employee') T = TypeVar('T') u = Union[T, int][int] self.assertEqual(repr(u), repr(int)) u = Union[List[int], int] - self.assertEqual(repr(u), 'typing.Union[typing.List[int], int]') + self.assertEqual(repr(u), 'typing.List[int] | int') u = Union[list[int], dict[str, float]] - self.assertEqual(repr(u), 'typing.Union[list[int], dict[str, float]]') + self.assertEqual(repr(u), 'list[int] | dict[str, float]') u = Union[int | float] - self.assertEqual(repr(u), 'typing.Union[int, float]') + self.assertEqual(repr(u), 'int | float') u = Union[None, str] - self.assertEqual(repr(u), 'typing.Optional[str]') + self.assertEqual(repr(u), 'None | str') u = Union[str, None] - self.assertEqual(repr(u), 'typing.Optional[str]') + self.assertEqual(repr(u), 'str | None') u = Union[None, str, int] - self.assertEqual(repr(u), 'typing.Union[NoneType, str, int]') + self.assertEqual(repr(u), 'None | str | int') u = Optional[str] - self.assertEqual(repr(u), 'typing.Optional[str]') + self.assertEqual(repr(u), 'str | None') def test_dir(self): dir_items = set(dir(Union[str, int])) @@ -2167,14 +2162,11 @@ class UnionTests(BaseTestCase): def test_cannot_subclass(self): with self.assertRaisesRegex(TypeError, - r'Cannot subclass typing\.Union'): + r"type 'typing\.Union' is not an acceptable base type"): class C(Union): pass - with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class D(type(Union)): - pass with self.assertRaisesRegex(TypeError, - r'Cannot subclass typing\.Union\[int, str\]'): + r'Cannot subclass int \| str'): class E(Union[int, str]): pass @@ -2220,7 +2212,7 @@ class UnionTests(BaseTestCase): def test_function_repr_union(self): def fun() -> int: ... - self.assertEqual(repr(Union[fun, int]), 'typing.Union[fun, int]') + self.assertEqual(repr(Union[fun, int]), f'{__name__}.{fun.__qualname__} | int') def test_union_str_pattern(self): # Shouldn't crash; see http://bugs.python.org/issue25390 @@ -4895,11 +4887,11 @@ class GenericTests(BaseTestCase): def test_extended_generic_rules_repr(self): T = TypeVar('T') self.assertEqual(repr(Union[Tuple, Callable]).replace('typing.', ''), - 'Union[Tuple, Callable]') + 'Tuple | Callable') self.assertEqual(repr(Union[Tuple, Tuple[int]]).replace('typing.', ''), - 'Union[Tuple, Tuple[int]]') + 'Tuple | Tuple[int]') self.assertEqual(repr(Callable[..., Optional[T]][int]).replace('typing.', ''), - 'Callable[..., Optional[int]]') + 'Callable[..., int | None]') self.assertEqual(repr(Callable[[], List[T]][int]).replace('typing.', ''), 'Callable[[], List[int]]') @@ -5079,9 +5071,9 @@ class GenericTests(BaseTestCase): with self.assertRaises(TypeError): issubclass(Tuple[int, ...], typing.Iterable) - def test_fail_with_bare_union(self): + def test_fail_with_special_forms(self): with self.assertRaises(TypeError): - List[Union] + List[Final] with self.assertRaises(TypeError): Tuple[Optional] with self.assertRaises(TypeError): @@ -5623,8 +5615,6 @@ class GenericTests(BaseTestCase): for obj in ( ClassVar[int], Final[int], - Union[int, float], - Optional[int], Literal[1, 2], Concatenate[int, ParamSpec("P")], TypeGuard[int], @@ -5656,7 +5646,7 @@ class GenericTests(BaseTestCase): __parameters__ = (T,) # Bare classes should be skipped for a in (List, list): - for b in (A, int, TypeVar, TypeVarTuple, ParamSpec, types.GenericAlias, types.UnionType): + for b in (A, int, TypeVar, TypeVarTuple, ParamSpec, types.GenericAlias, Union): with self.subTest(generic=a, sub=b): with self.assertRaisesRegex(TypeError, '.* is not a generic class'): a[b][str] @@ -5675,7 +5665,7 @@ class GenericTests(BaseTestCase): for s in (int, G, A, List, list, TypeVar, TypeVarTuple, ParamSpec, - types.GenericAlias, types.UnionType): + types.GenericAlias, Union): for t in Tuple, tuple: with self.subTest(tuple=t, sub=s): @@ -7176,7 +7166,7 @@ class GetUtilitiesTestCase(TestCase): self.assertIs(get_origin(Callable), collections.abc.Callable) self.assertIs(get_origin(list[int]), list) self.assertIs(get_origin(list), None) - self.assertIs(get_origin(list | str), types.UnionType) + self.assertIs(get_origin(list | str), Union) self.assertIs(get_origin(P.args), P) self.assertIs(get_origin(P.kwargs), P) self.assertIs(get_origin(Required[int]), Required) @@ -10434,7 +10424,6 @@ class SpecialAttrsTests(BaseTestCase): typing.TypeGuard: 'TypeGuard', typing.TypeIs: 'TypeIs', typing.TypeVar: 'TypeVar', - typing.Union: 'Union', typing.Self: 'Self', # Subscripted special forms typing.Annotated[Any, "Annotation"]: 'Annotated', @@ -10445,7 +10434,7 @@ class SpecialAttrsTests(BaseTestCase): typing.Literal[Any]: 'Literal', typing.Literal[1, 2]: 'Literal', typing.Literal[True, 2]: 'Literal', - typing.Optional[Any]: 'Optional', + typing.Optional[Any]: 'Union', typing.TypeGuard[Any]: 'TypeGuard', typing.TypeIs[Any]: 'TypeIs', typing.Union[Any]: 'Any', @@ -10464,7 +10453,10 @@ class SpecialAttrsTests(BaseTestCase): for proto in range(pickle.HIGHEST_PROTOCOL + 1): s = pickle.dumps(cls, proto) loaded = pickle.loads(s) - self.assertIs(cls, loaded) + if isinstance(cls, Union): + self.assertEqual(cls, loaded) + else: + self.assertIs(cls, loaded) TypeName = typing.NewType('SpecialAttrsTests.TypeName', Any) @@ -10739,6 +10731,34 @@ class TypeIterationTests(BaseTestCase): self.assertNotIsInstance(type_to_test, collections.abc.Iterable) +class UnionGenericAliasTests(BaseTestCase): + def test_constructor(self): + # Used e.g. in typer, pydantic + with self.assertWarns(DeprecationWarning): + inst = typing._UnionGenericAlias(typing.Union, (int, str)) + self.assertEqual(inst, int | str) + with self.assertWarns(DeprecationWarning): + # name is accepted but ignored + inst = typing._UnionGenericAlias(typing.Union, (int, None), name="Optional") + self.assertEqual(inst, int | None) + + def test_isinstance(self): + # Used e.g. in pydantic + with self.assertWarns(DeprecationWarning): + self.assertTrue(isinstance(Union[int, str], typing._UnionGenericAlias)) + with self.assertWarns(DeprecationWarning): + self.assertFalse(isinstance(int, typing._UnionGenericAlias)) + + def test_eq(self): + # type(t) == _UnionGenericAlias is used in vyos + with self.assertWarns(DeprecationWarning): + self.assertEqual(Union, typing._UnionGenericAlias) + with self.assertWarns(DeprecationWarning): + self.assertEqual(typing._UnionGenericAlias, typing._UnionGenericAlias) + with self.assertWarns(DeprecationWarning): + self.assertNotEqual(int, typing._UnionGenericAlias) + + def load_tests(loader, tests, pattern): import doctest tests.addTests(doctest.DocTestSuite(typing)) |