From d06950e0673ebbb2aefd97941efa09da1f3d1c65 Mon Sep 17 00:00:00 2001 From: oow214 <83155697+oow214@users.noreply.github.com> Date: Sat, 11 Jun 2022 20:16:36 +0900 Subject: [PATCH] Add classmethod initialize (#3773) --- vm/src/builtins/classmethod.rs | 45 ++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/vm/src/builtins/classmethod.rs b/vm/src/builtins/classmethod.rs index de7db8666..882e412eb 100644 --- a/vm/src/builtins/classmethod.rs +++ b/vm/src/builtins/classmethod.rs @@ -1,7 +1,8 @@ use super::{PyBoundMethod, PyType, PyTypeRef}; use crate::{ class::PyClassImpl, - types::{Constructor, GetDescriptor}, + common::lock::PyMutex, + types::{Constructor, GetDescriptor, Initializer}, AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, }; @@ -26,14 +27,16 @@ use crate::{ /// Class methods are different than C++ or Java static methods. /// If you want those, see the staticmethod builtin. #[pyclass(module = false, name = "classmethod")] -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct PyClassMethod { - callable: PyObjectRef, + callable: PyMutex, } impl From for PyClassMethod { - fn from(value: PyObjectRef) -> Self { - Self { callable: value } + fn from(callable: PyObjectRef) -> Self { + Self { + callable: PyMutex::new(callable), + } } } @@ -52,7 +55,8 @@ impl GetDescriptor for PyClassMethod { ) -> PyResult { let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?; let cls = cls.unwrap_or_else(|| obj.class().clone().into()); - Ok(PyBoundMethod::new_ref(cls, zelf.callable.clone(), &vm.ctx).into()) + let callable = zelf.callable.lock().clone(); + Ok(PyBoundMethod::new_ref(cls, callable, &vm.ctx).into()) } } @@ -60,16 +64,29 @@ impl Constructor for PyClassMethod { type Args = PyObjectRef; fn py_new(cls: PyTypeRef, callable: Self::Args, vm: &VirtualMachine) -> PyResult { - PyClassMethod { callable } - .into_ref_with_type(vm, cls) - .map(Into::into) + PyClassMethod { + callable: PyMutex::new(callable), + } + .into_ref_with_type(vm, cls) + .map(Into::into) + } +} + +impl Initializer for PyClassMethod { + type Args = PyObjectRef; + + fn init(zelf: PyRef, callable: Self::Args, _vm: &VirtualMachine) -> PyResult<()> { + *zelf.callable.lock() = callable; + Ok(()) } } impl PyClassMethod { pub fn new_ref(callable: PyObjectRef, ctx: &Context) -> PyRef { PyRef::new_ref( - Self { callable }, + Self { + callable: PyMutex::new(callable), + }, ctx.types.classmethod_type.to_owned(), None, ) @@ -80,12 +97,12 @@ impl PyClassMethod { impl PyClassMethod { #[pyproperty(magic)] fn func(&self) -> PyObjectRef { - self.callable.clone() + self.callable.lock().clone() } #[pyproperty(magic)] fn isabstractmethod(&self, vm: &VirtualMachine) -> PyObjectRef { - match vm.get_attribute_opt(self.callable.clone(), "__isabstractmethod__") { + match vm.get_attribute_opt(self.callable.lock().clone(), "__isabstractmethod__") { Ok(Some(is_abstract)) => is_abstract, _ => vm.ctx.new_bool(false).into(), } @@ -93,7 +110,9 @@ impl PyClassMethod { #[pyproperty(magic, setter)] fn set_isabstractmethod(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - self.callable.set_attr("__isabstractmethod__", value, vm)?; + self.callable + .lock() + .set_attr("__isabstractmethod__", value, vm)?; Ok(()) } }