forked from Rust-related/RustPython
Replace vm.isinstance to obj.is_instance
This commit is contained in:
@@ -2,11 +2,12 @@
|
||||
//! https://docs.python.org/3/c-api/object.html
|
||||
|
||||
use crate::{
|
||||
builtins::{pystr::IntoPyStrRef, PyBytes, PyInt, PyStrRef},
|
||||
builtins::{pystr::IntoPyStrRef, PyBytes, PyInt, PyStrRef, PyTupleRef},
|
||||
bytesinner::ByteInnerNewOptions,
|
||||
common::{hash::PyHash, str::to_ascii},
|
||||
function::OptionalArg,
|
||||
protocol::PyIter,
|
||||
pyobject::IdProtocol,
|
||||
pyref_type_error,
|
||||
types::{Constructor, PyComparisonOp},
|
||||
PyObjectRef, PyResult, TryFromObject, TypeProtocol, VirtualMachine,
|
||||
@@ -127,8 +128,35 @@ impl PyObjectRef {
|
||||
vm.issubclass(self, cls)
|
||||
}
|
||||
|
||||
/// Determines if `self` is an instance of `cls`, either directly, indirectly or virtually via
|
||||
/// the __instancecheck__ magic method.
|
||||
pub fn is_instance(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
vm.isinstance(self, cls)
|
||||
// cpython first does an exact check on the type, although documentation doesn't state that
|
||||
// https://github.com/python/cpython/blob/a24107b04c1277e3c1105f98aff5bfa3a98b33a0/Objects/abstract.c#L2408
|
||||
if self.class().is(cls) {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if cls.class().is(&vm.ctx.types.type_type) {
|
||||
return vm.abstract_isinstance(self, cls);
|
||||
}
|
||||
|
||||
if let Ok(tuple) = PyTupleRef::try_from_object(vm, cls.clone()) {
|
||||
for typ in tuple.as_slice().iter() {
|
||||
if vm.with_recursion("in __instancecheck__", || self.is_instance(typ, vm))? {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if let Ok(meth) = vm.get_special_method(cls.clone(), "__instancecheck__")? {
|
||||
let ret =
|
||||
vm.with_recursion("in __instancecheck__", || meth.invoke((self.clone(),), vm))?;
|
||||
return ret.try_to_bool(vm);
|
||||
}
|
||||
|
||||
vm.abstract_isinstance(self, cls)
|
||||
}
|
||||
|
||||
pub fn hash(&self, vm: &VirtualMachine) -> PyResult<PyHash> {
|
||||
|
||||
33
vm/src/vm.rs
33
vm/src/vm.rs
@@ -1013,7 +1013,7 @@ impl VirtualMachine {
|
||||
})
|
||||
}
|
||||
|
||||
fn abstract_isinstance(&self, obj: &PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
|
||||
pub fn abstract_isinstance(&self, obj: &PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
|
||||
if let Ok(typ) = PyTypeRef::try_from_object(self, cls.clone()) {
|
||||
if obj.class().issubclass(typ.clone()) {
|
||||
Ok(true)
|
||||
@@ -1046,37 +1046,6 @@ impl VirtualMachine {
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if `obj` is an instance of `cls`, either directly, indirectly or virtually via
|
||||
/// the __instancecheck__ magic method.
|
||||
pub fn isinstance(&self, obj: &PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
|
||||
// cpython first does an exact check on the type, although documentation doesn't state that
|
||||
// https://github.com/python/cpython/blob/a24107b04c1277e3c1105f98aff5bfa3a98b33a0/Objects/abstract.c#L2408
|
||||
if obj.class().is(cls) {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if cls.class().is(&self.ctx.types.type_type) {
|
||||
return self.abstract_isinstance(obj, cls);
|
||||
}
|
||||
|
||||
if let Ok(tuple) = PyTupleRef::try_from_object(self, cls.clone()) {
|
||||
for typ in tuple.as_slice().iter() {
|
||||
if self.with_recursion("in __instancecheck__", || self.isinstance(obj, typ))? {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if let Ok(meth) = self.get_special_method(cls.clone(), "__instancecheck__")? {
|
||||
let ret =
|
||||
self.with_recursion("in __instancecheck__", || meth.invoke((obj.clone(),), self))?;
|
||||
return ret.try_to_bool(self);
|
||||
}
|
||||
|
||||
self.abstract_isinstance(obj, cls)
|
||||
}
|
||||
|
||||
fn abstract_issubclass(&self, subclass: PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
|
||||
let mut derived = subclass;
|
||||
loop {
|
||||
|
||||
Reference in New Issue
Block a user