Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 0 additions & 2 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3296,8 +3296,6 @@ class Foo(collections.abc.Mapping, Protocol):

self.assertNotIsInstance([], collections.abc.Mapping)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_issubclass_and_isinstance_on_Protocol_itself(self):
class C:
def x(self): pass
Expand Down
8 changes: 5 additions & 3 deletions vm/src/builtins/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ impl Py<PyType> {
/// Determines if `subclass` is actually a subclass of `cls`, this doesn't call __subclasscheck__,
/// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic
/// method.
pub fn fast_issubclass(&self, cls: &impl Borrow<crate::PyObject>) -> bool {
pub fn fast_issubclass(&self, cls: &impl Borrow<PyObject>) -> bool {
self.as_object().is(cls.borrow()) || self.mro.read().iter().any(|c| c.is(cls.borrow()))
}

Expand Down Expand Up @@ -1216,8 +1216,10 @@ impl Py<PyType> {
}

#[pymethod]
fn __subclasscheck__(&self, subclass: PyTypeRef) -> bool {
subclass.fast_issubclass(self)
fn __subclasscheck__(&self, subclass: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
// Use real_is_subclass to avoid going through __subclasscheck__ recursion
// This matches CPython's type___subclasscheck___impl which calls _PyObject_RealIsSubclass
subclass.real_is_subclass(self.as_object(), vm)
}

#[pyclassmethod]
Expand Down
6 changes: 6 additions & 0 deletions vm/src/protocol/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,12 @@ impl PyObject {
}
}

/// Real issubclass check without going through __subclasscheck__
/// This is equivalent to CPython's _PyObject_RealIsSubclass which just calls recursive_issubclass
pub fn real_is_subclass(&self, cls: &PyObject, vm: &VirtualMachine) -> PyResult<bool> {
self.recursive_issubclass(cls, vm)
}

/// Determines if `self` is a subclass of `cls`, either directly, indirectly or virtually
/// via the __subclasscheck__ magic method.
/// PyObject_IsSubclass/object_issubclass
Expand Down
Loading