@@ -17,7 +17,7 @@ use crate::pyobject::{
1717 BorrowValue , Either , IdProtocol , PyAttributes , PyClassImpl , PyContext , PyIterable , PyLease ,
1818 PyObjectRef , PyRef , PyResult , PyValue , TryFromObject , TypeProtocol ,
1919} ;
20- use crate :: slots:: { self , Callable , PyTpFlags , PyTypeSlots } ;
20+ use crate :: slots:: { self , Callable , PyTpFlags , PyTypeSlots , SlotGetattro } ;
2121use crate :: vm:: VirtualMachine ;
2222use itertools:: Itertools ;
2323use std:: ops:: Deref ;
@@ -165,7 +165,14 @@ impl PyTypeRef {
165165 } as _ ;
166166 self . slots . cmp . store ( Some ( func) )
167167 }
168- _ => ( ) ,
168+ "__getattribute__" => {
169+ let func: slots:: GetattroFunc = |zelf, name, vm| {
170+ let magic = get_class_magic ( & zelf, "__getattribute__" ) ;
171+ vm. invoke ( & magic, vec ! [ zelf, name. into_object( ) ] )
172+ } ;
173+ self . slots . getattro . store ( Some ( func) )
174+ }
175+ _ => { }
169176 }
170177 }
171178}
@@ -180,7 +187,7 @@ fn get_class_magic(zelf: &PyObjectRef, name: &str) -> PyObjectRef {
180187 // attrs.get(name).unwrap().clone()
181188}
182189
183- #[ pyimpl( with( Callable ) , flags( BASETYPE ) ) ]
190+ #[ pyimpl( with( SlotGetattro , Callable ) , flags( BASETYPE ) ) ]
184191impl PyType {
185192 #[ pyproperty( name = "__mro__" ) ]
186193 fn get_mro ( zelf : PyRef < Self > ) -> PyTuple {
@@ -266,53 +273,6 @@ impl PyType {
266273 vm. ctx . new_dict ( )
267274 }
268275
269- #[ pymethod( magic) ]
270- fn getattribute ( zelf : PyRef < Self > , name_ref : PyStrRef , vm : & VirtualMachine ) -> PyResult {
271- let name = name_ref. borrow_value ( ) ;
272- vm_trace ! ( "type.__getattribute__({:?}, {:?})" , zelf, name) ;
273- let mcl = zelf. lease_class ( ) ;
274-
275- if let Some ( attr) = mcl. get_attr ( & name) {
276- let attr_class = attr. lease_class ( ) ;
277- if attr_class. has_attr ( "__set__" ) {
278- if let Some ( ref descr_get) =
279- PyLease :: into_pyref ( attr_class) . first_in_mro ( |cls| cls. slots . descr_get . load ( ) )
280- {
281- let mcl = PyLease :: into_pyref ( mcl) . into_object ( ) ;
282- return descr_get ( attr, Some ( zelf. into_object ( ) ) , Some ( mcl) , vm) ;
283- }
284- }
285- }
286-
287- if let Some ( attr) = zelf. get_attr ( & name) {
288- let attr_class = attr. class ( ) ;
289- if let Some ( ref descr_get) = attr_class. first_in_mro ( |cls| cls. slots . descr_get . load ( ) ) {
290- drop ( mcl) ;
291- return descr_get ( attr, None , Some ( zelf. into_object ( ) ) , vm) ;
292- }
293- }
294-
295- if let Some ( cls_attr) = zelf. get_attr ( & name) {
296- Ok ( cls_attr)
297- } else if let Some ( attr) = mcl. get_attr ( & name) {
298- drop ( mcl) ;
299- vm. call_if_get_descriptor ( attr, zelf. into_object ( ) )
300- } else if let Some ( ref getter) = zelf. get_attr ( "__getattr__" ) {
301- vm. invoke (
302- getter,
303- vec ! [
304- PyLease :: into_pyref( mcl) . into_object( ) ,
305- name_ref. into_object( ) ,
306- ] ,
307- )
308- } else {
309- Err ( vm. new_attribute_error ( format ! (
310- "type object '{}' has no attribute '{}'" ,
311- zelf, name
312- ) ) )
313- }
314- }
315-
316276 #[ pymethod( magic) ]
317277 fn setattr (
318278 zelf : PyRef < Self > ,
@@ -510,6 +470,58 @@ impl PyType {
510470 }
511471}
512472
473+ impl SlotGetattro for PyType {
474+ fn getattro ( zelf : PyRef < Self > , name_ref : PyStrRef , vm : & VirtualMachine ) -> PyResult {
475+ let name = name_ref. borrow_value ( ) ;
476+ vm_trace ! ( "type.__getattribute__({:?}, {:?})" , zelf, name) ;
477+ let mcl = zelf. lease_class ( ) ;
478+
479+ let mcl_attr = mcl. get_attr ( name) ;
480+
481+ if let Some ( ref attr) = mcl_attr {
482+ let attr_class = attr. lease_class ( ) ;
483+ if attr_class. has_attr ( "__set__" ) {
484+ if let Some ( ref descr_get) =
485+ PyLease :: into_pyref ( attr_class) . first_in_mro ( |cls| cls. slots . descr_get . load ( ) )
486+ {
487+ let mcl = PyLease :: into_pyref ( mcl) . into_object ( ) ;
488+ return descr_get ( attr. clone ( ) , Some ( zelf. into_object ( ) ) , Some ( mcl) , vm) ;
489+ }
490+ }
491+ }
492+
493+ let zelf_attr = zelf. get_attr ( name) ;
494+
495+ if let Some ( ref attr) = zelf_attr {
496+ let attr_class = attr. class ( ) ;
497+ if let Some ( descr_get) = attr_class. first_in_mro ( |cls| cls. slots . descr_get . load ( ) ) {
498+ drop ( mcl) ;
499+ return descr_get ( attr. clone ( ) , None , Some ( zelf. into_object ( ) ) , vm) ;
500+ }
501+ }
502+
503+ if let Some ( cls_attr) = zelf_attr {
504+ Ok ( cls_attr)
505+ } else if let Some ( attr) = mcl_attr {
506+ drop ( mcl) ;
507+ vm. call_if_get_descriptor ( attr, zelf. into_object ( ) )
508+ } else if let Some ( ref getter) = zelf. get_attr ( "__getattr__" ) {
509+ vm. invoke (
510+ getter,
511+ vec ! [
512+ PyLease :: into_pyref( mcl) . into_object( ) ,
513+ name_ref. into_object( ) ,
514+ ] ,
515+ )
516+ } else {
517+ Err ( vm. new_attribute_error ( format ! (
518+ "type object '{}' has no attribute '{}'" ,
519+ zelf, name
520+ ) ) )
521+ }
522+ }
523+ }
524+
513525impl Callable for PyType {
514526 fn call ( zelf : & PyRef < Self > , args : PyFuncArgs , vm : & VirtualMachine ) -> PyResult {
515527 vm_trace ! ( "type_call: {:?}" , zelf) ;
0 commit comments