Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-43224: Initial implementation of PEP 646 in typing.py #24527

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 186 additions & 1 deletion Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from copy import copy, deepcopy

from typing import Any, NoReturn
from typing import TypeVar, AnyStr
from typing import TypeVar, TypeVarTuple, Unpack, _UnpackedTypeVarTuple, AnyStr
from typing import T, KT, VT # Not in __all__.
from typing import Union, Optional, Literal
from typing import Tuple, List, Dict, MutableMapping
Expand Down Expand Up @@ -236,6 +236,147 @@ def test_no_bivariant(self):
TypeVar('T', covariant=True, contravariant=True)


class TypeVarTupleTests(BaseTestCase):

def test_basic_plain(self):
Ts = TypeVarTuple('Ts')
self.assertEqual(Ts, Ts)
self.assertIsInstance(Ts, TypeVarTuple)

def test_repr(self):
Ts = TypeVarTuple('Ts')
self.assertEqual(repr(Ts), 'Ts')
self.assertEqual(repr(Unpack[Ts]), '*Ts')

def test_no_redefinition(self):
self.assertNotEqual(TypeVar('Ts'), TypeVar('Ts'))

def test_cannot_subclass_vars(self):
with self.assertRaises(TypeError):
class V(TypeVarTuple('Ts')):
pass
with self.assertRaises(TypeError):
class V(Unpack[TypeVarTuple('Ts')]):
pass

def test_cannot_subclass_var_itself(self):
with self.assertRaises(TypeError):
class V(TypeVarTuple):
pass

def test_cannot_instantiate_vars(self):
Ts = TypeVarTuple('Ts')
with self.assertRaises(TypeError):
Ts()

def test_unpack(self):
Ts = TypeVarTuple('Ts')
self.assertEqual(Unpack[Ts], Unpack[Ts])
self.assertIsInstance(Unpack[Ts], _UnpackedTypeVarTuple)
with self.assertRaises(TypeError):
Unpack()
with self.assertRaises(TypeError):
Unpack[Tuple[int, str]]
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
with self.assertRaises(TypeError):
Unpack[List[int]]

def test_tuple(self):
Ts = TypeVarTuple('Ts')
Tuple[Unpack[Ts]]
with self.assertRaises(TypeError):
Tuple[Ts]

def test_list(self):
Ts = TypeVarTuple('Ts')
with self.assertRaises(TypeError):
List[Ts]
with self.assertRaises(TypeError):
List[Unpack[Ts]]

def test_union(self):
Xs = TypeVarTuple('Xs')
Ys = TypeVarTuple('Ys')
self.assertNotEqual(Xs, Ys)
with self.assertRaises(TypeError):
Union[Xs]
Union[Xs, int]
self.assertEqual(
Union[Unpack[Xs]],
Unpack[Xs]
)
self.assertNotEqual(
Union[Unpack[Xs]],
Union[Unpack[Xs], Unpack[Ys]]
)
self.assertEqual(
Union[Unpack[Xs], Unpack[Xs]],
Unpack[Xs]
)
self.assertNotEqual(
Union[Unpack[Xs], int],
Union[Unpack[Xs]]
)
self.assertNotEqual(
Union[Unpack[Xs], int],
Union[int]
)
self.assertEqual(
Union[Unpack[Xs], int].__args__,
(Unpack[Xs], int)
)
self.assertEqual(
Union[Unpack[Xs], int].__parameters__,
(Unpack[Xs],)
)
self.assertIs(
Union[Unpack[Xs], int].__origin__,
Union
)

def test_concatenation(self):
Xs = TypeVarTuple('Xs')
Tuple[int, Unpack[Xs]]
Tuple[Unpack[Xs], int]
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
Tuple[int, Unpack[Xs], str]
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
class C(Generic[Unpack[Xs]]): pass
C[int, Unpack[Xs]]
C[Unpack[Xs], int]
C[int, Unpack[Xs], str]

with self.assertRaises(TypeError):
Tuple[Unpack[Xs], Unpack[Xs]]
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
with self.assertRaises(TypeError):
C[Unpack[Xs], Unpack[Xs]]
Ys = TypeVarTuple('Ys')
with self.assertRaises(TypeError):
Tuple[Unpack[Xs], Unpack[Ys]]
with self.assertRaises(TypeError):
C[Unpack[Xs], Unpack[Ys]]

def test_class(self):
Ts = TypeVarTuple('Ts')

class C(Generic[Unpack[Ts]]): pass
class C(Generic[Unpack[Ts]]): pass
C[int]
C[int, str]

with self.assertRaises(TypeError):
class C(Generic[Ts]): pass
with self.assertRaises(TypeError):
class C(Generic[Unpack[Ts], int]): pass

T1 = TypeVar('T')
T2 = TypeVar('T')
class C(Generic[T1, T2, Unpack[Ts]]): pass
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
C[int, str]
C[int, str, float]
with self.assertRaises(TypeError):
C[int]




class UnionTests(BaseTestCase):

def test_basics(self):
Expand Down Expand Up @@ -1433,12 +1574,20 @@ def test_basics(self):
def test_generic_errors(self):
T = TypeVar('T')
S = TypeVar('S')
Ts1 = TypeVarTuple('Ts1')
Ts2 = TypeVarTuple('Ts2')
with self.assertRaises(TypeError):
Generic[T][T]
with self.assertRaises(TypeError):
Generic[Unpack[Ts1]][Unpack[Ts1]]
with self.assertRaises(TypeError):
Generic[T][S]
with self.assertRaises(TypeError):
Generic[Unpack[Ts1]][Unpack[Ts2]]
with self.assertRaises(TypeError):
class C(Generic[T], Generic[T]): ...
with self.assertRaises(TypeError):
class C(Generic[Ts1], Generic[Ts1]): ...
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
with self.assertRaises(TypeError):
isinstance([], List[int])
with self.assertRaises(TypeError):
Expand All @@ -1447,14 +1596,22 @@ class C(Generic[T], Generic[T]): ...
class NewGeneric(Generic): ...
with self.assertRaises(TypeError):
class MyGeneric(Generic[T], Generic[S]): ...
with self.assertRaises(TypeError):
class MyGeneric(Generic[Ts1], Generic[Ts2]): ...
with self.assertRaises(TypeError):
class MyGeneric(List[T], Generic[S]): ...

def test_init(self):
T = TypeVar('T')
S = TypeVar('S')
Ts1 = TypeVar('Ts1')
Ts2 = TypeVar('Ts2')
with self.assertRaises(TypeError):
Generic[T, T]
with self.assertRaises(TypeError):
Generic[Unpack[Ts1], Unpack[Ts1]]
with self.assertRaises(TypeError):
Generic[Unpack[Ts1], Unpack[Ts2]]
with self.assertRaises(TypeError):
Generic[T, S, T]

Expand Down Expand Up @@ -1508,14 +1665,40 @@ class C(Generic[T]):
self.assertTrue(str(Z).endswith(
'.C[typing.Tuple[str, int]]'))

def test_chain_repr_typevartuple(self):
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
T = TypeVar('T')
Ts = TypeVarTuple('Ts')

class C(Generic[Unpack[Ts]]):
pass

X = C[Tuple[Unpack[Ts], T]]
mrahtz marked this conversation as resolved.
Show resolved Hide resolved
self.assertEqual(X, C[Tuple[Unpack[Ts], T]])
self.assertNotEqual(X, C[Tuple[T, Unpack[Ts]]])

Y = X[T, int]
self.assertEqual(Y, X[T, int])
self.assertNotEqual(Y, X[Unpack[Ts], int])
self.assertNotEqual(Y, X[T, str])

Z = Y[str]
self.assertEqual(Z, Y[str])
self.assertNotEqual(Z, Y[int])
self.assertNotEqual(Z, Y[T])

self.assertTrue(str(Z).endswith(
'.C[typing.Tuple[str, int]]'))

def test_new_repr(self):
T = TypeVar('T')
U = TypeVar('U', covariant=True)
S = TypeVar('S')
Ts = TypeVarTuple('Ts')

self.assertEqual(repr(List), 'typing.List')
self.assertEqual(repr(List[T]), 'typing.List[~T]')
self.assertEqual(repr(List[U]), 'typing.List[+U]')
self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[*Ts]')
self.assertEqual(repr(List[S][T][int]), 'typing.List[int]')
self.assertEqual(repr(List[int]), 'typing.List[int]')

Expand All @@ -1535,6 +1718,8 @@ def test_new_repr_bare(self):
T = TypeVar('T')
self.assertEqual(repr(Generic[T]), 'typing.Generic[~T]')
self.assertEqual(repr(typing.Protocol[T]), 'typing.Protocol[~T]')
Ts = TypeVarTuple('Ts')
self.assertEqual(repr(Generic[Unpack[Ts]]), 'typing.Generic[*Ts]')
class C(typing.Dict[Any, Any]): ...
# this line should just work
repr(C.__mro__)
Expand Down
Loading