Skip to content

Commit e3e2e7f

Browse files
Merge pull request RustPython#869 from skinny121/isinstance_tuple_arg
Accept a tuple for the second argument of isinstance and issubclass
2 parents 63a71d6 + 4a4631a commit e3e2e7f

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

tests/snippets/types_snippet.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
assert isinstance(type, type)
2828
assert issubclass(type, type)
2929

30+
assert not isinstance(type, (int, float))
31+
assert isinstance(type, (int, object))
32+
33+
assert not issubclass(type, (int, float))
34+
assert issubclass(type, (int, type))
35+
3036
class A: pass
3137
class B(A): pass
3238
class C(A): pass

vm/src/builtins.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ use num_traits::Signed;
1111
use crate::compile;
1212
use crate::import::import_module;
1313
use crate::obj::objbool;
14+
use crate::obj::objcode::PyCodeRef;
1415
use crate::obj::objdict::PyDictRef;
1516
use crate::obj::objint::{self, PyIntRef};
1617
use crate::obj::objiter;
1718
use crate::obj::objstr::{self, PyString, PyStringRef};
18-
use crate::obj::objtype::{self, PyClassRef};
19+
use crate::obj::objtuple::PyTuple;
20+
use crate::obj::objtype::{self, PyClass, PyClassRef};
1921

2022
use crate::frame::Scope;
2123
use crate::function::{Args, KwArgs, OptionalArg, PyFuncArgs};
@@ -25,7 +27,6 @@ use crate::pyobject::{
2527
};
2628
use crate::vm::VirtualMachine;
2729

28-
use crate::obj::objcode::PyCodeRef;
2930
#[cfg(not(target_arch = "wasm32"))]
3031
use crate::stdlib::io::io_open;
3132

@@ -312,19 +313,37 @@ fn builtin_id(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
312313

313314
// builtin_input
314315

315-
fn builtin_isinstance(obj: PyObjectRef, typ: PyClassRef, vm: &VirtualMachine) -> PyResult<bool> {
316-
vm.isinstance(&obj, &typ)
316+
fn type_test(
317+
vm: &VirtualMachine,
318+
typ: PyObjectRef,
319+
test: impl Fn(&PyClassRef) -> PyResult<bool>,
320+
test_name: &str,
321+
) -> PyResult<bool> {
322+
match_class!(typ,
323+
cls @ PyClass => test(&cls),
324+
tuple @ PyTuple => {
325+
for cls_obj in tuple.elements.borrow().iter() {
326+
let cls = PyClassRef::try_from_object(vm, cls_obj.clone())?;
327+
if test(&cls)? {
328+
return Ok(true);
329+
}
330+
}
331+
Ok(false)
332+
},
333+
_ => Err(vm.new_type_error(format!("{}() arg 2 must be a type or tuple of types", test_name)))
334+
)
317335
}
318336

319-
fn builtin_issubclass(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
320-
arg_check!(
321-
vm,
322-
args,
323-
required = [(subclass, Some(vm.get_type())), (cls, Some(vm.get_type()))]
324-
);
337+
fn builtin_isinstance(obj: PyObjectRef, typ: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
338+
type_test(vm, typ, |cls| vm.isinstance(&obj, cls), "isinstance")
339+
}
325340

326-
let issubclass = vm.issubclass(subclass, cls)?;
327-
Ok(vm.context().new_bool(issubclass))
341+
fn builtin_issubclass(
342+
subclass: PyClassRef,
343+
typ: PyObjectRef,
344+
vm: &VirtualMachine,
345+
) -> PyResult<bool> {
346+
type_test(vm, typ, |cls| vm.issubclass(&subclass, cls), "issubclass")
328347
}
329348

330349
fn builtin_iter(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/vm.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,12 @@ impl VirtualMachine {
304304

305305
/// Determines if `subclass` is a subclass of `cls`, either directly, indirectly or virtually
306306
/// via the __subclasscheck__ magic method.
307-
pub fn issubclass(&self, subclass: &PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
308-
let ret = self.call_method(cls, "__subclasscheck__", vec![subclass.clone()])?;
307+
pub fn issubclass(&self, subclass: &PyClassRef, cls: &PyClassRef) -> PyResult<bool> {
308+
let ret = self.call_method(
309+
cls.as_object(),
310+
"__subclasscheck__",
311+
vec![subclass.clone().into_object()],
312+
)?;
309313
objbool::boolval(self, ret)
310314
}
311315

0 commit comments

Comments
 (0)