@@ -6,40 +6,74 @@ See also [CPython source code.](https://github.com/python/cpython/blob/50b48572d
6
6
use super :: { PyStr , PyType , PyTypeRef } ;
7
7
use crate :: {
8
8
class:: PyClassImpl ,
9
- function:: { IntoFuncArgs , OptionalArg } ,
10
- types:: { Callable , Constructor , GetAttr , GetDescriptor , Representable } ,
11
- AsObject , Context , Py , PyObjectRef , PyPayload , PyResult , VirtualMachine ,
9
+ common:: lock:: PyRwLock ,
10
+ function:: { FuncArgs , IntoFuncArgs , OptionalArg } ,
11
+ types:: { Callable , Constructor , GetAttr , GetDescriptor , Initializer , Representable } ,
12
+ AsObject , Context , Py , PyObjectRef , PyPayload , PyRef , PyResult , VirtualMachine ,
12
13
} ;
13
14
14
15
#[ pyclass( module = false , name = "super" , traverse) ]
15
16
#[ derive( Debug ) ]
16
17
pub struct PySuper {
18
+ inner : PyRwLock < PySuperInner > ,
19
+ }
20
+
21
+ #[ derive( Debug , Traverse ) ]
22
+ struct PySuperInner {
17
23
typ : PyTypeRef ,
18
24
obj : Option < ( PyObjectRef , PyTypeRef ) > ,
19
25
}
20
26
27
+ impl PySuperInner {
28
+ fn new ( typ : PyTypeRef , obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult < Self > {
29
+ let obj = if vm. is_none ( & obj) {
30
+ None
31
+ } else {
32
+ let obj_type = supercheck ( typ. clone ( ) , obj. clone ( ) , vm) ?;
33
+ Some ( ( obj, obj_type) )
34
+ } ;
35
+ Ok ( Self { typ, obj } )
36
+ }
37
+ }
38
+
21
39
impl PyPayload for PySuper {
22
40
fn class ( ctx : & Context ) -> & ' static Py < PyType > {
23
41
ctx. types . super_type
24
42
}
25
43
}
26
44
27
- #[ derive( FromArgs , Traverse ) ]
28
- pub struct PySuperNewArgs {
45
+ impl Constructor for PySuper {
46
+ type Args = FuncArgs ;
47
+
48
+ fn py_new ( cls : PyTypeRef , _args : Self :: Args , vm : & VirtualMachine ) -> PyResult {
49
+ let obj = PySuper {
50
+ inner : PyRwLock :: new ( PySuperInner :: new (
51
+ vm. ctx . types . object_type . to_owned ( ) , // is this correct?
52
+ vm. ctx . none ( ) ,
53
+ vm,
54
+ ) ?) ,
55
+ }
56
+ . into_ref_with_type ( vm, cls) ?;
57
+ Ok ( obj. into ( ) )
58
+ }
59
+ }
60
+
61
+ #[ derive( FromArgs ) ]
62
+ pub struct InitArgs {
29
63
#[ pyarg( positional, optional) ]
30
64
py_type : OptionalArg < PyTypeRef > ,
31
65
#[ pyarg( positional, optional) ]
32
66
py_obj : OptionalArg < PyObjectRef > ,
33
67
}
34
68
35
- impl Constructor for PySuper {
36
- type Args = PySuperNewArgs ;
69
+ impl Initializer for PySuper {
70
+ type Args = InitArgs ;
37
71
38
- fn py_new (
39
- cls : PyTypeRef ,
72
+ fn init (
73
+ zelf : PyRef < Self > ,
40
74
Self :: Args { py_type, py_obj } : Self :: Args ,
41
75
vm : & VirtualMachine ,
42
- ) -> PyResult {
76
+ ) -> PyResult < ( ) > {
43
77
// Get the type:
44
78
let ( typ, obj) = if let OptionalArg :: Present ( ty) = py_type {
45
79
( ty, py_obj. unwrap_or_none ( vm) )
@@ -91,44 +125,36 @@ impl Constructor for PySuper {
91
125
( typ, obj)
92
126
} ;
93
127
94
- PySuper :: new ( typ, obj, vm) ?
95
- . into_ref_with_type ( vm, cls)
96
- . map ( Into :: into)
128
+ let mut inner = PySuperInner :: new ( typ, obj, vm) ?;
129
+ std:: mem:: swap ( & mut inner, & mut zelf. inner . write ( ) ) ;
130
+
131
+ Ok ( ( ) )
97
132
}
98
133
}
99
134
100
- #[ pyclass( with( GetAttr , GetDescriptor , Constructor , Representable ) ) ]
135
+ #[ pyclass( with( GetAttr , GetDescriptor , Constructor , Initializer , Representable ) ) ]
101
136
impl PySuper {
102
- fn new ( typ : PyTypeRef , obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult < Self > {
103
- let obj = if vm. is_none ( & obj) {
104
- None
105
- } else {
106
- let obj_type = supercheck ( typ. clone ( ) , obj. clone ( ) , vm) ?;
107
- Some ( ( obj, obj_type) )
108
- } ;
109
- Ok ( Self { typ, obj } )
110
- }
111
-
112
137
#[ pygetset( magic) ]
113
138
fn thisclass ( & self ) -> PyTypeRef {
114
- self . typ . clone ( )
139
+ self . inner . read ( ) . typ . clone ( )
115
140
}
116
141
117
142
#[ pygetset( magic) ]
118
143
fn self_class ( & self ) -> Option < PyTypeRef > {
119
- Some ( self . obj . as_ref ( ) ?. 1 . clone ( ) )
144
+ Some ( self . inner . read ( ) . obj . as_ref ( ) ?. 1 . clone ( ) )
120
145
}
121
146
122
147
#[ pygetset]
123
148
fn __self__ ( & self ) -> Option < PyObjectRef > {
124
- Some ( self . obj . as_ref ( ) ?. 0 . clone ( ) )
149
+ Some ( self . inner . read ( ) . obj . as_ref ( ) ?. 0 . clone ( ) )
125
150
}
126
151
}
127
152
128
153
impl GetAttr for PySuper {
129
154
fn getattro ( zelf : & Py < Self > , name : & Py < PyStr > , vm : & VirtualMachine ) -> PyResult {
130
155
let skip = |zelf : & Py < Self > , name| zelf. as_object ( ) . generic_getattr ( name, vm) ;
131
- let ( obj, start_type) : ( PyObjectRef , PyTypeRef ) = match zelf. obj . clone ( ) {
156
+ let obj = zelf. inner . read ( ) . obj . clone ( ) ;
157
+ let ( obj, start_type) : ( PyObjectRef , PyTypeRef ) = match obj {
132
158
Some ( o) => o,
133
159
None => return skip ( zelf, name) ,
134
160
} ;
@@ -143,7 +169,7 @@ impl GetAttr for PySuper {
143
169
// skip the classes in start_type.mro up to and including zelf.typ
144
170
let mro: Vec < _ > = start_type
145
171
. iter_mro ( )
146
- . skip_while ( |cls| !cls. is ( & zelf. typ ) )
172
+ . skip_while ( |cls| !cls. is ( & zelf. inner . read ( ) . typ ) )
147
173
. skip ( 1 ) // skip su->type (if any)
148
174
. collect ( ) ;
149
175
for cls in mro {
@@ -171,26 +197,38 @@ impl GetDescriptor for PySuper {
171
197
vm : & VirtualMachine ,
172
198
) -> PyResult {
173
199
let ( zelf, obj) = Self :: _unwrap ( & zelf_obj, obj, vm) ?;
174
- if vm. is_none ( & obj) || zelf. obj . is_some ( ) {
200
+ if vm. is_none ( & obj) || zelf. inner . read ( ) . obj . is_some ( ) {
175
201
return Ok ( zelf_obj) ;
176
202
}
177
203
let zelf_class = zelf. as_object ( ) . class ( ) ;
178
204
if zelf_class. is ( vm. ctx . types . super_type ) {
179
- Ok ( PySuper :: new ( zelf. typ . clone ( ) , obj, vm) ?. into_pyobject ( vm) )
205
+ let typ = zelf. inner . read ( ) . typ . clone ( ) ;
206
+ Ok ( PySuper {
207
+ inner : PyRwLock :: new ( PySuperInner :: new ( typ, obj, vm) ?) ,
208
+ }
209
+ . into_ref ( & vm. ctx )
210
+ . into ( ) )
180
211
} else {
181
- let obj = vm. unwrap_or_none ( zelf. obj . clone ( ) . map ( |( o, _) | o) ) ;
182
- PyType :: call ( zelf. class ( ) , ( zelf. typ . clone ( ) , obj) . into_args ( vm) , vm)
212
+ let ( obj, typ) = {
213
+ let lock = zelf. inner . read ( ) ;
214
+ let obj = lock. obj . as_ref ( ) . map ( |( o, _) | o. to_owned ( ) ) ;
215
+ let typ = lock. typ . clone ( ) ;
216
+ ( obj, typ)
217
+ } ;
218
+ let obj = vm. unwrap_or_none ( obj) ;
219
+ PyType :: call ( zelf. class ( ) , ( typ, obj) . into_args ( vm) , vm)
183
220
}
184
221
}
185
222
}
186
223
187
224
impl Representable for PySuper {
188
225
#[ inline]
189
226
fn repr_str ( zelf : & Py < Self > , _vm : & VirtualMachine ) -> PyResult < String > {
190
- let type_name = & zelf. typ . name ( ) ;
191
- let repr = match zelf. obj {
227
+ let type_name = zelf. inner . read ( ) . typ . name ( ) . to_owned ( ) ;
228
+ let obj = zelf. inner . read ( ) . obj . clone ( ) ;
229
+ let repr = match obj {
192
230
Some ( ( _, ref ty) ) => {
193
- format ! ( "<super: <class '{}'>, <{} object>>" , type_name, ty. name( ) )
231
+ format ! ( "<super: <class '{}'>, <{} object>>" , & type_name, ty. name( ) )
194
232
}
195
233
None => format ! ( "<super: <class '{type_name}'>, NULL>" ) ,
196
234
} ;
0 commit comments