| [case testPEP695Basics] |
| from typing import Any, TypeAliasType, cast |
| |
| from testutil import assertRaises |
| |
| def id[T](x: T) -> T: |
| return x |
| |
| def test_call_generic_function() -> None: |
| assert id(2) == 2 |
| assert id('x') == 'x' |
| |
| class C[T]: |
| x: T |
| |
| def __init__(self, x: T) -> None: |
| self.x = x |
| |
| class D[T, S]: |
| x: T |
| y: S |
| |
| def __init__(self, x: T, y: S) -> None: |
| self.x = x |
| self.y = y |
| |
| def set(self, x: object, y: object) -> None: |
| self.x = cast(T, x) |
| self.y = cast(S, y) |
| |
| def test_generic_class() -> None: |
| c = C(5) |
| assert c.x == 5 |
| c2 = C[str]('x') |
| assert c2.x == 'x' |
| d = D[str, int]('a', 5) |
| assert d.x == 'a' |
| assert d.y == 5 |
| d.set('b', 6) |
| assert d.x == 'b' |
| assert d.y == 6 |
| |
| def test_generic_class_via_any() -> None: |
| c_any: Any = C |
| c = c_any(2) |
| assert c.x == 2 |
| c2 = c_any[str]('y') |
| assert c2.x == 'y' |
| assert str(c_any[str]) == 'native.C[str]' |
| |
| d_any: Any = D |
| d = d_any(1, 'x') |
| assert d.x == 1 |
| assert d.y == 'x' |
| d2 = d_any[int, str](2, 'y') |
| assert d2.x == 2 |
| assert d2.y == 'y' |
| |
| with assertRaises(TypeError): |
| c_any[int, str] |
| with assertRaises(TypeError): |
| d_any[int] |
| |
| class E[*Ts]: pass |
| |
| def test_type_var_tuple() -> None: |
| e: E[int, str] = E() |
| e_any: Any = E |
| assert isinstance(e_any(), E) |
| assert isinstance(e_any[int](), E) |
| assert isinstance(e_any[int, str](), E) |
| |
| class F[**P]: pass |
| |
| def test_param_spec() -> None: |
| f: F[[int, str]] = F() |
| f_any: Any = F |
| assert isinstance(f_any(), F) |
| assert isinstance(f_any[[int, str]](), F) |
| |
| class SubC[S](C[S]): |
| def __init__(self, x: S) -> None: |
| super().__init__(x) |
| |
| def test_generic_subclass() -> None: |
| s = SubC(1) |
| assert s.x == 1 |
| s2 = SubC[str]('y') |
| assert s2.x == 'y' |
| sub_any: Any = SubC |
| assert sub_any(1).x == 1 |
| assert sub_any[str]('x').x == 'x' |
| assert isinstance(s, SubC) |
| assert isinstance(s, C) |
| |
| class SubD[ |
| T, # Put everything on separate lines |
| S]( |
| D[T, |
| S]): pass |
| |
| def test_generic_subclass_two_params() -> None: |
| s = SubD(3, 'y') |
| assert s.x == 3 |
| assert s.y == 'y' |
| s2 = SubD[str, int]('z', 4) |
| assert s2.x == 'z' |
| assert s2.y == 4 |
| sub_any: Any = SubD |
| assert sub_any(3, 'y').y == 'y' |
| assert sub_any[int, str](3, 'y').y == 'y' |
| assert isinstance(s, SubD) |
| assert isinstance(s, D) |
| |
| class SubE[*Ts](E[*Ts]): pass |
| |
| def test_type_var_tuple_subclass() -> None: |
| sub_any: Any = SubE |
| assert isinstance(sub_any(), SubE) |
| assert isinstance(sub_any(), E) |
| assert isinstance(sub_any[int](), SubE) |
| assert isinstance(sub_any[int, str](), SubE) |
| |
| |
| class SubF[**P](F[P]): pass |
| |
| def test_param_spec_subclass() -> None: |
| sub_any: Any = SubF |
| assert isinstance(sub_any(), SubF) |
| assert isinstance(sub_any(), F) |
| assert isinstance(sub_any[[int]](), SubF) |
| assert isinstance(sub_any[[int, str]](), SubF) |
| |
| # We test that upper bounds and restricted values can be used, but not that |
| # they are introspectable |
| |
| def bound[T: C](x: T) -> T: |
| return x |
| |
| def test_function_with_upper_bound() -> None: |
| c = C(1) |
| assert bound(c) is c |
| |
| def restriction[T: (int, str)](x: T) -> T: |
| return x |
| |
| def test_function_with_value_restriction() -> None: |
| assert restriction(1) == 1 |
| assert restriction('x') == 'x' |
| |
| class Bound[T: C]: |
| def __init__(self, x: T) -> None: |
| self.x = x |
| |
| def test_class_with_upper_bound() -> None: |
| c = C(1) |
| b = Bound(c) |
| assert b.x is c |
| b2 = Bound[C](c) |
| assert b2.x is c |
| |
| class Restriction[T: (int, str)]: |
| def __init__(self, x: T) -> None: |
| self.x = x |
| |
| def test_class_with_value_restriction() -> None: |
| r = Restriction(1) |
| assert r.x == 1 |
| r2 = Restriction[str]('a') |
| assert r2.x == 'a' |
| |
| type A = int |
| |
| def test_simple_type_alias() -> None: |
| assert isinstance(A, TypeAliasType) |
| assert getattr(A, "__value__") is int |
| assert str(A) == "A" |
| |
| type B = Fwd[int] |
| Fwd = list |
| |
| def test_forward_reference_in_alias() -> None: |
| assert isinstance(B, TypeAliasType) |
| assert getattr(B, "__value__") == list[int] |
| |
| type R = int | list[R] |
| |
| def test_recursive_type_alias() -> None: |
| assert isinstance(R, TypeAliasType) |
| assert getattr(R, "__value__") == (int | list[R]) |
| [typing fixtures/typing-full.pyi] |
| |
| [case testPEP695GenericTypeAlias] |
| from typing import Callable |
| from types import GenericAlias |
| |
| from testutil import assertRaises |
| |
| type A[T] = list[T] |
| |
| def test_generic_alias() -> None: |
| assert type(A[str]) is GenericAlias |
| assert str(A[str]) == "A[str]" |
| assert str(getattr(A, "__value__")) == "list[T]" |
| |
| type B[T, S] = dict[S, T] |
| |
| def test_generic_alias_with_two_args() -> None: |
| assert str(B[str, int]) == "B[str, int]" |
| assert str(getattr(B, "__value__")) == "dict[S, T]" |
| |
| type C[*Ts] = tuple[*Ts] |
| |
| def test_type_var_tuple_type_alias() -> None: |
| assert str(C[int, str]) == "C[int, str]" |
| assert str(getattr(C, "__value__")) == "tuple[typing.Unpack[Ts]]" |
| |
| type D[**P] = Callable[P, int] |
| |
| def test_param_spec_type_alias() -> None: |
| assert str(D[[int, str]]) == "D[[int, str]]" |
| assert str(getattr(D, "__value__")) == "typing.Callable[P, int]" |
| [typing fixtures/typing-full.pyi] |