diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index d054c34fc..9f393d333 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -67,8 +67,8 @@ fn builtin_bin(x: PyIntRef, _vm: &VirtualMachine) -> String { // builtin_breakpoint -fn builtin_callable(obj: PyObjectRef, _vm: &VirtualMachine) -> bool { - objtype::class_has_attr(&obj.class(), "__call__") +fn builtin_callable(obj: PyObjectRef, vm: &VirtualMachine) -> bool { + vm.is_callable(&obj) } fn builtin_chr(i: u32, _vm: &VirtualMachine) -> String { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 6e7710516..81aa5367b 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -666,6 +666,21 @@ impl VirtualMachine { crate::stdlib::json::de_pyobject(self, s) } + pub fn is_callable(&self, obj: &PyObjectRef) -> bool { + match_class!(obj, + PyFunction => true, + PyMethod => true, + PyBuiltinFunction => true, + obj => { + if let Some(dict) = &obj.dict { + dict.contains_key("__call__", self) + } else { + false + } + }, + ) + } + pub fn _sub(&self, a: PyObjectRef, b: PyObjectRef) -> PyResult { self.call_or_reflection(a, b, "__sub__", "__rsub__", |vm, a, b| { Err(vm.new_unsupported_operand_error(a, b, "-"))