Skip to content

Commit d06950e

Browse files
authored
Add classmethod initialize (RustPython#3773)
1 parent 9757c82 commit d06950e

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

vm/src/builtins/classmethod.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use super::{PyBoundMethod, PyType, PyTypeRef};
22
use crate::{
33
class::PyClassImpl,
4-
types::{Constructor, GetDescriptor},
4+
common::lock::PyMutex,
5+
types::{Constructor, GetDescriptor, Initializer},
56
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
67
};
78

@@ -26,14 +27,16 @@ use crate::{
2627
/// Class methods are different than C++ or Java static methods.
2728
/// If you want those, see the staticmethod builtin.
2829
#[pyclass(module = false, name = "classmethod")]
29-
#[derive(Clone, Debug)]
30+
#[derive(Debug)]
3031
pub struct PyClassMethod {
31-
callable: PyObjectRef,
32+
callable: PyMutex<PyObjectRef>,
3233
}
3334

3435
impl From<PyObjectRef> for PyClassMethod {
35-
fn from(value: PyObjectRef) -> Self {
36-
Self { callable: value }
36+
fn from(callable: PyObjectRef) -> Self {
37+
Self {
38+
callable: PyMutex::new(callable),
39+
}
3740
}
3841
}
3942

@@ -52,24 +55,38 @@ impl GetDescriptor for PyClassMethod {
5255
) -> PyResult {
5356
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
5457
let cls = cls.unwrap_or_else(|| obj.class().clone().into());
55-
Ok(PyBoundMethod::new_ref(cls, zelf.callable.clone(), &vm.ctx).into())
58+
let callable = zelf.callable.lock().clone();
59+
Ok(PyBoundMethod::new_ref(cls, callable, &vm.ctx).into())
5660
}
5761
}
5862

5963
impl Constructor for PyClassMethod {
6064
type Args = PyObjectRef;
6165

6266
fn py_new(cls: PyTypeRef, callable: Self::Args, vm: &VirtualMachine) -> PyResult {
63-
PyClassMethod { callable }
64-
.into_ref_with_type(vm, cls)
65-
.map(Into::into)
67+
PyClassMethod {
68+
callable: PyMutex::new(callable),
69+
}
70+
.into_ref_with_type(vm, cls)
71+
.map(Into::into)
72+
}
73+
}
74+
75+
impl Initializer for PyClassMethod {
76+
type Args = PyObjectRef;
77+
78+
fn init(zelf: PyRef<Self>, callable: Self::Args, _vm: &VirtualMachine) -> PyResult<()> {
79+
*zelf.callable.lock() = callable;
80+
Ok(())
6681
}
6782
}
6883

6984
impl PyClassMethod {
7085
pub fn new_ref(callable: PyObjectRef, ctx: &Context) -> PyRef<Self> {
7186
PyRef::new_ref(
72-
Self { callable },
87+
Self {
88+
callable: PyMutex::new(callable),
89+
},
7390
ctx.types.classmethod_type.to_owned(),
7491
None,
7592
)
@@ -80,20 +97,22 @@ impl PyClassMethod {
8097
impl PyClassMethod {
8198
#[pyproperty(magic)]
8299
fn func(&self) -> PyObjectRef {
83-
self.callable.clone()
100+
self.callable.lock().clone()
84101
}
85102

86103
#[pyproperty(magic)]
87104
fn isabstractmethod(&self, vm: &VirtualMachine) -> PyObjectRef {
88-
match vm.get_attribute_opt(self.callable.clone(), "__isabstractmethod__") {
105+
match vm.get_attribute_opt(self.callable.lock().clone(), "__isabstractmethod__") {
89106
Ok(Some(is_abstract)) => is_abstract,
90107
_ => vm.ctx.new_bool(false).into(),
91108
}
92109
}
93110

94111
#[pyproperty(magic, setter)]
95112
fn set_isabstractmethod(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
96-
self.callable.set_attr("__isabstractmethod__", value, vm)?;
113+
self.callable
114+
.lock()
115+
.set_attr("__isabstractmethod__", value, vm)?;
97116
Ok(())
98117
}
99118
}

0 commit comments

Comments
 (0)