[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]
