1
1
use super :: { PyBoundMethod , PyType , PyTypeRef } ;
2
2
use crate :: {
3
3
class:: PyClassImpl ,
4
- types:: { Constructor , GetDescriptor } ,
4
+ common:: lock:: PyMutex ,
5
+ types:: { Constructor , GetDescriptor , Initializer } ,
5
6
AsObject , Context , Py , PyObjectRef , PyPayload , PyRef , PyResult , VirtualMachine ,
6
7
} ;
7
8
@@ -26,14 +27,16 @@ use crate::{
26
27
/// Class methods are different than C++ or Java static methods.
27
28
/// If you want those, see the staticmethod builtin.
28
29
#[ pyclass( module = false , name = "classmethod" ) ]
29
- #[ derive( Clone , Debug ) ]
30
+ #[ derive( Debug ) ]
30
31
pub struct PyClassMethod {
31
- callable : PyObjectRef ,
32
+ callable : PyMutex < PyObjectRef > ,
32
33
}
33
34
34
35
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
+ }
37
40
}
38
41
}
39
42
@@ -52,24 +55,38 @@ impl GetDescriptor for PyClassMethod {
52
55
) -> PyResult {
53
56
let ( zelf, obj) = Self :: _unwrap ( zelf, obj, vm) ?;
54
57
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 ( ) )
56
60
}
57
61
}
58
62
59
63
impl Constructor for PyClassMethod {
60
64
type Args = PyObjectRef ;
61
65
62
66
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 ( ( ) )
66
81
}
67
82
}
68
83
69
84
impl PyClassMethod {
70
85
pub fn new_ref ( callable : PyObjectRef , ctx : & Context ) -> PyRef < Self > {
71
86
PyRef :: new_ref (
72
- Self { callable } ,
87
+ Self {
88
+ callable : PyMutex :: new ( callable) ,
89
+ } ,
73
90
ctx. types . classmethod_type . to_owned ( ) ,
74
91
None ,
75
92
)
@@ -80,20 +97,22 @@ impl PyClassMethod {
80
97
impl PyClassMethod {
81
98
#[ pyproperty( magic) ]
82
99
fn func ( & self ) -> PyObjectRef {
83
- self . callable . clone ( )
100
+ self . callable . lock ( ) . clone ( )
84
101
}
85
102
86
103
#[ pyproperty( magic) ]
87
104
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__" ) {
89
106
Ok ( Some ( is_abstract) ) => is_abstract,
90
107
_ => vm. ctx . new_bool ( false ) . into ( ) ,
91
108
}
92
109
}
93
110
94
111
#[ pyproperty( magic, setter) ]
95
112
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) ?;
97
116
Ok ( ( ) )
98
117
}
99
118
}
0 commit comments