@@ -22,6 +22,7 @@ pub struct PyClass {
22
22
pub name : String ,
23
23
pub mro : Vec < PyClassRef > ,
24
24
pub subclasses : RefCell < Vec < PyWeak > > ,
25
+ pub attributes : RefCell < PyAttributes > ,
25
26
}
26
27
27
28
impl fmt:: Display for PyClass {
@@ -149,6 +150,25 @@ impl PyClassRef {
149
150
}
150
151
}
151
152
153
+ fn set_attr (
154
+ self ,
155
+ attr_name : PyStringRef ,
156
+ value : PyObjectRef ,
157
+ vm : & VirtualMachine ,
158
+ ) -> PyResult < ( ) > {
159
+ if let Some ( attr) = class_get_attr ( & self . type_pyref ( ) , & attr_name. value ) {
160
+ if let Some ( descriptor) = class_get_attr ( & attr. type_pyref ( ) , "__set__" ) {
161
+ vm. invoke ( descriptor, vec ! [ attr, self . into_object( ) , value] ) ?;
162
+ return Ok ( ( ) ) ;
163
+ }
164
+ }
165
+
166
+ self . attributes
167
+ . borrow_mut ( )
168
+ . insert ( attr_name. to_string ( ) , value) ;
169
+ Ok ( ( ) )
170
+ }
171
+
152
172
fn subclasses ( self , _vm : & VirtualMachine ) -> PyList {
153
173
let mut subclasses = self . subclasses . borrow_mut ( ) ;
154
174
subclasses. retain ( |x| x. upgrade ( ) . is_some ( ) ) ;
@@ -181,6 +201,7 @@ pub fn init(ctx: &PyContext) {
181
201
"__repr__" => ctx. new_rustfunc( PyClassRef :: repr) ,
182
202
"__prepare__" => ctx. new_rustfunc( PyClassRef :: prepare) ,
183
203
"__getattribute__" => ctx. new_rustfunc( PyClassRef :: getattribute) ,
204
+ "__setattr__" => ctx. new_rustfunc( PyClassRef :: set_attr) ,
184
205
"__subclasses__" => ctx. new_rustfunc( PyClassRef :: subclasses) ,
185
206
"__getattribute__" => ctx. new_rustfunc( PyClassRef :: getattribute) ,
186
207
"__instancecheck__" => ctx. new_rustfunc( PyClassRef :: instance_check) ,
@@ -260,45 +281,26 @@ pub fn type_call(class: PyClassRef, args: Args, kwargs: KwArgs, vm: &VirtualMach
260
281
Ok ( obj)
261
282
}
262
283
263
- // Very private helper function for class_get_attr
264
- fn class_get_attr_in_dict ( class : & PyClassRef , attr_name : & str ) -> Option < PyObjectRef > {
265
- if let Some ( ref dict) = class. as_object ( ) . dict {
266
- dict. borrow ( ) . get ( attr_name) . cloned ( )
267
- } else {
268
- panic ! ( "Only classes should be in MRO!" ) ;
269
- }
270
- }
271
-
272
- // Very private helper function for class_has_attr
273
- fn class_has_attr_in_dict ( class : & PyClassRef , attr_name : & str ) -> bool {
274
- if let Some ( ref dict) = class. as_object ( ) . dict {
275
- dict. borrow ( ) . contains_key ( attr_name)
276
- } else {
277
- panic ! ( "All classes are expected to have dicts!" ) ;
278
- }
279
- }
280
-
281
284
// This is the internal get_attr implementation for fast lookup on a class.
282
- pub fn class_get_attr ( zelf : & PyClassRef , attr_name : & str ) -> Option < PyObjectRef > {
283
- let mro = & zelf. mro ;
284
- if let Some ( item) = class_get_attr_in_dict ( zelf, attr_name) {
285
+ pub fn class_get_attr ( class : & PyClassRef , attr_name : & str ) -> Option < PyObjectRef > {
286
+ if let Some ( item) = class. attributes . borrow ( ) . get ( attr_name) . cloned ( ) {
285
287
return Some ( item) ;
286
288
}
287
- for class in mro {
288
- if let Some ( item) = class_get_attr_in_dict ( class, attr_name) {
289
+ for class in & class . mro {
290
+ if let Some ( item) = class. attributes . borrow ( ) . get ( attr_name) . cloned ( ) {
289
291
return Some ( item) ;
290
292
}
291
293
}
292
294
None
293
295
}
294
296
295
297
// This is the internal has_attr implementation for fast lookup on a class.
296
- pub fn class_has_attr ( zelf : & PyClassRef , attr_name : & str ) -> bool {
297
- class_has_attr_in_dict ( zelf , attr_name)
298
- || zelf
298
+ pub fn class_has_attr ( class : & PyClassRef , attr_name : & str ) -> bool {
299
+ class . attributes . borrow ( ) . contains_key ( attr_name)
300
+ || class
299
301
. mro
300
302
. iter ( )
301
- . any ( |d| class_has_attr_in_dict ( d , attr_name) )
303
+ . any ( |c| c . attributes . borrow ( ) . contains_key ( attr_name) )
302
304
}
303
305
304
306
pub fn get_attributes ( cls : PyClassRef ) -> PyAttributes {
@@ -309,10 +311,8 @@ pub fn get_attributes(cls: PyClassRef) -> PyAttributes {
309
311
base_classes. reverse ( ) ;
310
312
311
313
for bc in base_classes {
312
- if let Some ( ref dict) = & bc. as_object ( ) . dict {
313
- for ( name, value) in dict. borrow ( ) . iter ( ) {
314
- attributes. insert ( name. to_string ( ) , value. clone ( ) ) ;
315
- }
314
+ for ( name, value) in bc. attributes . borrow ( ) . iter ( ) {
315
+ attributes. insert ( name. to_string ( ) , value. clone ( ) ) ;
316
316
}
317
317
}
318
318
@@ -374,8 +374,9 @@ pub fn new(
374
374
name : String :: from ( name) ,
375
375
mro,
376
376
subclasses : RefCell :: new ( vec ! [ ] ) ,
377
+ attributes : RefCell :: new ( dict) ,
377
378
} ,
378
- dict : Some ( RefCell :: new ( dict ) ) ,
379
+ dict : None ,
379
380
typ,
380
381
}
381
382
. into_ref ( ) ;
0 commit comments