type.__type_params__

This commit is contained in:
Jeong YunWon authored and Jeong, YunWon committed 2025-07-01 19:05:29 +09:00
1 parent e25c2856ad
commit fa7af0e5ea
5 files changed
+57 -38

No files matched your search

-2
View File
@@ -3246,8 +3246,6 @@ class TestStringAnnotations(unittest.TestCase):
# won't exist on the instance.
self.assertNotIn('not_iv4', c.__dict__)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_text_annotations(self):
from test import dataclass_textanno
-35
View File
@@ -1605,8 +1605,6 @@ 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')
@@ -1809,8 +1807,6 @@ 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')
@@ -2494,7 +2490,6 @@ class BaseCallableTests:
self.assertEqual(C5[int, str, float],
Callable[[typing.List[int], tuple[str, int], float], int])
@unittest.skip("TODO: RUSTPYTHON")
def test_type_subst_error(self):
Callable = self.Callable
P = ParamSpec('P')
@@ -3859,8 +3854,6 @@ class GenericTests(BaseTestCase):
def barfoo2(x: CT): ...
self.assertIs(get_type_hints(barfoo2, globals(), locals())['x'], CT)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generic_pep585_forward_ref(self):
# See https://bugs.python.org/issue41370
@@ -5189,8 +5182,6 @@ class ForwardRefTests(BaseTestCase):
self.assertIsNot(r1, r2)
self.assertRaises(RecursionError, cmp, r1, r2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_union_forward_recursion(self):
ValueList = List['Value']
Value = Union[str, ValueList]
@@ -5239,8 +5230,6 @@ class ForwardRefTests(BaseTestCase):
self.assertEqual(get_type_hints(foo, globals(), locals()),
{'a': Callable[..., T]})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_special_forms_forward(self):
class C:
@@ -5323,8 +5312,6 @@ class ForwardRefTests(BaseTestCase):
self.assertEqual(get_type_hints(Child.foo), {'x': int})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_no_type_check_nested_types(self):
# See https://bugs.python.org/issue46571
class Other:
@@ -5409,8 +5396,6 @@ class ForwardRefTests(BaseTestCase):
# `TypeError: can't set attributes of built-in/extension type 'dict'`
no_type_check(dict)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_no_type_check_forward_ref_as_string(self):
class C:
foo: typing.ClassVar[int] = 7
@@ -5465,8 +5450,6 @@ class ForwardRefTests(BaseTestCase):
hints = get_type_hints(ns['C'].foo)
self.assertEqual(hints, {'a': ns['C'], 'return': ns['D']})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_final_forward_ref(self):
self.assertEqual(gth(Loop, globals())['attr'], Final[Loop])
self.assertNotEqual(gth(Loop, globals())['attr'], Final[int])
@@ -5832,8 +5815,6 @@ class GetTypeHintTests(BaseTestCase):
'my_inner_a2': mod_generics_cache.B.A,
'my_outer_a': mod_generics_cache.A})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_get_type_hints_classes_no_implicit_optional(self):
class WithNoneDefault:
field: int = None # most type-checkers won't be happy with it
@@ -5878,8 +5859,6 @@ class GetTypeHintTests(BaseTestCase):
b.__annotations__ = {'x': 'A'}
self.assertEqual(gth(b, locals()), {'x': A})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_get_type_hints_ClassVar(self):
self.assertEqual(gth(ann_module2.CV, ann_module2.__dict__),
{'var': typing.ClassVar[ann_module2.CV]})
@@ -6006,8 +5985,6 @@ class GetTypeHintTests(BaseTestCase):
{'x': Annotated[int, 'data']},
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_get_type_hints_classes_str_annotations(self):
class Foo:
y = str
@@ -6023,8 +6000,6 @@ class GetTypeHintTests(BaseTestCase):
self.assertNotIn('bad', sys.modules)
self.assertEqual(get_type_hints(BadModule), {})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_get_type_hints_annotated_bad_module(self):
# See https://bugs.python.org/issue44468
class BadBase:
@@ -6035,8 +6010,6 @@ class GetTypeHintTests(BaseTestCase):
self.assertNotIn('bad', sys.modules)
self.assertEqual(get_type_hints(BadType), {'foo': tuple, 'bar': list})
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_forward_ref_and_final(self):
# https://bugs.python.org/issue45166
hints = get_type_hints(ann_module5)
@@ -8274,8 +8247,6 @@ class AnnotatedTests(BaseTestCase):
A.x = 5
self.assertEqual(C.x, 5)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_special_form_containment(self):
class C:
classvar: Annotated[ClassVar[int], "a decoration"] = 4
@@ -8284,8 +8255,6 @@ class AnnotatedTests(BaseTestCase):
self.assertEqual(get_type_hints(C, globals())['classvar'], ClassVar[int])
self.assertEqual(get_type_hints(C, globals())['const'], Final[int])
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_special_forms_nesting(self):
# These are uncommon types and are to ensure runtime
# is lax on validation. See gh-89547 for more context.
@@ -8563,8 +8532,6 @@ class TypeAliasTests(BaseTestCase):
with self.assertRaises(TypeError):
isinstance(42, TypeAlias)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_stringized_usage(self):
class A:
a: "TypeAlias"
@@ -8652,8 +8619,6 @@ class ParamSpecTests(BaseTestCase):
self.assertEqual(repr(P.kwargs), "P.kwargs")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_stringized(self):
P = ParamSpec('P')
class C(Generic[P]):
+14 -1
View File
@@ -2901,7 +2901,20 @@ impl Compiler<'_> {
} else {
let was_in_annotation = self.in_annotation;
self.in_annotation = true;
let result = self.compile_expression(annotation);
// Special handling for starred annotations (*Ts -> Unpack[Ts])
let result = match annotation {
Expr::Starred(ExprStarred { value, .. }) => {
// Following CPython's approach:
// *args: *Ts (where Ts is a TypeVarTuple).
// Do [annotation_value] = [*Ts].
self.compile_expression(value)?;
emit!(self, Instruction::UnpackSequence { size: 1 });
Ok(())
}
_ => self.compile_expression(annotation),
};
self.in_annotation = was_in_annotation;
result?;
}
+42
View File
@@ -849,6 +849,48 @@ impl PyType {
.and_then(|doc| get_text_signature_from_internal_doc(&self.name(), doc))
.map(|signature| signature.to_string())
}
#[pygetset]
fn __type_params__(&self, vm: &VirtualMachine) -> PyTupleRef {
let attrs = self.attributes.read();
let key = identifier!(vm, __type_params__);
if let Some(params) = attrs.get(&key) {
if let Ok(tuple) = params.clone().downcast::<PyTuple>() {
return tuple;
}
}
// Return empty tuple if not found or not a tuple
vm.ctx.empty_tuple.clone()
}
#[pygetset(setter)]
fn set___type_params__(
&self,
value: PySetterValue<PyTupleRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
match value {
PySetterValue::Assign(ref val) => {
let key = identifier!(vm, __type_params__);
self.check_set_special_type_attr(val.as_ref(), key, vm)?;
let mut attrs = self.attributes.write();
attrs.insert(key, val.clone().into());
}
PySetterValue::Delete => {
// For delete, we still need to check if the type is immutable
if self.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) {
return Err(vm.new_type_error(format!(
"cannot delete '__type_params__' attribute of immutable type '{}'",
self.slot_name()
)));
}
let mut attrs = self.attributes.write();
let key = identifier!(vm, __type_params__);
attrs.shift_remove(&key);
}
}
Ok(())
}
}
impl Constructor for PyType {
+1
View File
@@ -223,6 +223,7 @@ declare_const_name! {
__sizeof__,
__truediv__,
__trunc__,
__type_params__,
__typing_subst__,
__typing_is_unpacked_typevartuple__,
__typing_prepare_subst__,