Compile starred annotations (#5881)

* Fix starred annotation

* uncomment starred annotation
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2025-07-01 17:20:42 +09:00
1 parent 4ebd485694
commit 3d951a883a
16 files changed
+153 -163

No files matched your search

+94 -115
View File
@@ -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,))
+16 -3
View File
@@ -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, ..
+1 -1
View File
@@ -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)
}
}
+1 -1
View File
@@ -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)
}
}
+1 -1
View File
@@ -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)
}
}
+28 -30
View File
@@ -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
+1 -1
View File
@@ -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)
}
}
+1 -1
View File
@@ -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]
+2 -2
View File
@@ -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)
}
}
+1 -1
View File
@@ -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)
}
}
+1 -1
View File
@@ -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)
}
}
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -415,7 +415,7 @@ mod _collections {
args: PyObjectRef,
vm: &VirtualMachine,
) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
PyGenericAlias::from_args(cls, args, vm)
}
}
+1 -1
View File
@@ -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
View File
@@ -592,7 +592,7 @@ pub(super) mod _os {
args: PyObjectRef,
vm: &VirtualMachine,
) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
PyGenericAlias::from_args(cls, args, vm)
}
}
+2 -2
View File
@@ -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)
}
}