mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Compile starred annotations (#5881)
* Fix starred annotation * uncomment starred annotation
This commit is contained in:
1 parent
4ebd485694
commit
3d951a883a
16 files changed
+153
-163
No files matched your search
Vendored
+94
-115
@@ -1224,15 +1224,15 @@ class UnpackTests(BaseTestCase):
|
||||
|
||||
PartOld = Old[int, *Ts]
|
||||
self.assertEqual(PartOld[str].__args__, (int, str))
|
||||
# self.assertEqual(PartOld[*tuple[str]].__args__, (int, str))
|
||||
# self.assertEqual(PartOld[*Tuple[str]].__args__, (int, str))
|
||||
self.assertEqual(PartOld[*tuple[str]].__args__, (int, str))
|
||||
self.assertEqual(PartOld[*Tuple[str]].__args__, (int, str))
|
||||
self.assertEqual(PartOld[Unpack[tuple[str]]].__args__, (int, str))
|
||||
self.assertEqual(PartOld[Unpack[Tuple[str]]].__args__, (int, str))
|
||||
|
||||
PartNew = New[int, *Ts]
|
||||
self.assertEqual(PartNew[str].__args__, (int, str))
|
||||
# self.assertEqual(PartNew[*tuple[str]].__args__, (int, str))
|
||||
# self.assertEqual(PartNew[*Tuple[str]].__args__, (int, str))
|
||||
self.assertEqual(PartNew[*tuple[str]].__args__, (int, str))
|
||||
self.assertEqual(PartNew[*Tuple[str]].__args__, (int, str))
|
||||
self.assertEqual(PartNew[Unpack[tuple[str]]].__args__, (int, str))
|
||||
self.assertEqual(PartNew[Unpack[Tuple[str]]].__args__, (int, str))
|
||||
|
||||
@@ -1241,7 +1241,7 @@ class UnpackTests(BaseTestCase):
|
||||
def test_unpack_wrong_type(self):
|
||||
Ts = TypeVarTuple("Ts")
|
||||
class Gen[*Ts]: ...
|
||||
# PartGen = Gen[int, *Ts]
|
||||
PartGen = Gen[int, *Ts]
|
||||
|
||||
bad_unpack_param = re.escape("Unpack[...] must be used with a tuple type")
|
||||
with self.assertRaisesRegex(TypeError, bad_unpack_param):
|
||||
@@ -1291,7 +1291,7 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
|
||||
def test_parameterised_tuple_is_equal_to_itself(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
# self.assertEqual(tuple[*Ts], tuple[*Ts])
|
||||
self.assertEqual(tuple[*Ts], tuple[*Ts])
|
||||
self.assertEqual(Tuple[Unpack[Ts]], Tuple[Unpack[Ts]])
|
||||
|
||||
def tests_tuple_arg_ordering_matters(self):
|
||||
@@ -1306,28 +1306,24 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
Tuple[Unpack[Ts2], Unpack[Ts1]],
|
||||
)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_tuple_args_and_parameters_are_correct(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
# t1 = tuple[*Ts]
|
||||
t1 = tuple[*Ts]
|
||||
self.assertEqual(t1.__args__, (*Ts,))
|
||||
self.assertEqual(t1.__parameters__, (Ts,))
|
||||
t2 = Tuple[Unpack[Ts]]
|
||||
self.assertEqual(t2.__args__, (Unpack[Ts],))
|
||||
self.assertEqual(t2.__parameters__, (Ts,))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_var_substitution(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
T = TypeVar('T')
|
||||
T2 = TypeVar('T2')
|
||||
# class G1(Generic[*Ts]): pass
|
||||
class G1(Generic[*Ts]): pass
|
||||
class G2(Generic[Unpack[Ts]]): pass
|
||||
|
||||
for A in G1, G2, Tuple, tuple:
|
||||
# B = A[*Ts]
|
||||
B = A[*Ts]
|
||||
self.assertEqual(B[()], A[()])
|
||||
self.assertEqual(B[float], A[float])
|
||||
self.assertEqual(B[float, str], A[float, str])
|
||||
@@ -1337,7 +1333,7 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEqual(C[float], A[float])
|
||||
self.assertEqual(C[float, str], A[float, str])
|
||||
|
||||
# D = list[A[*Ts]]
|
||||
D = list[A[*Ts]]
|
||||
self.assertEqual(D[()], list[A[()]])
|
||||
self.assertEqual(D[float], list[A[float]])
|
||||
self.assertEqual(D[float, str], list[A[float, str]])
|
||||
@@ -1365,7 +1361,7 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEqual(G[float, str, int], A[float, str, int])
|
||||
self.assertEqual(G[float, str, int, bytes], A[float, str, int, bytes])
|
||||
|
||||
# H = tuple[list[T], A[*Ts], list[T2]]
|
||||
H = tuple[list[T], A[*Ts], list[T2]]
|
||||
with self.assertRaises(TypeError):
|
||||
H[()]
|
||||
with self.assertRaises(TypeError):
|
||||
@@ -1391,13 +1387,11 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEqual(I[float, str, int, bytes],
|
||||
Tuple[List[float], A[str, int], List[bytes]])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_bad_var_substitution(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
T = TypeVar('T')
|
||||
T2 = TypeVar('T2')
|
||||
# class G1(Generic[*Ts]): pass
|
||||
class G1(Generic[*Ts]): pass
|
||||
class G2(Generic[Unpack[Ts]]): pass
|
||||
|
||||
for A in G1, G2, Tuple, tuple:
|
||||
@@ -1407,8 +1401,7 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
|
||||
C = A[T, T2]
|
||||
with self.assertRaises(TypeError):
|
||||
# C[*Ts]
|
||||
pass
|
||||
C[*Ts]
|
||||
with self.assertRaises(TypeError):
|
||||
C[Unpack[Ts]]
|
||||
|
||||
@@ -1427,7 +1420,7 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
def test_repr_is_correct(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
|
||||
# class G1(Generic[*Ts]): pass
|
||||
class G1(Generic[*Ts]): pass
|
||||
class G2(Generic[Unpack[Ts]]): pass
|
||||
|
||||
self.assertEqual(repr(Ts), 'Ts')
|
||||
@@ -1435,17 +1428,15 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEqual(repr((*Ts,)[0]), 'typing.Unpack[Ts]')
|
||||
self.assertEqual(repr(Unpack[Ts]), 'typing.Unpack[Ts]')
|
||||
|
||||
# self.assertEqual(repr(tuple[*Ts]), 'tuple[typing.Unpack[Ts]]')
|
||||
self.assertEqual(repr(tuple[*Ts]), 'tuple[typing.Unpack[Ts]]')
|
||||
self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[typing.Unpack[Ts]]')
|
||||
|
||||
# self.assertEqual(repr(*tuple[*Ts]), '*tuple[typing.Unpack[Ts]]')
|
||||
self.assertEqual(repr(*tuple[*Ts]), '*tuple[typing.Unpack[Ts]]')
|
||||
self.assertEqual(repr(Unpack[Tuple[Unpack[Ts]]]), 'typing.Unpack[typing.Tuple[typing.Unpack[Ts]]]')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_variadic_class_repr_is_correct(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
# class A(Generic[*Ts]): pass
|
||||
class A(Generic[*Ts]): pass
|
||||
class B(Generic[Unpack[Ts]]): pass
|
||||
|
||||
self.assertEndsWith(repr(A[()]), 'A[()]')
|
||||
@@ -1455,8 +1446,8 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEndsWith(repr(A[float, str]), 'A[float, str]')
|
||||
self.assertEndsWith(repr(B[float, str]), 'B[float, str]')
|
||||
|
||||
# self.assertEndsWith(repr(A[*tuple[int, ...]]),
|
||||
# 'A[*tuple[int, ...]]')
|
||||
self.assertEndsWith(repr(A[*tuple[int, ...]]),
|
||||
'A[*tuple[int, ...]]')
|
||||
self.assertEndsWith(repr(B[Unpack[Tuple[int, ...]]]),
|
||||
'B[typing.Unpack[typing.Tuple[int, ...]]]')
|
||||
|
||||
@@ -1475,17 +1466,15 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEndsWith(repr(B[float, Unpack[Tuple[int, ...]], str]),
|
||||
'B[float, typing.Unpack[typing.Tuple[int, ...]], str]')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_variadic_class_alias_repr_is_correct(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
class A(Generic[Unpack[Ts]]): pass
|
||||
|
||||
# B = A[*Ts]
|
||||
# self.assertEndsWith(repr(B), 'A[typing.Unpack[Ts]]')
|
||||
# self.assertEndsWith(repr(B[()]), 'A[()]')
|
||||
# self.assertEndsWith(repr(B[float]), 'A[float]')
|
||||
# self.assertEndsWith(repr(B[float, str]), 'A[float, str]')
|
||||
B = A[*Ts]
|
||||
self.assertEndsWith(repr(B), 'A[typing.Unpack[Ts]]')
|
||||
self.assertEndsWith(repr(B[()]), 'A[()]')
|
||||
self.assertEndsWith(repr(B[float]), 'A[float]')
|
||||
self.assertEndsWith(repr(B[float, str]), 'A[float, str]')
|
||||
|
||||
C = A[Unpack[Ts]]
|
||||
self.assertEndsWith(repr(C), 'A[typing.Unpack[Ts]]')
|
||||
@@ -1562,12 +1551,10 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'):
|
||||
class J(Unpack[Ts]): pass
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_variadic_class_args_are_correct(self):
|
||||
T = TypeVar('T')
|
||||
Ts = TypeVarTuple('Ts')
|
||||
# class A(Generic[*Ts]): pass
|
||||
class A(Generic[*Ts]): pass
|
||||
class B(Generic[Unpack[Ts]]): pass
|
||||
|
||||
C = A[()]
|
||||
@@ -1590,10 +1577,10 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertEqual(I.__args__, (T,))
|
||||
self.assertEqual(J.__args__, (T,))
|
||||
|
||||
# K = A[*Ts]
|
||||
# L = B[Unpack[Ts]]
|
||||
# self.assertEqual(K.__args__, (*Ts,))
|
||||
# self.assertEqual(L.__args__, (Unpack[Ts],))
|
||||
K = A[*Ts]
|
||||
L = B[Unpack[Ts]]
|
||||
self.assertEqual(K.__args__, (*Ts,))
|
||||
self.assertEqual(L.__args__, (Unpack[Ts],))
|
||||
|
||||
M = A[T, *Ts]
|
||||
N = B[T, Unpack[Ts]]
|
||||
@@ -1618,19 +1605,21 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
self.assertIs(D[T].__origin__, D)
|
||||
self.assertIs(D[Unpack[Ts]].__origin__, D)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_get_type_hints_on_unpack_args(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
|
||||
# def func1(*args: *Ts): pass
|
||||
# self.assertEqual(gth(func1), {'args': Unpack[Ts]})
|
||||
def func1(*args: *Ts): pass
|
||||
self.assertEqual(gth(func1), {'args': Unpack[Ts]})
|
||||
|
||||
# def func2(*args: *tuple[int, str]): pass
|
||||
# self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]})
|
||||
def func2(*args: *tuple[int, str]): pass
|
||||
self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]})
|
||||
|
||||
# class CustomVariadic(Generic[*Ts]): pass
|
||||
class CustomVariadic(Generic[*Ts]): pass
|
||||
|
||||
# def func3(*args: *CustomVariadic[int, str]): pass
|
||||
# self.assertEqual(gth(func3), {'args': Unpack[CustomVariadic[int, str]]})
|
||||
def func3(*args: *CustomVariadic[int, str]): pass
|
||||
self.assertEqual(gth(func3), {'args': Unpack[CustomVariadic[int, str]]})
|
||||
|
||||
def test_get_type_hints_on_unpack_args_string(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
@@ -1642,17 +1631,17 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
def func2(*args: '*tuple[int, str]'): pass
|
||||
self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]})
|
||||
|
||||
# class CustomVariadic(Generic[*Ts]): pass
|
||||
class CustomVariadic(Generic[*Ts]): pass
|
||||
|
||||
# def func3(*args: '*CustomVariadic[int, str]'): pass
|
||||
# self.assertEqual(gth(func3, localns={'CustomVariadic': CustomVariadic}),
|
||||
# {'args': Unpack[CustomVariadic[int, str]]})
|
||||
def func3(*args: '*CustomVariadic[int, str]'): pass
|
||||
self.assertEqual(gth(func3, localns={'CustomVariadic': CustomVariadic}),
|
||||
{'args': Unpack[CustomVariadic[int, str]]})
|
||||
|
||||
|
||||
def test_tuple_args_are_correct(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
|
||||
# self.assertEqual(tuple[*Ts].__args__, (*Ts,))
|
||||
self.assertEqual(tuple[*Ts].__args__, (*Ts,))
|
||||
self.assertEqual(Tuple[Unpack[Ts]].__args__, (Unpack[Ts],))
|
||||
|
||||
self.assertEqual(tuple[*Ts, int].__args__, (*Ts, int))
|
||||
@@ -1820,20 +1809,21 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
F[int, str, float]
|
||||
F[int, str, float, bool]
|
||||
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_variadic_args_annotations_are_correct(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
|
||||
def f(*args: Unpack[Ts]): pass
|
||||
# def g(*args: *Ts): pass
|
||||
def g(*args: *Ts): pass
|
||||
self.assertEqual(f.__annotations__, {'args': Unpack[Ts]})
|
||||
# self.assertEqual(g.__annotations__, {'args': (*Ts,)[0]})
|
||||
self.assertEqual(g.__annotations__, {'args': (*Ts,)[0]})
|
||||
|
||||
|
||||
def test_variadic_args_with_ellipsis_annotations_are_correct(self):
|
||||
# def a(*args: *tuple[int, ...]): pass
|
||||
# self.assertEqual(a.__annotations__,
|
||||
# {'args': (*tuple[int, ...],)[0]})
|
||||
def a(*args: *tuple[int, ...]): pass
|
||||
self.assertEqual(a.__annotations__,
|
||||
{'args': (*tuple[int, ...],)[0]})
|
||||
|
||||
def b(*args: Unpack[Tuple[int, ...]]): pass
|
||||
self.assertEqual(b.__annotations__,
|
||||
@@ -1845,29 +1835,29 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
|
||||
# Unpacking using `*`, native `tuple` type
|
||||
|
||||
# def a(*args: *tuple[int, *Ts]): pass
|
||||
# self.assertEqual(
|
||||
# a.__annotations__,
|
||||
# {'args': (*tuple[int, *Ts],)[0]},
|
||||
# )
|
||||
def a(*args: *tuple[int, *Ts]): pass
|
||||
self.assertEqual(
|
||||
a.__annotations__,
|
||||
{'args': (*tuple[int, *Ts],)[0]},
|
||||
)
|
||||
|
||||
# def b(*args: *tuple[*Ts, int]): pass
|
||||
# self.assertEqual(
|
||||
# b.__annotations__,
|
||||
# {'args': (*tuple[*Ts, int],)[0]},
|
||||
# )
|
||||
def b(*args: *tuple[*Ts, int]): pass
|
||||
self.assertEqual(
|
||||
b.__annotations__,
|
||||
{'args': (*tuple[*Ts, int],)[0]},
|
||||
)
|
||||
|
||||
# def c(*args: *tuple[str, *Ts, int]): pass
|
||||
# self.assertEqual(
|
||||
# c.__annotations__,
|
||||
# {'args': (*tuple[str, *Ts, int],)[0]},
|
||||
# )
|
||||
def c(*args: *tuple[str, *Ts, int]): pass
|
||||
self.assertEqual(
|
||||
c.__annotations__,
|
||||
{'args': (*tuple[str, *Ts, int],)[0]},
|
||||
)
|
||||
|
||||
# def d(*args: *tuple[int, bool, *Ts, float, str]): pass
|
||||
# self.assertEqual(
|
||||
# d.__annotations__,
|
||||
# {'args': (*tuple[int, bool, *Ts, float, str],)[0]},
|
||||
# )
|
||||
def d(*args: *tuple[int, bool, *Ts, float, str]): pass
|
||||
self.assertEqual(
|
||||
d.__annotations__,
|
||||
{'args': (*tuple[int, bool, *Ts, float, str],)[0]},
|
||||
)
|
||||
|
||||
# Unpacking using `Unpack`, `Tuple` type from typing.py
|
||||
|
||||
@@ -1895,11 +1885,9 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
{'args': Unpack[Tuple[int, bool, Unpack[Ts], float, str]]},
|
||||
)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_variadic_class_same_args_results_in_equalty(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
# class C(Generic[*Ts]): pass
|
||||
class C(Generic[*Ts]): pass
|
||||
class D(Generic[Unpack[Ts]]): pass
|
||||
|
||||
self.assertEqual(C[int], C[int])
|
||||
@@ -1909,8 +1897,8 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
Ts2 = TypeVarTuple('Ts2')
|
||||
|
||||
self.assertEqual(
|
||||
# C[*Ts1],
|
||||
# C[*Ts1],
|
||||
C[*Ts1],
|
||||
C[*Ts1],
|
||||
)
|
||||
self.assertEqual(
|
||||
D[Unpack[Ts1]],
|
||||
@@ -1935,11 +1923,9 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
D[int, Unpack[Ts1], Unpack[Ts2]],
|
||||
)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_variadic_class_arg_ordering_matters(self):
|
||||
Ts = TypeVarTuple('Ts')
|
||||
# class C(Generic[*Ts]): pass
|
||||
class C(Generic[*Ts]): pass
|
||||
class D(Generic[Unpack[Ts]]): pass
|
||||
|
||||
self.assertNotEqual(
|
||||
@@ -1968,10 +1954,10 @@ class TypeVarTupleTests(BaseTestCase):
|
||||
Ts1 = TypeVarTuple('Ts1')
|
||||
Ts2 = TypeVarTuple('Ts2')
|
||||
|
||||
# class C(Generic[*Ts]): pass
|
||||
class C(Generic[*Ts]): pass
|
||||
class D(Generic[Unpack[Ts]]): pass
|
||||
|
||||
# self.assertNotEqual(C[*Ts1], C[*Ts2])
|
||||
self.assertNotEqual(C[*Ts1], C[*Ts2])
|
||||
self.assertNotEqual(D[Unpack[Ts1]], D[Unpack[Ts2]])
|
||||
|
||||
class TypeVarTuplePicklingTests(BaseTestCase):
|
||||
@@ -2010,8 +1996,7 @@ class TypeVarTuplePicklingTests(BaseTestCase):
|
||||
global_Ts = TypeVarTuple('global_Ts')
|
||||
|
||||
tuples = [
|
||||
# TODO: RUSTPYTHON
|
||||
# tuple[*global_Ts],
|
||||
tuple[*global_Ts],
|
||||
Tuple[Unpack[global_Ts]],
|
||||
|
||||
tuple[T, *global_Ts],
|
||||
@@ -6153,7 +6138,7 @@ class GetUtilitiesTestCase(TestCase):
|
||||
self.assertIs(get_origin(NotRequired[int]), NotRequired)
|
||||
self.assertIs(get_origin((*Ts,)[0]), Unpack)
|
||||
self.assertIs(get_origin(Unpack[Ts]), Unpack)
|
||||
# self.assertIs(get_origin((*tuple[*Ts],)[0]), tuple)
|
||||
self.assertIs(get_origin((*tuple[*Ts],)[0]), tuple)
|
||||
self.assertIs(get_origin(Unpack[Tuple[Unpack[Ts]]]), Unpack)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@@ -6221,9 +6206,9 @@ class GetUtilitiesTestCase(TestCase):
|
||||
self.assertEqual(get_args(Ts), ())
|
||||
self.assertEqual(get_args((*Ts,)[0]), (Ts,))
|
||||
self.assertEqual(get_args(Unpack[Ts]), (Ts,))
|
||||
# self.assertEqual(get_args(tuple[*Ts]), (*Ts,))
|
||||
self.assertEqual(get_args(tuple[*Ts]), (*Ts,))
|
||||
self.assertEqual(get_args(tuple[Unpack[Ts]]), (Unpack[Ts],))
|
||||
# self.assertEqual(get_args((*tuple[*Ts],)[0]), (*Ts,))
|
||||
self.assertEqual(get_args((*tuple[*Ts],)[0]), (*Ts,))
|
||||
self.assertEqual(get_args(Unpack[tuple[Unpack[Ts]]]), (tuple[Unpack[Ts]],))
|
||||
|
||||
|
||||
@@ -8405,8 +8390,6 @@ class AnnotatedTests(BaseTestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
LI[None]
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_typevar_subst(self):
|
||||
dec = "a decoration"
|
||||
Ts = TypeVarTuple('Ts')
|
||||
@@ -8414,7 +8397,7 @@ class AnnotatedTests(BaseTestCase):
|
||||
T1 = TypeVar('T1')
|
||||
T2 = TypeVar('T2')
|
||||
|
||||
# A = Annotated[tuple[*Ts], dec]
|
||||
A = Annotated[tuple[*Ts], dec]
|
||||
self.assertEqual(A[int], Annotated[tuple[int], dec])
|
||||
self.assertEqual(A[str, int], Annotated[tuple[str, int], dec])
|
||||
with self.assertRaises(TypeError):
|
||||
@@ -8751,15 +8734,13 @@ class ParamSpecTests(BaseTestCase):
|
||||
self.assertEqual(G1.__args__, ((int, str), (bytes,)))
|
||||
self.assertEqual(G2.__args__, ((int,), (str, bytes)))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_typevartuple_and_paramspecs_in_user_generics(self):
|
||||
Ts = TypeVarTuple("Ts")
|
||||
P = ParamSpec("P")
|
||||
|
||||
# class X(Generic[*Ts, P]):
|
||||
# f: Callable[P, int]
|
||||
# g: Tuple[*Ts]
|
||||
class X(Generic[*Ts, P]):
|
||||
f: Callable[P, int]
|
||||
g: Tuple[*Ts]
|
||||
|
||||
G1 = X[int, [bytes]]
|
||||
self.assertEqual(G1.__args__, (int, (bytes,)))
|
||||
@@ -8772,9 +8753,9 @@ class ParamSpecTests(BaseTestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
X[()]
|
||||
|
||||
# class Y(Generic[P, *Ts]):
|
||||
# f: Callable[P, int]
|
||||
# g: Tuple[*Ts]
|
||||
class Y(Generic[P, *Ts]):
|
||||
f: Callable[P, int]
|
||||
g: Tuple[*Ts]
|
||||
|
||||
G1 = Y[[bytes], int]
|
||||
self.assertEqual(G1.__args__, ((bytes,), int))
|
||||
@@ -8787,8 +8768,6 @@ class ParamSpecTests(BaseTestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
Y[()]
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_typevartuple_and_paramspecs_in_generic_aliases(self):
|
||||
P = ParamSpec('P')
|
||||
T = TypeVar('T')
|
||||
@@ -8796,21 +8775,21 @@ class ParamSpecTests(BaseTestCase):
|
||||
|
||||
for C in Callable, collections.abc.Callable:
|
||||
with self.subTest(generic=C):
|
||||
# A = C[P, Tuple[*Ts]]
|
||||
A = C[P, Tuple[*Ts]]
|
||||
B = A[[int, str], bytes, float]
|
||||
self.assertEqual(B.__args__, (int, str, Tuple[bytes, float]))
|
||||
|
||||
class X(Generic[T, P]):
|
||||
pass
|
||||
|
||||
# A = X[Tuple[*Ts], P]
|
||||
A = X[Tuple[*Ts], P]
|
||||
B = A[bytes, float, [int, str]]
|
||||
self.assertEqual(B.__args__, (Tuple[bytes, float], (int, str,)))
|
||||
|
||||
class Y(Generic[P, T]):
|
||||
pass
|
||||
|
||||
# A = Y[P, Tuple[*Ts]]
|
||||
A = Y[P, Tuple[*Ts]]
|
||||
B = A[[int, str], bytes, float]
|
||||
self.assertEqual(B.__args__, ((int, str,), Tuple[bytes, float]))
|
||||
|
||||
@@ -8892,10 +8871,10 @@ class ParamSpecTests(BaseTestCase):
|
||||
self.assertEqual(A8.__args__, ((T, list[T]),))
|
||||
self.assertEqual(A8[int], Base[[int, list[int]]])
|
||||
|
||||
# A9 = Base[[Tuple[*Ts], *Ts]]
|
||||
# self.assertEqual(A9.__parameters__, (Ts,))
|
||||
# self.assertEqual(A9.__args__, ((Tuple[*Ts], *Ts),))
|
||||
# self.assertEqual(A9[int, str], Base[Tuple[int, str], int, str])
|
||||
A9 = Base[[Tuple[*Ts], *Ts]]
|
||||
self.assertEqual(A9.__parameters__, (Ts,))
|
||||
self.assertEqual(A9.__args__, ((Tuple[*Ts], *Ts),))
|
||||
self.assertEqual(A9[int, str], Base[Tuple[int, str], int, str])
|
||||
|
||||
A10 = Base[P2]
|
||||
self.assertEqual(A10.__parameters__, (P2,))
|
||||
|
||||
@@ -80,6 +80,7 @@ struct Compiler<'src> {
|
||||
ctx: CompileContext,
|
||||
class_name: Option<String>,
|
||||
opts: CompileOpts,
|
||||
in_annotation: bool,
|
||||
}
|
||||
|
||||
enum DoneWithFuture {
|
||||
@@ -335,6 +336,7 @@ impl<'src> Compiler<'src> {
|
||||
},
|
||||
class_name: None,
|
||||
opts,
|
||||
in_annotation: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2897,7 +2899,11 @@ impl Compiler<'_> {
|
||||
.into(),
|
||||
});
|
||||
} else {
|
||||
self.compile_expression(annotation)?;
|
||||
let was_in_annotation = self.in_annotation;
|
||||
self.in_annotation = true;
|
||||
let result = self.compile_expression(annotation);
|
||||
self.in_annotation = was_in_annotation;
|
||||
result?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -3504,8 +3510,15 @@ impl Compiler<'_> {
|
||||
Self::contains_await(elt),
|
||||
)?;
|
||||
}
|
||||
Expr::Starred(_) => {
|
||||
return Err(self.error(CodegenErrorType::InvalidStarExpr));
|
||||
Expr::Starred(ExprStarred { value, .. }) => {
|
||||
if self.in_annotation {
|
||||
// In annotation context, starred expressions are allowed (PEP 646)
|
||||
// For now, just compile the inner value without wrapping with Unpack
|
||||
// This is a temporary solution until we figure out how to properly import typing
|
||||
self.compile_expression(value)?;
|
||||
} else {
|
||||
return Err(self.error(CodegenErrorType::InvalidStarExpr));
|
||||
}
|
||||
}
|
||||
Expr::If(ExprIf {
|
||||
test, body, orelse, ..
|
||||
|
||||
@@ -69,7 +69,7 @@ impl PyAsyncGen {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ impl PyDict {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ impl Constructor for PyEnumerate {
|
||||
impl PyEnumerate {
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,12 @@ impl Constructor for PyGenericAlias {
|
||||
return Err(vm.new_type_error("GenericAlias() takes no keyword arguments"));
|
||||
}
|
||||
let (origin, arguments): (_, PyObjectRef) = args.bind(vm)?;
|
||||
PyGenericAlias::new(origin, arguments, vm)
|
||||
let args = if let Ok(tuple) = arguments.try_to_ref::<PyTuple>(vm) {
|
||||
tuple.to_owned()
|
||||
} else {
|
||||
PyTuple::new_ref(vec![arguments], &vm.ctx)
|
||||
};
|
||||
PyGenericAlias::new(origin, args, false, vm)
|
||||
.into_ref_with_type(vm, cls)
|
||||
.map(Into::into)
|
||||
}
|
||||
@@ -84,28 +89,7 @@ impl Constructor for PyGenericAlias {
|
||||
flags(BASETYPE)
|
||||
)]
|
||||
impl PyGenericAlias {
|
||||
pub fn new(origin: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> Self {
|
||||
let args = if let Ok(tuple) = args.try_to_ref::<PyTuple>(vm) {
|
||||
tuple.to_owned()
|
||||
} else {
|
||||
PyTuple::new_ref(vec![args], &vm.ctx)
|
||||
};
|
||||
|
||||
let parameters = make_parameters(&args, vm);
|
||||
Self {
|
||||
origin,
|
||||
args,
|
||||
parameters,
|
||||
starred: false, // default to false
|
||||
}
|
||||
}
|
||||
|
||||
fn with_tuple_args(
|
||||
origin: PyTypeRef,
|
||||
args: PyTupleRef,
|
||||
starred: bool,
|
||||
vm: &VirtualMachine,
|
||||
) -> Self {
|
||||
pub fn new(origin: PyTypeRef, args: PyTupleRef, starred: bool, vm: &VirtualMachine) -> Self {
|
||||
let parameters = make_parameters(&args, vm);
|
||||
Self {
|
||||
origin,
|
||||
@@ -115,6 +99,16 @@ impl PyGenericAlias {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a GenericAlias from an origin and PyObjectRef arguments (helper for compatibility)
|
||||
pub fn from_args(origin: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> Self {
|
||||
let args = if let Ok(tuple) = args.try_to_ref::<PyTuple>(vm) {
|
||||
tuple.to_owned()
|
||||
} else {
|
||||
PyTuple::new_ref(vec![args], &vm.ctx)
|
||||
};
|
||||
Self::new(origin, args, false, vm)
|
||||
}
|
||||
|
||||
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
|
||||
fn repr_item(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
if obj.is(&vm.ctx.ellipsis) {
|
||||
@@ -146,7 +140,7 @@ impl PyGenericAlias {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(format!(
|
||||
let repr_str = format!(
|
||||
"{}[{}]",
|
||||
repr_item(self.origin.clone().into(), vm)?,
|
||||
if self.args.is_empty() {
|
||||
@@ -158,7 +152,14 @@ impl PyGenericAlias {
|
||||
.collect::<PyResult<Vec<_>>>()?
|
||||
.join(", ")
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
// Add * prefix if this is a starred GenericAlias
|
||||
Ok(if self.starred {
|
||||
format!("*{repr_str}")
|
||||
} else {
|
||||
repr_str
|
||||
})
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
@@ -200,10 +201,7 @@ impl PyGenericAlias {
|
||||
vm,
|
||||
)?;
|
||||
|
||||
Ok(
|
||||
PyGenericAlias::new(zelf.origin.clone(), new_args.to_pyobject(vm), vm)
|
||||
.into_pyobject(vm),
|
||||
)
|
||||
Ok(PyGenericAlias::new(zelf.origin.clone(), new_args, false, vm).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -598,7 +596,7 @@ impl Iterable for PyGenericAlias {
|
||||
// CPython's ga_iter creates an iterator that yields one starred GenericAlias
|
||||
// we don't have gaiterobject yet
|
||||
|
||||
let starred_alias = PyGenericAlias::with_tuple_args(
|
||||
let starred_alias = PyGenericAlias::new(
|
||||
zelf.origin.clone(),
|
||||
zelf.args.clone(),
|
||||
true, // starred
|
||||
|
||||
@@ -337,7 +337,7 @@ impl PyList {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ impl PyMappingProxy {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
@@ -790,7 +790,7 @@ impl PySet {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1134,7 +1134,7 @@ impl PyFrozenSet {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ impl PyTuple {
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ impl Constructor for PyWeak {
|
||||
impl PyWeak {
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -693,7 +693,7 @@ impl PyObject {
|
||||
} else {
|
||||
if self.class().fast_issubclass(vm.ctx.types.type_type) {
|
||||
if self.is(vm.ctx.types.type_type) {
|
||||
return PyGenericAlias::new(self.class().to_owned(), needle, vm)
|
||||
return PyGenericAlias::from_args(self.class().to_owned(), needle, vm)
|
||||
.to_pyresult(vm);
|
||||
}
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ mod _collections {
|
||||
args: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ mod decl {
|
||||
args: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
+1
-1
@@ -592,7 +592,7 @@ pub(super) mod _os {
|
||||
args: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -502,7 +502,7 @@ mod _sre {
|
||||
args: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,7 +816,7 @@ mod _sre {
|
||||
args: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
PyGenericAlias::from_args(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user