Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix init
  • Loading branch information
youknowone committed Jun 26, 2025
commit 6161d13a846b0601a2f1c47fa3e405aae7b4144d
58 changes: 1 addition & 57 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,6 @@ def test_var_substitution(self):
self.assertEqual(subst(int|str), int|str)
self.assertEqual(subst(Union[int, str]), Union[int, str])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_bad_var_substitution(self):
T = TypeVar('T')
bad_args = (
Expand Down Expand Up @@ -736,8 +734,6 @@ def test_allow_default_after_non_default_in_alias(self):
a4 = Callable[*Ts, T]
self.assertEqual(a4.__args__, (*Ts, T))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_paramspec_specialization(self):
T = TypeVar("T")
P = ParamSpec('P', default=[str, int])
Expand Down Expand Up @@ -785,8 +781,6 @@ class X[**Ts]: ...
self.assertIs(Ts.__default__, NoDefault)
self.assertFalse(Ts.has_default())

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_no_default_after_non_default(self):
DefaultStrT = TypeVar('DefaultStrT', default=str)
T = TypeVar('T')
Expand All @@ -796,8 +790,6 @@ def test_no_default_after_non_default(self):
):
Test = Generic[DefaultStrT, T]

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_need_more_params(self):
DefaultStrT = TypeVar('DefaultStrT', default=str)
T = TypeVar('T')
Expand Down Expand Up @@ -1638,7 +1630,7 @@ class B(Generic[Unpack[Ts]]): pass
def test_variadic_class_origin_is_correct(self):
Ts = TypeVarTuple('Ts')

# class C(Generic[*Ts]): pass
class C(Generic[*Ts]): pass
self.assertIs(C[int].__origin__, C)
self.assertIs(C[T].__origin__, C)
self.assertIs(C[Unpack[Ts]].__origin__, C)
Expand Down Expand Up @@ -1766,8 +1758,6 @@ def test_callable_args_are_correct(self):
self.assertEqual(s.__args__, (*Ts1, *Ts2))
self.assertEqual(u.__args__, (Unpack[Ts1], Unpack[Ts2]))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_variadic_class_with_duplicate_typevartuples_fails(self):
Ts1 = TypeVarTuple('Ts1')
Ts2 = TypeVarTuple('Ts2')
Expand Down Expand Up @@ -1815,15 +1805,11 @@ def test_type_concatenation_in_tuple_argument_list_succeeds(self):
Tuple[int, Unpack[Ts], str]
Tuple[int, bool, Unpack[Ts], float, str]

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_variadic_class_definition_using_packed_typevartuple_fails(self):
Ts = TypeVarTuple('Ts')
with self.assertRaises(TypeError):
class C(Generic[Ts]): pass

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_variadic_class_definition_using_concrete_types_fails(self):
Ts = TypeVarTuple('Ts')
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -3193,8 +3179,6 @@ def meth2(self):
self.assertIsInstance(C(), P)
self.assertIsSubclass(C, P)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_protocols_issubclass(self):
T = TypeVar('T')

Expand Down Expand Up @@ -3562,8 +3546,6 @@ def test_basics(self):
T = TypeVar("T")
self.assertEqual(List[list[T] | float].__parameters__, (T,))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generic_errors(self):
T = TypeVar('T')
S = TypeVar('S')
Expand Down Expand Up @@ -3605,8 +3587,6 @@ def test_generic_subclass_checks(self):
# but, not when the right arg is also a generic:
self.assertRaises(TypeError, isinstance, typ, typ)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_init(self):
T = TypeVar('T')
S = TypeVar('S')
Expand Down Expand Up @@ -3727,8 +3707,6 @@ def __setattr__(self, key, value):
# returned by the `Immutable[int]()` call
self.assertIsInstance(Immutable[int](), Immutable)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_subscripted_generics_as_proxies(self):
T = TypeVar('T')
class C(Generic[T]):
Expand Down Expand Up @@ -3838,8 +3816,6 @@ class C(List[int]): ...
self.assertTrue(naive_list_base_check([1, 2, 3], C))
self.assertFalse(naive_list_base_check(['a', 'b'], C))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_multi_subscr_base(self):
T = TypeVar('T')
U = TypeVar('U')
Expand Down Expand Up @@ -4096,8 +4072,6 @@ def test_pep_695_generics_with_future_annotations_nested_in_function(self):
set(results.generic_func.__type_params__)
)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_extended_generic_rules_subclassing(self):
class T1(Tuple[T, KT]): ...
class T2(Tuple[T, ...]): ...
Expand Down Expand Up @@ -4135,8 +4109,6 @@ def test_fail_with_bare_union(self):
with self.assertRaises(TypeError):
List[ClassVar[int]]

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_fail_with_bare_generic(self):
T = TypeVar('T')
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -4341,8 +4313,6 @@ class D(Generic[T]):
with self.assertRaises(AttributeError):
d_int.foobar = 'no'

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_errors(self):
with self.assertRaises(TypeError):
B = SimpleMapping[XK, Any]
Expand Down Expand Up @@ -4596,8 +4566,6 @@ def foo(x: T):

foo(42)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_implicit_any(self):
T = TypeVar('T')

Expand Down Expand Up @@ -5121,8 +5089,6 @@ class NoTypeCheck_WithFunction:


class ForwardRefTests(BaseTestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_basics(self):

class Node(Generic[T]):
Expand Down Expand Up @@ -5387,8 +5353,6 @@ class CF:
with self.assertRaises(TypeError):
get_type_hints(CF, globals()),

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_syntax_error(self):

with self.assertRaises(SyntaxError):
Expand Down Expand Up @@ -6103,8 +6067,6 @@ def with_union(x: int | list[Annotated[str, 'meta']]): ...
{'x': int | list[Annotated[str, 'meta']]},
)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_get_type_hints_annotated_refs(self):

Const = Annotated[T, "Const"]
Expand Down Expand Up @@ -7103,8 +7065,6 @@ class B(NamedTuple):
class C(NamedTuple, B):
y: str

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_generic(self):
class X(NamedTuple, Generic[T]):
x: T
Expand Down Expand Up @@ -7859,8 +7819,6 @@ class Point3D(Point2DGeneric[T], Generic[T, KT]):
class Point3D(Point2DGeneric[T], Generic[KT]):
c: KT

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_implicit_any_inheritance(self):
class A(TypedDict, Generic[T]):
a: T
Expand Down Expand Up @@ -8142,8 +8100,6 @@ def test_no_isinstance(self):

class IOTests(BaseTestCase):

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_io(self):

def stuff(a: IO) -> AnyStr:
Expand All @@ -8152,8 +8108,6 @@ def stuff(a: IO) -> AnyStr:
a = stuff.__annotations__['a']
self.assertEqual(a.__parameters__, (AnyStr,))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_textio(self):

def stuff(a: TextIO) -> str:
Expand All @@ -8162,8 +8116,6 @@ def stuff(a: TextIO) -> str:
a = stuff.__annotations__['a']
self.assertEqual(a.__parameters__, ())

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_binaryio(self):

def stuff(a: BinaryIO) -> bytes:
Expand Down Expand Up @@ -8483,8 +8435,6 @@ def test_too_few_type_args(self):
with self.assertRaisesRegex(TypeError, 'at least two arguments'):
Annotated[int]

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_pickle(self):
samples = [typing.Any, typing.Union[int, str],
typing.Optional[str], Tuple[int, ...],
Expand Down Expand Up @@ -8822,8 +8772,6 @@ def foo(self, *args: "P.args", **kwargs: "P.kwargs"):
gth(C.foo, globals(), locals()), {"args": P.args, "kwargs": P.kwargs}
)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_user_generics(self):
T = TypeVar("T")
P = ParamSpec("P")
Expand Down Expand Up @@ -8878,8 +8826,6 @@ class Z(Generic[P]):
with self.assertRaisesRegex(TypeError, "many arguments for"):
Z[P_2, bool]

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_multiple_paramspecs_in_user_generics(self):
P = ParamSpec("P")
P2 = ParamSpec("P2")
Expand Down Expand Up @@ -9524,8 +9470,6 @@ def test_special_attrs2(self):
loaded = pickle.loads(s)
self.assertIs(SpecialAttrsP, loaded)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_genericalias_dir(self):
class Foo(Generic[T]):
def bar(self):
Expand Down
2 changes: 2 additions & 0 deletions vm/src/protocol/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ impl PyObject {
self.get_attr(attr_name, vm).map(|o| !vm.is_none(&o))
}

/// Get an attribute by name.
/// `attr_name` can be a `&str`, `String`, or `PyStrRef`.
pub fn get_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult {
let attr_name = attr_name.as_pystr(&vm.ctx);
self.get_attr_inner(attr_name, vm)
Expand Down
40 changes: 37 additions & 3 deletions vm/src/stdlib/typing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
pub(crate) mod decl {
use crate::{
AsObject, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
builtins::{PyGenericAlias, PyTupleRef, PyTypeRef, pystr::AsPyStr},
builtins::{PyTupleRef, PyTypeRef, pystr::AsPyStr},
function::{FuncArgs, IntoFuncArgs, PyComparisonValue},
protocol::PyNumberMethods,
types::{AsNumber, Comparable, Constructor, PyComparisonOp, Representable},
Expand Down Expand Up @@ -920,6 +920,30 @@ pub(crate) mod decl {
}
}

/// Helper function to call typing module functions with cls as first argument
/// Similar to CPython's call_typing_args_kwargs
fn call_typing_args_kwargs(
name: &'static str,
cls: PyTypeRef,
args: FuncArgs,
vm: &VirtualMachine,
) -> PyResult {
let typing = vm.import("typing", 0)?;
let func = typing.get_attr(name, vm)?;

// Prepare arguments: (cls, *args)
let mut call_args = vec![cls.into()];
call_args.extend(args.args);

// Call with prepared args and original kwargs
let func_args = FuncArgs {
args: call_args,
kwargs: args.kwargs,
};

func.call(func_args, vm)
}

#[pyattr]
#[pyclass(name)]
#[derive(Debug, PyPayload)]
Expand All @@ -930,8 +954,18 @@ pub(crate) mod decl {
#[pyclass(flags(BASETYPE))]
impl Generic {
#[pyclassmethod(magic)]
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyResult {
// Convert single arg to FuncArgs
let func_args = FuncArgs {
args: vec![args],
kwargs: Default::default(),
};
call_typing_args_kwargs("_generic_class_getitem", cls, func_args, vm)
}

#[pyclassmethod(magic)]
fn init_subclass(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
call_typing_args_kwargs("_generic_init_subclass", cls, args, vm)
}
}

Expand Down