Skip to content

Commit 151ba9a

Browse files
ever0deyouknowone
authored andcommitted
Fix classmethod descr_get to match CPython behavior (RustPython#7420)
Simplify classmethod.__get__ to always create a PyBoundMethod binding the callable to the class, matching CPython's cm_descr_get which simply calls PyMethod_New(cm->cm_callable, type). The previous implementation incorrectly tried to call __get__ on the wrapped callable, which broke when a bound method was passed to classmethod() (e.g. classmethod(A().foo)).
1 parent 471f4e3 commit 151ba9a

2 files changed

Lines changed: 1 addition & 7 deletions

File tree

Lib/test/test_decorators.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ def bar(): return 42
291291
self.assertEqual(bar(), 42)
292292
self.assertEqual(actions, expected_actions)
293293

294-
@unittest.expectedFailure # TODO: RUSTPYTHON
295294
def test_bound_function_inside_classmethod(self):
296295
class A:
297296
def foo(self, cls):

crates/vm/src/builtins/classmethod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,8 @@ impl GetDescriptor for PyClassMethod {
5757
) -> PyResult {
5858
let (zelf, _obj) = Self::_unwrap(&zelf, obj, vm)?;
5959
let cls = cls.unwrap_or_else(|| _obj.class().to_owned().into());
60-
// Clone and release lock before calling Python code to prevent deadlock
6160
let callable = zelf.callable.lock().clone();
62-
let call_descr_get: PyResult<PyObjectRef> = callable.get_attr("__get__", vm);
63-
match call_descr_get {
64-
Err(_) => Ok(PyBoundMethod::new(cls, callable).into_ref(&vm.ctx).into()),
65-
Ok(call_descr_get) => call_descr_get.call((cls.clone(), cls), vm),
66-
}
61+
Ok(PyBoundMethod::new(cls, callable).into_ref(&vm.ctx).into())
6762
}
6863
}
6964

0 commit comments

Comments
 (0)