@@ -618,23 +618,28 @@ impl VirtualMachine {
618
618
objbool:: boolval ( self , ret)
619
619
}
620
620
621
- pub fn call_get_descriptor ( & self , attr : PyObjectRef , obj : PyObjectRef ) -> PyResult {
622
- let attr_class = attr . class ( ) ;
623
- let slots = attr_class . slots . borrow ( ) ;
624
- if let Some ( descr_get) = slots. borrow ( ) . descr_get . as_ref ( ) {
621
+ pub fn call_get_descriptor ( & self , descr : PyObjectRef , obj : PyObjectRef ) -> Option < PyResult > {
622
+ let descr_class = descr . class ( ) ;
623
+ let slots = descr_class . slots . borrow ( ) ;
624
+ Some ( if let Some ( descr_get) = slots. borrow ( ) . descr_get . as_ref ( ) {
625
625
let cls = obj. class ( ) ;
626
626
descr_get (
627
627
self ,
628
- attr ,
628
+ descr ,
629
629
Some ( obj. clone ( ) ) ,
630
630
OptionalArg :: Present ( cls. into_object ( ) ) ,
631
631
)
632
- } else if let Some ( ref descriptor) = attr_class . get_attr ( "__get__" ) {
632
+ } else if let Some ( ref descriptor) = descr_class . get_attr ( "__get__" ) {
633
633
let cls = obj. class ( ) ;
634
- self . invoke ( descriptor, vec ! [ attr , obj. clone( ) , cls. into_object( ) ] )
634
+ self . invoke ( descriptor, vec ! [ descr , obj. clone( ) , cls. into_object( ) ] )
635
635
} else {
636
- Ok ( attr)
637
- }
636
+ return None ;
637
+ } )
638
+ }
639
+
640
+ pub fn call_if_get_descriptor ( & self , attr : PyObjectRef , obj : PyObjectRef ) -> PyResult {
641
+ self . call_get_descriptor ( attr. clone ( ) , obj)
642
+ . unwrap_or ( Ok ( attr) )
638
643
}
639
644
640
645
pub fn call_method < T > ( & self , obj : & PyObjectRef , method_name : & str , args : T ) -> PyResult
@@ -654,7 +659,7 @@ impl VirtualMachine {
654
659
method_name,
655
660
func
656
661
) ;
657
- let wrapped = self . call_get_descriptor ( func, obj. clone ( ) ) ?;
662
+ let wrapped = self . call_if_get_descriptor ( func, obj. clone ( ) ) ?;
658
663
self . invoke ( & wrapped, args)
659
664
}
660
665
None => Err ( self . new_type_error ( format ! ( "Unsupported method: {}" , method_name) ) ) ,
@@ -787,7 +792,7 @@ impl VirtualMachine {
787
792
{
788
793
let cls = obj. class ( ) ;
789
794
match cls. get_attr ( method_name) {
790
- Some ( method) => self . call_get_descriptor ( method, obj. clone ( ) ) ,
795
+ Some ( method) => self . call_if_get_descriptor ( method, obj. clone ( ) ) ,
791
796
None => Err ( self . new_type_error ( err_msg ( ) ) ) ,
792
797
}
793
798
}
@@ -796,7 +801,7 @@ impl VirtualMachine {
796
801
pub fn get_method ( & self , obj : PyObjectRef , method_name : & str ) -> Option < PyResult > {
797
802
let cls = obj. class ( ) ;
798
803
let method = cls. get_attr ( method_name) ?;
799
- Some ( self . call_get_descriptor ( method, obj. clone ( ) ) )
804
+ Some ( self . call_if_get_descriptor ( method, obj. clone ( ) ) )
800
805
}
801
806
802
807
/// Calls a method on `obj` passing `arg`, if the method exists.
@@ -848,6 +853,7 @@ impl VirtualMachine {
848
853
} )
849
854
}
850
855
856
+ /// CPython _PyObject_GenericGetAttrWithDict
851
857
pub fn generic_getattribute (
852
858
& self ,
853
859
obj : PyObjectRef ,
@@ -859,10 +865,8 @@ impl VirtualMachine {
859
865
if let Some ( attr) = cls. get_attr ( & name) {
860
866
let attr_class = attr. class ( ) ;
861
867
if attr_class. has_attr ( "__set__" ) {
862
- if let Some ( descriptor) = attr_class. get_attr ( "__get__" ) {
863
- return self
864
- . invoke ( & descriptor, vec ! [ attr, obj, cls. into_object( ) ] )
865
- . map ( Some ) ;
868
+ if let Some ( r) = self . call_get_descriptor ( attr, obj. clone ( ) ) {
869
+ return r. map ( Some ) ;
866
870
}
867
871
}
868
872
}
@@ -876,7 +880,7 @@ impl VirtualMachine {
876
880
if let Some ( obj_attr) = attr {
877
881
Ok ( Some ( obj_attr) )
878
882
} else if let Some ( attr) = cls. get_attr ( & name) {
879
- self . call_get_descriptor ( attr, obj) . map ( Some )
883
+ self . call_if_get_descriptor ( attr, obj) . map ( Some )
880
884
} else if let Some ( getter) = cls. get_attr ( "__getattr__" ) {
881
885
self . invoke ( & getter, vec ! [ obj, name_str. into_object( ) ] )
882
886
. map ( Some )
0 commit comments