11use super :: { PyBoundMethod , PyType , PyTypeRef } ;
22use 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 ) ]
3031pub struct PyClassMethod {
31- callable : PyObjectRef ,
32+ callable : PyMutex < PyObjectRef > ,
3233}
3334
3435impl 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
5963impl 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
6984impl 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 {
8097impl 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