diff --git a/tests/snippets/class.py b/tests/snippets/class.py index e226f9c4b4..f5dce24257 100644 --- a/tests/snippets/class.py +++ b/tests/snippets/class.py @@ -42,12 +42,9 @@ def kungfu(x): bar = Bar() -bar.fubar(2) -# TODO: make below work: -# Bar.fubar(2) +bar.fubar(2) +Bar.fubar(2) bar.kungfu(3) -# TODO: make below work: -# Bar.kungfu(3) - +Bar.kungfu(3) diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index d4e4dafce2..955f2643e5 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,6 +1,6 @@ use super::super::pyobject::{ - AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult, - TypeProtocol, + AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, + PyResult, TypeProtocol, }; use super::super::vm::VirtualMachine; use super::objtype; @@ -22,7 +22,17 @@ pub fn init(context: &PyContext) { } fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - Ok(vm.new_bound_method(args.args[0].clone(), args.args[1].clone())) + arg_check!( + vm, + args, + required = [(function, None), (obj, None), (cls, None)] + ); + + if obj.is(&vm.get_none()) && !cls.is(&obj.typ()) { + Ok(function.clone()) + } else { + Ok(vm.ctx.new_bound_method(function.clone(), obj.clone())) + } } fn member_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { @@ -50,7 +60,7 @@ fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { match cls.get_attr("function") { Some(function) => { let py_obj = owner.clone(); - let py_method = vm.new_bound_method(function, py_obj); + let py_method = vm.ctx.new_bound_method(function, py_obj); Ok(py_method) } None => { diff --git a/vm/src/obj/objproperty.rs b/vm/src/obj/objproperty.rs index d2972a2686..1876915cb0 100644 --- a/vm/src/obj/objproperty.rs +++ b/vm/src/obj/objproperty.rs @@ -31,7 +31,7 @@ fn property_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { match cls.get_attr("fget") { Some(getter) => { - let py_method = vm.new_bound_method(getter, inst.clone()); + let py_method = vm.ctx.new_bound_method(getter, inst.clone()); vm.invoke(py_method, PyFuncArgs::default()) } None => { diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 7f68a37e63..86818cf98f 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -29,6 +29,7 @@ pub fn init(context: &PyContext) { type_type.set_attr("__class__", context.new_member_descriptor(type_new)); type_type.set_attr("__repr__", context.new_rustfunc(type_repr)); type_type.set_attr("__prepare__", context.new_rustfunc(type_prepare)); + type_type.set_attr("__getattribute__", context.new_rustfunc(type_getattribute)); } fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -85,7 +86,7 @@ pub fn get_type_name(typ: &PyObjectRef) -> String { } pub fn type_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - debug!("type.__new__{:?}", args); + debug!("type.__new__ {:?}", args); if args.args.len() == 2 { arg_check!( vm, diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 05ecade75d..17c89ba0b6 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -92,10 +92,6 @@ impl VirtualMachine { self.ctx.none() } - pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef { - self.ctx.new_bound_method(function, object) - } - pub fn get_type(&self) -> PyObjectRef { self.ctx.type_type() } @@ -202,7 +198,13 @@ impl VirtualMachine { let cls = obj.typ(); match cls.get_attr(method_name) { Some(func) => { - trace!("vm.call_method {:?} {:?} -> {:?}", obj, method_name, func); + trace!( + "vm.call_method {:?} {:?} {:?} -> {:?}", + obj, + cls, + method_name, + func + ); let wrapped = self.call_get_descriptor(func, obj.clone())?; self.invoke(wrapped, args) } @@ -423,6 +425,7 @@ impl VirtualMachine { // get_attribute should be used for full attribute access (usually from user code). pub fn get_attribute(&mut self, obj: PyObjectRef, attr_name: PyObjectRef) -> PyResult { + trace!("vm.__getattribute__: {:?} {:?}", obj, attr_name); self.call_method(&obj, "__getattribute__", vec![attr_name]) }