diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 3a66cdcdea..7988f946ca 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5130,7 +5130,6 @@ class Child(Parent): gc.collect() self.assertEqual(Parent.__subclasses__(), []) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_instance_method_get_behavior(self): # test case for gh-113157 diff --git a/crates/vm/src/builtins/function.rs b/crates/vm/src/builtins/function.rs index 0003720c66..a223815162 100644 --- a/crates/vm/src/builtins/function.rs +++ b/crates/vm/src/builtins/function.rs @@ -1216,6 +1216,17 @@ impl GetAttr for PyBoundMethod { } } +impl GetDescriptor for PyBoundMethod { + fn descr_get( + zelf: PyObjectRef, + _obj: Option, + _cls: Option, + _vm: &VirtualMachine, + ) -> PyResult { + Ok(zelf) + } +} + #[derive(FromArgs)] pub struct PyBoundMethodNewArgs { #[pyarg(positional)] @@ -1230,8 +1241,14 @@ impl Constructor for PyBoundMethod { fn py_new( _cls: &Py, Self::Args { function, object }: Self::Args, - _vm: &VirtualMachine, + vm: &VirtualMachine, ) -> PyResult { + if !function.is_callable() { + return Err(vm.new_type_error("first argument must be callable".to_owned())); + } + if vm.is_none(&object) { + return Err(vm.new_type_error("instance must not be None".to_owned())); + } Ok(Self::new(object, function)) } } @@ -1258,7 +1275,15 @@ impl PyBoundMethod { } #[pyclass( - with(Callable, Comparable, Hashable, GetAttr, Constructor, Representable), + with( + Callable, + Comparable, + Hashable, + GetAttr, + GetDescriptor, + Constructor, + Representable + ), flags(IMMUTABLETYPE, HAS_WEAKREF) )] impl PyBoundMethod { @@ -1266,11 +1291,11 @@ impl PyBoundMethod { fn __reduce__( &self, vm: &VirtualMachine, - ) -> (Option, (PyObjectRef, Option)) { - let builtins_getattr = vm.builtins.get_attr("getattr", vm).ok(); + ) -> PyResult<(PyObjectRef, (PyObjectRef, PyObjectRef))> { + let builtins_getattr = vm.builtins.get_attr("getattr", vm)?; let func_self = self.object.clone(); - let func_name = self.function.get_attr("__name__", vm).ok(); - (builtins_getattr, (func_self, func_name)) + let func_name = self.function.get_attr("__name__", vm)?; + Ok((builtins_getattr, (func_self, func_name))) } #[pygetset]