Skip to content

Commit ba8730d

Browse files
committed
type.__type_params__
1 parent e1b0eb8 commit ba8730d

File tree

3 files changed

+46
-35
lines changed

3 files changed

+46
-35
lines changed

Lib/test/test_typing.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,8 +1605,6 @@ class D(Generic[Unpack[Ts]]): pass
16051605
self.assertIs(D[T].__origin__, D)
16061606
self.assertIs(D[Unpack[Ts]].__origin__, D)
16071607

1608-
# TODO: RUSTPYTHON
1609-
@unittest.expectedFailure
16101608
def test_get_type_hints_on_unpack_args(self):
16111609
Ts = TypeVarTuple('Ts')
16121610

@@ -1809,8 +1807,6 @@ class F(Generic[Unpack[Ts], T1, T2]): pass
18091807
F[int, str, float]
18101808
F[int, str, float, bool]
18111809

1812-
# TODO: RUSTPYTHON
1813-
@unittest.expectedFailure
18141810
def test_variadic_args_annotations_are_correct(self):
18151811
Ts = TypeVarTuple('Ts')
18161812

@@ -3859,8 +3855,6 @@ def barfoo(x: AT): ...
38593855
def barfoo2(x: CT): ...
38603856
self.assertIs(get_type_hints(barfoo2, globals(), locals())['x'], CT)
38613857

3862-
# TODO: RUSTPYTHON
3863-
@unittest.expectedFailure
38643858
def test_generic_pep585_forward_ref(self):
38653859
# See https://bugs.python.org/issue41370
38663860

@@ -5189,8 +5183,6 @@ def cmp(o1, o2):
51895183
self.assertIsNot(r1, r2)
51905184
self.assertRaises(RecursionError, cmp, r1, r2)
51915185

5192-
# TODO: RUSTPYTHON
5193-
@unittest.expectedFailure
51945186
def test_union_forward_recursion(self):
51955187
ValueList = List['Value']
51965188
Value = Union[str, ValueList]
@@ -5239,8 +5231,6 @@ def foo(a: 'Callable[..., T]'):
52395231
self.assertEqual(get_type_hints(foo, globals(), locals()),
52405232
{'a': Callable[..., T]})
52415233

5242-
# TODO: RUSTPYTHON
5243-
@unittest.expectedFailure
52445234
def test_special_forms_forward(self):
52455235

52465236
class C:
@@ -5323,8 +5313,6 @@ def foo(self, x: int): ...
53235313

53245314
self.assertEqual(get_type_hints(Child.foo), {'x': int})
53255315

5326-
# TODO: RUSTPYTHON
5327-
@unittest.expectedFailure
53285316
def test_no_type_check_nested_types(self):
53295317
# See https://bugs.python.org/issue46571
53305318
class Other:
@@ -5409,8 +5397,6 @@ def test_no_type_check_TypeError(self):
54095397
# `TypeError: can't set attributes of built-in/extension type 'dict'`
54105398
no_type_check(dict)
54115399

5412-
# TODO: RUSTPYTHON
5413-
@unittest.expectedFailure
54145400
def test_no_type_check_forward_ref_as_string(self):
54155401
class C:
54165402
foo: typing.ClassVar[int] = 7
@@ -5465,8 +5451,6 @@ def test_default_globals(self):
54655451
hints = get_type_hints(ns['C'].foo)
54665452
self.assertEqual(hints, {'a': ns['C'], 'return': ns['D']})
54675453

5468-
# TODO: RUSTPYTHON
5469-
@unittest.expectedFailure
54705454
def test_final_forward_ref(self):
54715455
self.assertEqual(gth(Loop, globals())['attr'], Final[Loop])
54725456
self.assertNotEqual(gth(Loop, globals())['attr'], Final[int])
@@ -5832,8 +5816,6 @@ def test_get_type_hints_classes(self):
58325816
'my_inner_a2': mod_generics_cache.B.A,
58335817
'my_outer_a': mod_generics_cache.A})
58345818

5835-
# TODO: RUSTPYTHON
5836-
@unittest.expectedFailure
58375819
def test_get_type_hints_classes_no_implicit_optional(self):
58385820
class WithNoneDefault:
58395821
field: int = None # most type-checkers won't be happy with it
@@ -5878,8 +5860,6 @@ class B: ...
58785860
b.__annotations__ = {'x': 'A'}
58795861
self.assertEqual(gth(b, locals()), {'x': A})
58805862

5881-
# TODO: RUSTPYTHON
5882-
@unittest.expectedFailure
58835863
def test_get_type_hints_ClassVar(self):
58845864
self.assertEqual(gth(ann_module2.CV, ann_module2.__dict__),
58855865
{'var': typing.ClassVar[ann_module2.CV]})
@@ -6006,8 +5986,6 @@ def annotated_with_none_default(x: Annotated[int, 'data'] = None): ...
60065986
{'x': Annotated[int, 'data']},
60075987
)
60085988

6009-
# TODO: RUSTPYTHON
6010-
@unittest.expectedFailure
60115989
def test_get_type_hints_classes_str_annotations(self):
60125990
class Foo:
60135991
y = str
@@ -6023,8 +6001,6 @@ class BadModule:
60236001
self.assertNotIn('bad', sys.modules)
60246002
self.assertEqual(get_type_hints(BadModule), {})
60256003

6026-
# TODO: RUSTPYTHON
6027-
@unittest.expectedFailure
60286004
def test_get_type_hints_annotated_bad_module(self):
60296005
# See https://bugs.python.org/issue44468
60306006
class BadBase:
@@ -6035,8 +6011,6 @@ class BadType(BadBase):
60356011
self.assertNotIn('bad', sys.modules)
60366012
self.assertEqual(get_type_hints(BadType), {'foo': tuple, 'bar': list})
60376013

6038-
# TODO: RUSTPYTHON
6039-
@unittest.expectedFailure
60406014
def test_forward_ref_and_final(self):
60416015
# https://bugs.python.org/issue45166
60426016
hints = get_type_hints(ann_module5)
@@ -8274,8 +8248,6 @@ class C:
82748248
A.x = 5
82758249
self.assertEqual(C.x, 5)
82768250

8277-
# TODO: RUSTPYTHON
8278-
@unittest.expectedFailure
82798251
def test_special_form_containment(self):
82808252
class C:
82818253
classvar: Annotated[ClassVar[int], "a decoration"] = 4
@@ -8284,8 +8256,6 @@ class C:
82848256
self.assertEqual(get_type_hints(C, globals())['classvar'], ClassVar[int])
82858257
self.assertEqual(get_type_hints(C, globals())['const'], Final[int])
82868258

8287-
# TODO: RUSTPYTHON
8288-
@unittest.expectedFailure
82898259
def test_special_forms_nesting(self):
82908260
# These are uncommon types and are to ensure runtime
82918261
# is lax on validation. See gh-89547 for more context.
@@ -8563,8 +8533,6 @@ def test_no_isinstance(self):
85638533
with self.assertRaises(TypeError):
85648534
isinstance(42, TypeAlias)
85658535

8566-
# TODO: RUSTPYTHON
8567-
@unittest.expectedFailure
85688536
def test_stringized_usage(self):
85698537
class A:
85708538
a: "TypeAlias"
@@ -8652,8 +8620,6 @@ def test_args_kwargs(self):
86528620
self.assertEqual(repr(P.kwargs), "P.kwargs")
86538621

86548622

8655-
# TODO: RUSTPYTHON
8656-
@unittest.expectedFailure
86578623
def test_stringized(self):
86588624
P = ParamSpec('P')
86598625
class C(Generic[P]):

compiler/codegen/src/compile.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2901,7 +2901,20 @@ impl Compiler<'_> {
29012901
} else {
29022902
let was_in_annotation = self.in_annotation;
29032903
self.in_annotation = true;
2904-
let result = self.compile_expression(annotation);
2904+
2905+
// Special handling for starred annotations (*Ts -> Unpack[Ts])
2906+
let result = match annotation {
2907+
Expr::Starred(ExprStarred { value, .. }) => {
2908+
// Following CPython's approach:
2909+
// *args: *Ts (where Ts is a TypeVarTuple).
2910+
// Do [annotation_value] = [*Ts].
2911+
self.compile_expression(value)?;
2912+
emit!(self, Instruction::UnpackSequence { size: 1 });
2913+
Ok(())
2914+
}
2915+
_ => self.compile_expression(annotation),
2916+
};
2917+
29052918
self.in_annotation = was_in_annotation;
29062919
result?;
29072920
}

vm/src/builtins/type.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,38 @@ impl PyType {
849849
.and_then(|doc| get_text_signature_from_internal_doc(&self.name(), doc))
850850
.map(|signature| signature.to_string())
851851
}
852+
853+
#[pygetset]
854+
fn __type_params__(&self, vm: &VirtualMachine) -> PyTupleRef {
855+
let attrs = self.attributes.read();
856+
let key = vm.ctx.intern_str("__type_params__");
857+
if let Some(params) = attrs.get(&key) {
858+
if let Ok(tuple) = params.clone().downcast::<PyTuple>() {
859+
return tuple;
860+
}
861+
}
862+
// Return empty tuple if not found or not a tuple
863+
vm.ctx.empty_tuple.clone()
864+
}
865+
866+
#[pygetset(setter)]
867+
fn set___type_params__(
868+
&self,
869+
value: PySetterValue<PyTupleRef>,
870+
vm: &VirtualMachine,
871+
) -> PyResult<()> {
872+
match value {
873+
PySetterValue::Assign(value) => {
874+
let mut attrs = self.attributes.write();
875+
let key = vm.ctx.intern_str("__type_params__");
876+
attrs.insert(key, value.into());
877+
}
878+
PySetterValue::Delete => {
879+
return Err(vm.new_type_error("__type_params__ must be set to a tuple object"));
880+
}
881+
}
882+
Ok(())
883+
}
852884
}
853885

854886
impl Constructor for PyType {

0 commit comments

Comments
 (0)