Fix type.__subclasscheck__ (#5864)

This commit is contained in:
Jeong, YunWon
2025-06-29 11:21:07 +09:00
committed by GitHub
parent 4ebecc0f5e
commit 0ef22ab6f2
3 changed files with 11 additions and 5 deletions

View File

@@ -3296,8 +3296,6 @@ class ProtocolTests(BaseTestCase):
self.assertNotIsInstance([], collections.abc.Mapping)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_issubclass_and_isinstance_on_Protocol_itself(self):
class C:
def x(self): pass

View File

@@ -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()))
}
@@ -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]

View File

@@ -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