| [case testPEP695Basics] | |
| from enum import Enum | |
| from typing import Any, Literal, 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]) | |
| class SomeEnum(Enum): | |
| AVALUE = "a" | |
| type EnumLiteralAlias1 = Literal[SomeEnum.AVALUE] | |
| type EnumLiteralAlias2 = Literal[SomeEnum.AVALUE] | None | |
| EnumLiteralAlias3 = Literal[SomeEnum.AVALUE] | None | |
| [typing fixtures/typing-full.pyi] | |
| [case testPEP695GenericTypeAlias] | |
| import sys | |
| 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 | |
| if sys.version_info >= (3, 15): # type: ignore[operator] | |
| assert str(A[str]) == "_frozen_importlib.A[str]" | |
| else: | |
| 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: | |
| if sys.version_info >= (3, 15): # type: ignore[operator] | |
| assert str(B[str, int]) == "_frozen_importlib.B[str, int]" | |
| else: | |
| 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: | |
| if sys.version_info >= (3, 15): # type: ignore[operator] | |
| assert str(C[int, str]) == "_frozen_importlib.C[int, str]" | |
| assert str(getattr(C, "__value__")) == "tuple[typing.Unpack[~Ts]]" | |
| else: | |
| 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: | |
| if sys.version_info >= (3, 15): # type: ignore[operator] | |
| assert str(D[[int, str]]) == "_frozen_importlib.D[[int, str]]" | |
| else: | |
| assert str(D[[int, str]]) == "D[[int, str]]" | |
| assert str(getattr(D, "__value__")) == "typing.Callable[P, int]" | |
| [typing fixtures/typing-full.pyi] | |
| [case testPEP695NonNativeClass] | |
| from mypy_extensions import mypyc_attr | |
| @mypyc_attr(native_class=False) | |
| class Base: | |
| pass | |
| @mypyc_attr(native_class=False) | |
| class G[T]: | |
| def __init__(self, x: T) -> None: | |
| self.x = x | |
| @mypyc_attr(native_class=False) | |
| class WithBase[T](Base): | |
| pass | |
| @mypyc_attr(native_class=False) | |
| class Sub[S](G[S]): | |
| pass | |
| @mypyc_attr(native_class=False) | |
| class Variadic[T, *Ts, **P]: | |
| pass | |
| [file driver.py] | |
| from typing import Generic | |
| from native import Base, G, WithBase, Sub, Variadic | |
| (T,) = G.__type_params__ | |
| assert G.__bases__ == (Generic,) | |
| assert G.__orig_bases__ == (Generic[T],) | |
| assert G.__parameters__ == (T,) | |
| assert G[int](3).x == 3 | |
| assert WithBase.__bases__ == (Base, Generic) | |
| assert WithBase.__parameters__ == WithBase.__type_params__ | |
| assert WithBase[int]() is not None | |
| (S,) = Sub.__type_params__ | |
| assert Sub.__bases__ == (G, Generic) | |
| assert Sub.__orig_bases__ == (G[S], Generic[S]) | |
| assert Sub.__parameters__ == (S,) | |
| assert Sub[str]("a").x == "a" | |
| assert len(Variadic.__type_params__) == 3 | |
| assert Variadic.__parameters__ == Variadic.__type_params__ | |
| assert Variadic[int, str, [int]] is not None | |
| [typing fixtures/typing-full.pyi] |